2 * Copyright (C) 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 * Copyright (C) 2012 Igalia, S.L.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "BytecodeGenerator.h"
34 #include "Interpreter.h"
35 #include "JSActivation.h"
36 #include "JSFunction.h"
37 #include "JSNameScope.h"
38 #include "LowLevelInterpreter.h"
39 #include "Operations.h"
41 #include "StackAlignment.h"
42 #include "StrongInlines.h"
43 #include "UnlinkedCodeBlock.h"
44 #include "UnlinkedInstructionStream.h"
45 #include <wtf/StdLibExtras.h>
46 #include <wtf/text/WTFString.h>
52 void Label::setLocation(unsigned location)
54 m_location = location;
56 unsigned size = m_unresolvedJumps.size();
57 for (unsigned i = 0; i < size; ++i)
58 m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
61 ParserError BytecodeGenerator::generate()
63 SamplingRegion samplingRegion("Bytecode Generation");
65 m_codeBlock->setThisRegister(m_thisRegister.virtualRegister());
66 for (size_t i = 0; i < m_deconstructedParameters.size(); i++) {
67 auto& entry = m_deconstructedParameters[i];
68 entry.second->bindValue(*this, entry.first.get());
71 m_scopeNode->emitBytecode(*this);
73 m_staticPropertyAnalyzer.kill();
75 for (unsigned i = 0; i < m_tryRanges.size(); ++i) {
76 TryRange& range = m_tryRanges[i];
77 int start = range.start->bind();
78 int end = range.end->bind();
80 // This will happen for empty try blocks and for some cases of finally blocks:
92 // The return will pop scopes to execute the outer finally block. But this includes
93 // popping the try context for the inner try. The try context is live in the fall-through
94 // part of the finally block not because we will emit a handler that overlaps the finally,
95 // but because we haven't yet had a chance to plant the catch target. Then when we finish
96 // emitting code for the outer finally block, we repush the try contex, this time with a
97 // new start index. But that means that the start index for the try range corresponding
98 // to the inner-finally-following-the-return (marked as "*HERE*" above) will be greater
99 // than the end index of the try block. This is harmless since end < start handlers will
100 // never get matched in our logic, but we do the runtime a favor and choose to not emit
101 // such handlers at all.
105 ASSERT(range.tryData->targetScopeDepth != UINT_MAX);
106 UnlinkedHandlerInfo info = {
107 static_cast<uint32_t>(start), static_cast<uint32_t>(end),
108 static_cast<uint32_t>(range.tryData->target->bind()),
109 range.tryData->targetScopeDepth
111 m_codeBlock->addExceptionHandler(info);
114 m_codeBlock->setInstructions(std::make_unique<UnlinkedInstructionStream>(m_instructions));
116 m_codeBlock->shrinkToFit();
118 if (m_expressionTooDeep)
119 return ParserError(ParserError::OutOfMemory);
120 return ParserError(ParserError::ErrorNone);
123 bool BytecodeGenerator::addVar(
124 const Identifier& ident, ConstantMode constantMode, WatchMode watchMode, RegisterID*& r0)
126 ASSERT(static_cast<size_t>(m_codeBlock->m_numVars) == m_calleeRegisters.size());
128 ConcurrentJITLocker locker(symbolTable().m_lock);
129 int index = virtualRegisterForLocal(m_calleeRegisters.size()).offset();
130 SymbolTableEntry newEntry(index, constantMode == IsConstant ? ReadOnly : 0);
131 SymbolTable::Map::AddResult result = symbolTable().add(locker, ident.impl(), newEntry);
133 if (!result.isNewEntry) {
134 r0 = ®isterFor(result.iterator->value.getIndex());
138 if (watchMode == IsWatchable) {
139 while (m_watchableVariables.size() < static_cast<size_t>(m_codeBlock->m_numVars))
140 m_watchableVariables.append(Identifier());
141 m_watchableVariables.append(ident);
146 ASSERT(watchMode == NotWatchable || static_cast<size_t>(m_codeBlock->m_numVars) == m_watchableVariables.size());
151 void BytecodeGenerator::preserveLastVar()
153 if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
154 m_lastVar = &m_calleeRegisters.last();
157 BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
158 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
159 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
161 , m_scopeNode(programNode)
162 , m_codeBlock(vm, codeBlock)
163 , m_thisRegister(CallFrame::thisArgumentOffset())
164 , m_activationRegister(0)
165 , m_emptyValueRegister(0)
166 , m_globalObjectRegister(0)
168 , m_localScopeDepth(0)
169 , m_codeType(GlobalCode)
170 , m_nextConstantOffset(0)
171 , m_globalConstantIndex(0)
172 , m_firstLazyFunction(0)
173 , m_lastLazyFunction(0)
174 , m_staticPropertyAnalyzer(&m_instructions)
176 , m_lastOpcodeID(op_end)
178 , m_lastOpcodePosition(0)
180 , m_usesExceptions(false)
181 , m_expressionTooDeep(false)
183 m_codeBlock->setNumParameters(1); // Allocate space for "this"
185 emitOpcode(op_enter);
187 const VarStack& varStack = programNode->varStack();
188 const FunctionStack& functionStack = programNode->functionStack();
190 for (size_t i = 0; i < functionStack.size(); ++i) {
191 FunctionBodyNode* function = functionStack[i];
192 UnlinkedFunctionExecutable* unlinkedFunction = makeFunction(function);
193 codeBlock->addFunctionDeclaration(*m_vm, function->ident(), unlinkedFunction);
196 for (size_t i = 0; i < varStack.size(); ++i)
197 codeBlock->addVariableDeclaration(varStack[i].first, !!(varStack[i].second & DeclarationStacks::IsConstant));
201 BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
202 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
203 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
204 , m_symbolTable(codeBlock->symbolTable())
205 , m_scopeNode(functionBody)
206 , m_codeBlock(vm, codeBlock)
207 , m_activationRegister(0)
208 , m_emptyValueRegister(0)
209 , m_globalObjectRegister(0)
211 , m_localScopeDepth(0)
212 , m_codeType(FunctionCode)
213 , m_nextConstantOffset(0)
214 , m_globalConstantIndex(0)
215 , m_firstLazyFunction(0)
216 , m_lastLazyFunction(0)
217 , m_staticPropertyAnalyzer(&m_instructions)
219 , m_lastOpcodeID(op_end)
221 , m_lastOpcodePosition(0)
223 , m_usesExceptions(false)
224 , m_expressionTooDeep(false)
226 m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
227 Vector<Identifier> boundParameterProperties;
228 FunctionParameters& parameters = *functionBody->parameters();
229 for (size_t i = 0; i < parameters.size(); i++) {
230 auto pattern = parameters.at(i);
231 if (pattern->isBindingNode())
233 pattern->collectBoundIdentifiers(boundParameterProperties);
236 m_symbolTable->setParameterCountIncludingThis(functionBody->parameters()->size() + 1);
238 emitOpcode(op_enter);
239 if (m_codeBlock->needsFullScopeChain() || m_shouldEmitDebugHooks) {
240 m_activationRegister = addVar();
241 emitInitLazyRegister(m_activationRegister);
242 m_codeBlock->setActivationRegister(m_activationRegister->virtualRegister());
245 m_symbolTable->setCaptureStart(virtualRegisterForLocal(m_codeBlock->m_numVars).offset());
247 if (functionBody->usesArguments() || codeBlock->usesEval()) { // May reify arguments object.
248 RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
249 RegisterID* argumentsRegister = addVar(propertyNames().arguments, IsVariable, NotWatchable); // Can be changed by assigning to 'arguments'.
251 // We can save a little space by hard-coding the knowledge that the two
252 // 'arguments' values are stored in consecutive registers, and storing
253 // only the index of the assignable one.
254 codeBlock->setArgumentsRegister(argumentsRegister->virtualRegister());
255 ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->virtualRegister() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
257 emitInitLazyRegister(argumentsRegister);
258 emitInitLazyRegister(unmodifiedArgumentsRegister);
260 if (shouldTearOffArgumentsEagerly()) {
261 emitOpcode(op_create_arguments);
262 instructions().append(argumentsRegister->index());
266 bool shouldCaptureAllTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval();
268 bool capturesAnyArgumentByName = false;
269 Vector<RegisterID*, 0, UnsafeVectorOverflow> capturedArguments;
270 if (functionBody->hasCapturedVariables() || shouldCaptureAllTheThings) {
271 FunctionParameters& parameters = *functionBody->parameters();
272 capturedArguments.resize(parameters.size());
273 for (size_t i = 0; i < parameters.size(); ++i) {
274 capturedArguments[i] = 0;
275 auto pattern = parameters.at(i);
276 if (!pattern->isBindingNode())
278 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
279 if (!functionBody->captures(ident) && !shouldCaptureAllTheThings)
281 capturesAnyArgumentByName = true;
282 capturedArguments[i] = addVar();
286 if (capturesAnyArgumentByName && !shouldTearOffArgumentsEagerly()) {
287 size_t parameterCount = m_symbolTable->parameterCount();
288 auto slowArguments = std::make_unique<SlowArgument[]>(parameterCount);
289 for (size_t i = 0; i < parameterCount; ++i) {
290 if (!capturedArguments[i]) {
291 ASSERT(slowArguments[i].status == SlowArgument::Normal);
292 slowArguments[i].index = CallFrame::argumentOffset(i);
295 slowArguments[i].status = SlowArgument::Captured;
296 slowArguments[i].index = capturedArguments[i]->index();
298 m_symbolTable->setSlowArguments(std::move(slowArguments));
301 RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var.
303 const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
304 const DeclarationStacks::VarStack& varStack = functionBody->varStack();
307 // Captured variables and functions go first so that activations don't have
308 // to step over the non-captured locals to mark them.
309 if (functionBody->hasCapturedVariables()) {
310 for (size_t i = 0; i < boundParameterProperties.size(); i++) {
311 const Identifier& ident = boundParameterProperties[i];
312 if (functionBody->captures(ident))
313 addVar(ident, IsVariable, IsWatchable);
315 for (size_t i = 0; i < functionStack.size(); ++i) {
316 FunctionBodyNode* function = functionStack[i];
317 const Identifier& ident = function->ident();
318 if (functionBody->captures(ident)) {
319 m_functions.add(ident.impl());
320 emitNewFunction(addVar(ident, IsVariable, IsWatchable), IsCaptured, function);
323 for (size_t i = 0; i < varStack.size(); ++i) {
324 const Identifier& ident = varStack[i].first;
325 if (functionBody->captures(ident))
326 addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, IsWatchable);
330 m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset());
332 bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
333 m_firstLazyFunction = codeBlock->m_numVars;
334 for (size_t i = 0; i < functionStack.size(); ++i) {
335 FunctionBodyNode* function = functionStack[i];
336 const Identifier& ident = function->ident();
337 if (!functionBody->captures(ident)) {
338 m_functions.add(ident.impl());
339 RefPtr<RegisterID> reg = addVar(ident, IsVariable, NotWatchable);
340 // Don't lazily create functions that override the name 'arguments'
341 // as this would complicate lazy instantiation of actual arguments.
342 if (!canLazilyCreateFunctions || ident == propertyNames().arguments)
343 emitNewFunction(reg.get(), NotCaptured, function);
345 emitInitLazyRegister(reg.get());
346 m_lazyFunctions.set(reg->virtualRegister().toLocal(), function);
350 m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
351 for (size_t i = 0; i < boundParameterProperties.size(); i++) {
352 const Identifier& ident = boundParameterProperties[i];
353 if (!functionBody->captures(ident))
354 addVar(ident, IsVariable, IsWatchable);
356 for (size_t i = 0; i < varStack.size(); ++i) {
357 const Identifier& ident = varStack[i].first;
358 if (!functionBody->captures(ident))
359 addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, NotWatchable);
362 if (shouldCaptureAllTheThings)
363 m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset());
365 if (m_symbolTable->captureCount())
366 emitOpcode(op_touch_entry);
368 m_parameters.grow(parameters.size() + 1); // reserve space for "this"
370 // Add "this" as a parameter
371 int nextParameterIndex = CallFrame::thisArgumentOffset();
372 m_thisRegister.setIndex(nextParameterIndex++);
373 m_codeBlock->addParameter();
374 for (size_t i = 0; i < parameters.size(); ++i, ++nextParameterIndex) {
375 int index = nextParameterIndex;
376 auto pattern = parameters.at(i);
377 if (!pattern->isBindingNode()) {
378 m_codeBlock->addParameter();
379 RegisterID& parameter = registerFor(index);
380 parameter.setIndex(index);
381 m_deconstructedParameters.append(std::make_pair(¶meter, pattern));
384 auto simpleParameter = static_cast<const BindingNode*>(pattern);
385 if (capturedArguments.size() && capturedArguments[i]) {
386 ASSERT((functionBody->hasCapturedVariables() && functionBody->captures(simpleParameter->boundProperty())) || shouldCaptureAllTheThings);
387 index = capturedArguments[i]->index();
388 RegisterID original(nextParameterIndex);
389 emitMove(capturedArguments[i], &original);
391 addParameter(simpleParameter->boundProperty(), index);
395 // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration.
396 addCallee(functionBody, calleeRegister);
398 if (isConstructor()) {
399 emitCreateThis(&m_thisRegister);
400 } else if (functionBody->usesThis() || codeBlock->usesEval()) {
401 m_codeBlock->addPropertyAccessInstruction(instructions().size());
402 emitOpcode(op_to_this);
403 instructions().append(kill(&m_thisRegister));
404 instructions().append(0);
408 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
409 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
410 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
411 , m_symbolTable(codeBlock->symbolTable())
412 , m_scopeNode(evalNode)
413 , m_codeBlock(vm, codeBlock)
414 , m_thisRegister(CallFrame::thisArgumentOffset())
415 , m_activationRegister(0)
416 , m_emptyValueRegister(0)
417 , m_globalObjectRegister(0)
419 , m_localScopeDepth(0)
420 , m_codeType(EvalCode)
421 , m_nextConstantOffset(0)
422 , m_globalConstantIndex(0)
423 , m_firstLazyFunction(0)
424 , m_lastLazyFunction(0)
425 , m_staticPropertyAnalyzer(&m_instructions)
427 , m_lastOpcodeID(op_end)
429 , m_lastOpcodePosition(0)
431 , m_usesExceptions(false)
432 , m_expressionTooDeep(false)
434 m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
435 m_codeBlock->setNumParameters(1);
437 emitOpcode(op_enter);
439 const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
440 for (size_t i = 0; i < functionStack.size(); ++i)
441 m_codeBlock->addFunctionDecl(makeFunction(functionStack[i]));
443 const DeclarationStacks::VarStack& varStack = evalNode->varStack();
444 unsigned numVariables = varStack.size();
445 Vector<Identifier, 0, UnsafeVectorOverflow> variables;
446 variables.reserveCapacity(numVariables);
447 for (size_t i = 0; i < numVariables; ++i) {
448 ASSERT(varStack[i].first.impl()->isIdentifier());
449 variables.append(varStack[i].first);
451 codeBlock->adoptVariables(variables);
455 BytecodeGenerator::~BytecodeGenerator()
459 RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg)
461 emitOpcode(op_init_lazy_reg);
462 instructions().append(reg->index());
463 ASSERT(!hasWatchableVariable(reg->index()));
467 RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
469 if (!functionNameIsInScope(functionBodyNode->ident(), functionBodyNode->functionMode()))
472 if (functionNameScopeIsDynamic(m_codeBlock->usesEval(), m_codeBlock->isStrictMode()))
475 m_calleeRegister.setIndex(JSStack::Callee);
476 if (functionBodyNode->captures(functionBodyNode->ident()))
477 return emitMove(addVar(), IsCaptured, &m_calleeRegister);
479 return &m_calleeRegister;
482 void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister)
487 symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly));
490 void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex)
492 // Parameters overwrite var declarations, but not function declarations.
493 StringImpl* rep = ident.impl();
494 if (!m_functions.contains(rep)) {
495 symbolTable().set(rep, parameterIndex);
496 RegisterID& parameter = registerFor(parameterIndex);
497 parameter.setIndex(parameterIndex);
500 // To maintain the calling convention, we have to allocate unique space for
501 // each parameter, even if the parameter doesn't make it into the symbol table.
502 m_codeBlock->addParameter();
505 bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
507 if (ident != propertyNames().arguments)
510 if (!shouldOptimizeLocals())
513 SymbolTableEntry entry = symbolTable().get(ident.impl());
517 if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
523 RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
525 ASSERT(willResolveToArguments(propertyNames().arguments));
527 SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.impl());
528 ASSERT(!entry.isNull());
529 return ®isterFor(entry.getIndex());
532 RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
534 if (!reg->virtualRegister().isLocal())
537 int localVariableNumber = reg->virtualRegister().toLocal();
539 if (m_lastLazyFunction <= localVariableNumber || localVariableNumber < m_firstLazyFunction)
541 emitLazyNewFunction(reg, m_lazyFunctions.get(localVariableNumber));
545 RegisterID* BytecodeGenerator::newRegister()
547 m_calleeRegisters.append(virtualRegisterForLocal(m_calleeRegisters.size()));
548 int numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size());
549 numCalleeRegisters = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numCalleeRegisters);
550 m_codeBlock->m_numCalleeRegisters = numCalleeRegisters;
551 return &m_calleeRegisters.last();
554 RegisterID* BytecodeGenerator::newTemporary()
556 // Reclaim free register IDs.
557 while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
558 m_calleeRegisters.removeLast();
560 RegisterID* result = newRegister();
561 result->setTemporary();
565 LabelScopePtr BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
567 // Reclaim free label scopes.
568 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
569 m_labelScopes.removeLast();
571 // Allocate new label scope.
572 LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
573 m_labelScopes.append(scope);
574 return LabelScopePtr(&m_labelScopes, m_labelScopes.size() - 1);
577 PassRefPtr<Label> BytecodeGenerator::newLabel()
579 // Reclaim free label IDs.
580 while (m_labels.size() && !m_labels.last().refCount())
581 m_labels.removeLast();
583 // Allocate new label ID.
584 m_labels.append(this);
585 return &m_labels.last();
588 PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
590 unsigned newLabelIndex = instructions().size();
591 l0->setLocation(newLabelIndex);
593 if (m_codeBlock->numberOfJumpTargets()) {
594 unsigned lastLabelIndex = m_codeBlock->lastJumpTarget();
595 ASSERT(lastLabelIndex <= newLabelIndex);
596 if (newLabelIndex == lastLabelIndex) {
597 // Peephole optimizations have already been disabled by emitting the last label
602 m_codeBlock->addJumpTarget(newLabelIndex);
604 // This disables peephole optimizations when an instruction is a jump target
605 m_lastOpcodeID = op_end;
609 void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
612 size_t opcodePosition = instructions().size();
613 ASSERT(opcodePosition - m_lastOpcodePosition == opcodeLength(m_lastOpcodeID) || m_lastOpcodeID == op_end);
614 m_lastOpcodePosition = opcodePosition;
616 instructions().append(opcodeID);
617 m_lastOpcodeID = opcodeID;
620 UnlinkedArrayProfile BytecodeGenerator::newArrayProfile()
622 return m_codeBlock->addArrayProfile();
625 UnlinkedArrayAllocationProfile BytecodeGenerator::newArrayAllocationProfile()
627 return m_codeBlock->addArrayAllocationProfile();
630 UnlinkedObjectAllocationProfile BytecodeGenerator::newObjectAllocationProfile()
632 return m_codeBlock->addObjectAllocationProfile();
635 UnlinkedValueProfile BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
637 UnlinkedValueProfile result = m_codeBlock->addValueProfile();
638 emitOpcode(opcodeID);
642 void BytecodeGenerator::emitLoopHint()
644 emitOpcode(op_loop_hint);
647 void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
649 ASSERT(instructions().size() >= 4);
650 size_t size = instructions().size();
651 dstIndex = instructions().at(size - 3).u.operand;
652 src1Index = instructions().at(size - 2).u.operand;
653 src2Index = instructions().at(size - 1).u.operand;
656 void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
658 ASSERT(instructions().size() >= 3);
659 size_t size = instructions().size();
660 dstIndex = instructions().at(size - 2).u.operand;
661 srcIndex = instructions().at(size - 1).u.operand;
664 void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
666 ASSERT(instructions().size() >= 4);
667 instructions().shrink(instructions().size() - 4);
668 m_lastOpcodeID = op_end;
671 void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
673 ASSERT(instructions().size() >= 3);
674 instructions().shrink(instructions().size() - 3);
675 m_lastOpcodeID = op_end;
678 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
680 size_t begin = instructions().size();
682 instructions().append(target->bind(begin, instructions().size()));
686 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
688 if (m_lastOpcodeID == op_less) {
693 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
695 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
698 size_t begin = instructions().size();
699 emitOpcode(op_jless);
700 instructions().append(src1Index);
701 instructions().append(src2Index);
702 instructions().append(target->bind(begin, instructions().size()));
705 } else if (m_lastOpcodeID == op_lesseq) {
710 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
712 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
715 size_t begin = instructions().size();
716 emitOpcode(op_jlesseq);
717 instructions().append(src1Index);
718 instructions().append(src2Index);
719 instructions().append(target->bind(begin, instructions().size()));
722 } else if (m_lastOpcodeID == op_greater) {
727 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
729 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
732 size_t begin = instructions().size();
733 emitOpcode(op_jgreater);
734 instructions().append(src1Index);
735 instructions().append(src2Index);
736 instructions().append(target->bind(begin, instructions().size()));
739 } else if (m_lastOpcodeID == op_greatereq) {
744 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
746 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
749 size_t begin = instructions().size();
750 emitOpcode(op_jgreatereq);
751 instructions().append(src1Index);
752 instructions().append(src2Index);
753 instructions().append(target->bind(begin, instructions().size()));
756 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
760 retrieveLastUnaryOp(dstIndex, srcIndex);
762 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
765 size_t begin = instructions().size();
766 emitOpcode(op_jeq_null);
767 instructions().append(srcIndex);
768 instructions().append(target->bind(begin, instructions().size()));
771 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
775 retrieveLastUnaryOp(dstIndex, srcIndex);
777 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
780 size_t begin = instructions().size();
781 emitOpcode(op_jneq_null);
782 instructions().append(srcIndex);
783 instructions().append(target->bind(begin, instructions().size()));
788 size_t begin = instructions().size();
790 emitOpcode(op_jtrue);
791 instructions().append(cond->index());
792 instructions().append(target->bind(begin, instructions().size()));
796 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
798 if (m_lastOpcodeID == op_less && target->isForward()) {
803 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
805 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
808 size_t begin = instructions().size();
809 emitOpcode(op_jnless);
810 instructions().append(src1Index);
811 instructions().append(src2Index);
812 instructions().append(target->bind(begin, instructions().size()));
815 } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
820 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
822 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
825 size_t begin = instructions().size();
826 emitOpcode(op_jnlesseq);
827 instructions().append(src1Index);
828 instructions().append(src2Index);
829 instructions().append(target->bind(begin, instructions().size()));
832 } else if (m_lastOpcodeID == op_greater && target->isForward()) {
837 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
839 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
842 size_t begin = instructions().size();
843 emitOpcode(op_jngreater);
844 instructions().append(src1Index);
845 instructions().append(src2Index);
846 instructions().append(target->bind(begin, instructions().size()));
849 } else if (m_lastOpcodeID == op_greatereq && target->isForward()) {
854 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
856 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
859 size_t begin = instructions().size();
860 emitOpcode(op_jngreatereq);
861 instructions().append(src1Index);
862 instructions().append(src2Index);
863 instructions().append(target->bind(begin, instructions().size()));
866 } else if (m_lastOpcodeID == op_not) {
870 retrieveLastUnaryOp(dstIndex, srcIndex);
872 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
875 size_t begin = instructions().size();
876 emitOpcode(op_jtrue);
877 instructions().append(srcIndex);
878 instructions().append(target->bind(begin, instructions().size()));
881 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
885 retrieveLastUnaryOp(dstIndex, srcIndex);
887 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
890 size_t begin = instructions().size();
891 emitOpcode(op_jneq_null);
892 instructions().append(srcIndex);
893 instructions().append(target->bind(begin, instructions().size()));
896 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
900 retrieveLastUnaryOp(dstIndex, srcIndex);
902 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
905 size_t begin = instructions().size();
906 emitOpcode(op_jeq_null);
907 instructions().append(srcIndex);
908 instructions().append(target->bind(begin, instructions().size()));
913 size_t begin = instructions().size();
914 emitOpcode(op_jfalse);
915 instructions().append(cond->index());
916 instructions().append(target->bind(begin, instructions().size()));
920 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
922 size_t begin = instructions().size();
924 emitOpcode(op_jneq_ptr);
925 instructions().append(cond->index());
926 instructions().append(Special::CallFunction);
927 instructions().append(target->bind(begin, instructions().size()));
931 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
933 size_t begin = instructions().size();
935 emitOpcode(op_jneq_ptr);
936 instructions().append(cond->index());
937 instructions().append(Special::ApplyFunction);
938 instructions().append(target->bind(begin, instructions().size()));
942 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
944 StringImpl* rep = ident.impl();
945 IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
946 if (result.isNewEntry)
947 m_codeBlock->addIdentifier(ident);
949 return result.iterator->value;
952 // We can't hash JSValue(), so we use a dedicated data member to cache it.
953 RegisterID* BytecodeGenerator::addConstantEmptyValue()
955 if (!m_emptyValueRegister) {
956 int index = m_nextConstantOffset;
957 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
958 ++m_nextConstantOffset;
959 m_codeBlock->addConstant(JSValue());
960 m_emptyValueRegister = &m_constantPoolRegisters[index];
963 return m_emptyValueRegister;
966 RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
969 return addConstantEmptyValue();
971 int index = m_nextConstantOffset;
972 JSValueMap::AddResult result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
973 if (result.isNewEntry) {
974 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
975 ++m_nextConstantOffset;
976 m_codeBlock->addConstant(v);
978 index = result.iterator->value;
979 return &m_constantPoolRegisters[index];
982 unsigned BytecodeGenerator::addRegExp(RegExp* r)
984 return m_codeBlock->addRegExp(r);
987 RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, CaptureMode captureMode, RegisterID* src)
989 m_staticPropertyAnalyzer.mov(dst->index(), src->index());
991 emitOpcode(captureMode == IsCaptured ? op_captured_mov : op_mov);
992 instructions().append(dst->index());
993 instructions().append(src->index());
994 if (captureMode == IsCaptured)
995 instructions().append(watchableVariable(dst->index()));
999 RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
1001 return emitMove(dst, captureMode(dst->index()), src);
1004 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src)
1006 emitOpcode(opcodeID);
1007 instructions().append(dst->index());
1008 instructions().append(src->index());
1012 RegisterID* BytecodeGenerator::emitInc(RegisterID* srcDst)
1015 instructions().append(srcDst->index());
1019 RegisterID* BytecodeGenerator::emitDec(RegisterID* srcDst)
1022 instructions().append(srcDst->index());
1026 RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
1028 emitOpcode(opcodeID);
1029 instructions().append(dst->index());
1030 instructions().append(src1->index());
1031 instructions().append(src2->index());
1033 if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
1034 opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
1035 instructions().append(types.toInt());
1040 RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2)
1042 if (m_lastOpcodeID == op_typeof) {
1046 retrieveLastUnaryOp(dstIndex, srcIndex);
1048 if (src1->index() == dstIndex
1049 && src1->isTemporary()
1050 && m_codeBlock->isConstantRegisterIndex(src2->index())
1051 && m_codeBlock->constantRegister(src2->index()).get().isString()) {
1052 const String& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
1053 if (value == "undefined") {
1055 emitOpcode(op_is_undefined);
1056 instructions().append(dst->index());
1057 instructions().append(srcIndex);
1060 if (value == "boolean") {
1062 emitOpcode(op_is_boolean);
1063 instructions().append(dst->index());
1064 instructions().append(srcIndex);
1067 if (value == "number") {
1069 emitOpcode(op_is_number);
1070 instructions().append(dst->index());
1071 instructions().append(srcIndex);
1074 if (value == "string") {
1076 emitOpcode(op_is_string);
1077 instructions().append(dst->index());
1078 instructions().append(srcIndex);
1081 if (value == "object") {
1083 emitOpcode(op_is_object);
1084 instructions().append(dst->index());
1085 instructions().append(srcIndex);
1088 if (value == "function") {
1090 emitOpcode(op_is_function);
1091 instructions().append(dst->index());
1092 instructions().append(srcIndex);
1098 emitOpcode(opcodeID);
1099 instructions().append(dst->index());
1100 instructions().append(src1->index());
1101 instructions().append(src2->index());
1105 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
1107 return emitLoad(dst, jsBoolean(b));
1110 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
1112 // FIXME: Our hash tables won't hold infinity, so we make a new JSValue each time.
1113 // Later we can do the extra work to handle that like the other cases. They also don't
1114 // work correctly with NaN as a key.
1115 if (std::isnan(number) || number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
1116 return emitLoad(dst, jsNumber(number));
1117 JSValue& valueInMap = m_numberMap.add(number, JSValue()).iterator->value;
1119 valueInMap = jsNumber(number);
1120 return emitLoad(dst, valueInMap);
1123 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
1125 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
1127 stringInMap = jsOwnedString(vm(), identifier.string());
1128 return emitLoad(dst, JSValue(stringInMap));
1131 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
1133 RegisterID* constantID = addConstantValue(v);
1135 return emitMove(dst, constantID);
1139 RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst)
1141 if (!m_globalObjectRegister) {
1142 int index = m_nextConstantOffset;
1143 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1144 ++m_nextConstantOffset;
1145 m_codeBlock->addConstant(JSValue());
1146 m_globalObjectRegister = &m_constantPoolRegisters[index];
1147 m_codeBlock->setGlobalObjectRegister(VirtualRegister(index));
1150 emitMove(dst, m_globalObjectRegister);
1151 return m_globalObjectRegister;
1154 bool BytecodeGenerator::isCaptured(int operand)
1156 return m_symbolTable && m_symbolTable->isCaptured(operand);
1159 Local BytecodeGenerator::local(const Identifier& property)
1161 if (property == propertyNames().thisIdentifier)
1162 return Local(thisRegister(), ReadOnly, NotCaptured);
1164 if (property == propertyNames().arguments)
1165 createArgumentsIfNecessary();
1167 if (!shouldOptimizeLocals())
1170 SymbolTableEntry entry = symbolTable().get(property.impl());
1174 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex()));
1175 return Local(local, entry.getAttributes(), captureMode(local->index()));
1178 Local BytecodeGenerator::constLocal(const Identifier& property)
1180 if (m_codeType != FunctionCode)
1183 SymbolTableEntry entry = symbolTable().get(property.impl());
1187 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex()));
1188 return Local(local, entry.getAttributes(), captureMode(local->index()));
1191 void BytecodeGenerator::emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target)
1193 size_t begin = instructions().size();
1194 emitOpcode(op_check_has_instance);
1195 instructions().append(dst->index());
1196 instructions().append(value->index());
1197 instructions().append(base->index());
1198 instructions().append(target->bind(begin, instructions().size()));
1201 // Indicates the least upper bound of resolve type based on local scope. The bytecode linker
1202 // will start with this ResolveType and compute the least upper bound including intercepting scopes.
1203 ResolveType BytecodeGenerator::resolveType()
1205 if (m_localScopeDepth)
1207 if (m_symbolTable && m_symbolTable->usesNonStrictEval())
1208 return GlobalPropertyWithVarInjectionChecks;
1209 return GlobalProperty;
1212 RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Identifier& identifier)
1214 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1216 ASSERT(!m_symbolTable || !m_symbolTable->contains(identifier.impl()) || resolveType() == Dynamic);
1218 // resolve_scope dst, id, ResolveType, depth
1219 emitOpcode(op_resolve_scope);
1220 instructions().append(kill(dst));
1221 instructions().append(addConstant(identifier));
1222 instructions().append(resolveType());
1223 instructions().append(0);
1224 instructions().append(0);
1228 RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier& identifier, ResolveMode resolveMode)
1230 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1232 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
1233 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope);
1234 instructions().append(kill(dst));
1235 instructions().append(scope->index());
1236 instructions().append(addConstant(identifier));
1237 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
1238 instructions().append(0);
1239 instructions().append(0);
1240 instructions().append(profile);
1244 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode)
1246 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1248 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
1249 emitOpcode(op_put_to_scope);
1250 instructions().append(scope->index());
1251 instructions().append(addConstant(identifier));
1252 instructions().append(value->index());
1253 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
1254 instructions().append(0);
1255 instructions().append(0);
1259 RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype)
1261 emitOpcode(op_instanceof);
1262 instructions().append(dst->index());
1263 instructions().append(value->index());
1264 instructions().append(basePrototype->index());
1268 RegisterID* BytecodeGenerator::emitInitGlobalConst(const Identifier& identifier, RegisterID* value)
1270 ASSERT(m_codeType == GlobalCode);
1271 emitOpcode(op_init_global_const_nop);
1272 instructions().append(0);
1273 instructions().append(value->index());
1274 instructions().append(0);
1275 instructions().append(addConstant(identifier));
1279 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
1281 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1283 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_id);
1284 instructions().append(kill(dst));
1285 instructions().append(base->index());
1286 instructions().append(addConstant(property));
1287 instructions().append(0);
1288 instructions().append(0);
1289 instructions().append(0);
1290 instructions().append(0);
1291 instructions().append(profile);
1295 RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterID* base)
1297 emitOpcode(op_get_arguments_length);
1298 instructions().append(dst->index());
1299 ASSERT(base->virtualRegister() == m_codeBlock->argumentsRegister());
1300 instructions().append(base->index());
1301 instructions().append(addConstant(propertyNames().length));
1305 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1307 unsigned propertyIndex = addConstant(property);
1309 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1311 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1313 emitOpcode(op_put_by_id);
1314 instructions().append(base->index());
1315 instructions().append(propertyIndex);
1316 instructions().append(value->index());
1317 instructions().append(0);
1318 instructions().append(0);
1319 instructions().append(0);
1320 instructions().append(0);
1321 instructions().append(0);
1325 RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1327 unsigned propertyIndex = addConstant(property);
1329 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1331 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1333 emitOpcode(op_put_by_id);
1334 instructions().append(base->index());
1335 instructions().append(propertyIndex);
1336 instructions().append(value->index());
1337 instructions().append(0);
1338 instructions().append(0);
1339 instructions().append(0);
1340 instructions().append(0);
1341 instructions().append(
1342 property != m_vm->propertyNames->underscoreProto
1343 && PropertyName(property).asIndex() == PropertyName::NotAnIndex);
1347 void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter)
1349 unsigned propertyIndex = addConstant(property);
1351 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1353 emitOpcode(op_put_getter_setter);
1354 instructions().append(base->index());
1355 instructions().append(propertyIndex);
1356 instructions().append(getter->index());
1357 instructions().append(setter->index());
1360 RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
1362 emitOpcode(op_del_by_id);
1363 instructions().append(dst->index());
1364 instructions().append(base->index());
1365 instructions().append(addConstant(property));
1369 RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1371 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1372 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_argument_by_val);
1373 instructions().append(kill(dst));
1374 ASSERT(base->virtualRegister() == m_codeBlock->argumentsRegister());
1375 instructions().append(base->index());
1376 instructions().append(property->index());
1377 instructions().append(arrayProfile);
1378 instructions().append(profile);
1382 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1384 for (size_t i = m_forInContextStack.size(); i > 0; i--) {
1385 ForInContext& context = m_forInContextStack[i - 1];
1386 if (context.propertyRegister == property) {
1387 emitOpcode(op_get_by_pname);
1388 instructions().append(dst->index());
1389 instructions().append(base->index());
1390 instructions().append(property->index());
1391 instructions().append(context.expectedSubscriptRegister->index());
1392 instructions().append(context.iterRegister->index());
1393 instructions().append(context.indexRegister->index());
1397 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1398 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val);
1399 instructions().append(kill(dst));
1400 instructions().append(base->index());
1401 instructions().append(property->index());
1402 instructions().append(arrayProfile);
1403 instructions().append(profile);
1407 RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1409 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1410 emitOpcode(op_put_by_val);
1411 instructions().append(base->index());
1412 instructions().append(property->index());
1413 instructions().append(value->index());
1414 instructions().append(arrayProfile);
1418 RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1420 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1421 emitOpcode(op_put_by_val_direct);
1422 instructions().append(base->index());
1423 instructions().append(property->index());
1424 instructions().append(value->index());
1425 instructions().append(arrayProfile);
1429 RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1431 emitOpcode(op_del_by_val);
1432 instructions().append(dst->index());
1433 instructions().append(base->index());
1434 instructions().append(property->index());
1438 RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1440 emitOpcode(op_put_by_index);
1441 instructions().append(base->index());
1442 instructions().append(index);
1443 instructions().append(value->index());
1447 RegisterID* BytecodeGenerator::emitCreateThis(RegisterID* dst)
1449 RefPtr<RegisterID> func = newTemporary();
1451 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1452 emitOpcode(op_get_callee);
1453 instructions().append(func->index());
1454 instructions().append(0);
1456 size_t begin = instructions().size();
1457 m_staticPropertyAnalyzer.createThis(m_thisRegister.index(), begin + 3);
1459 emitOpcode(op_create_this);
1460 instructions().append(m_thisRegister.index());
1461 instructions().append(func->index());
1462 instructions().append(0);
1466 RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
1468 size_t begin = instructions().size();
1469 m_staticPropertyAnalyzer.newObject(dst->index(), begin + 2);
1471 emitOpcode(op_new_object);
1472 instructions().append(dst->index());
1473 instructions().append(0);
1474 instructions().append(newObjectAllocationProfile());
1478 unsigned BytecodeGenerator::addConstantBuffer(unsigned length)
1480 return m_codeBlock->addConstantBuffer(length);
1483 JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
1485 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
1487 stringInMap = jsString(vm(), identifier.string());
1488 addConstantValue(stringInMap);
1493 RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length)
1495 #if !ASSERT_DISABLED
1496 unsigned checkLength = 0;
1498 bool hadVariableExpression = false;
1500 for (ElementNode* n = elements; n; n = n->next()) {
1501 if (!n->value()->isConstant()) {
1502 hadVariableExpression = true;
1507 #if !ASSERT_DISABLED
1511 if (!hadVariableExpression) {
1512 ASSERT(length == checkLength);
1513 unsigned constantBufferIndex = addConstantBuffer(length);
1514 JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex).data();
1516 for (ElementNode* n = elements; index < length; n = n->next()) {
1517 ASSERT(n->value()->isConstant());
1518 constantBuffer[index++] = static_cast<ConstantNode*>(n->value())->jsValue(*this);
1520 emitOpcode(op_new_array_buffer);
1521 instructions().append(dst->index());
1522 instructions().append(constantBufferIndex);
1523 instructions().append(length);
1524 instructions().append(newArrayAllocationProfile());
1529 Vector<RefPtr<RegisterID>, 16, UnsafeVectorOverflow> argv;
1530 for (ElementNode* n = elements; n; n = n->next()) {
1534 ASSERT(!n->value()->isSpreadExpression());
1535 argv.append(newTemporary());
1536 // op_new_array requires the initial values to be a sequential range of registers
1537 ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() - 1);
1538 emitNode(argv.last().get(), n->value());
1541 emitOpcode(op_new_array);
1542 instructions().append(dst->index());
1543 instructions().append(argv.size() ? argv[0]->index() : 0); // argv
1544 instructions().append(argv.size()); // argc
1545 instructions().append(newArrayAllocationProfile());
1549 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, CaptureMode captureMode, FunctionBodyNode* function)
1551 return emitNewFunctionInternal(dst, captureMode, m_codeBlock->addFunctionDecl(makeFunction(function)), false);
1554 RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function)
1556 FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0);
1558 ptr.iterator->value = m_codeBlock->addFunctionDecl(makeFunction(function));
1559 return emitNewFunctionInternal(dst, NotCaptured, ptr.iterator->value, true);
1562 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, CaptureMode captureMode, unsigned index, bool doNullCheck)
1564 createActivationIfNecessary();
1565 emitOpcode(captureMode == IsCaptured ? op_new_captured_func : op_new_func);
1566 instructions().append(dst->index());
1567 instructions().append(index);
1568 if (captureMode == IsCaptured) {
1569 ASSERT(!doNullCheck);
1570 instructions().append(watchableVariable(dst->index()));
1572 instructions().append(doNullCheck);
1576 RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
1578 emitOpcode(op_new_regexp);
1579 instructions().append(dst->index());
1580 instructions().append(addRegExp(regExp));
1584 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
1586 FunctionBodyNode* function = n->body();
1587 unsigned index = m_codeBlock->addFunctionExpr(makeFunction(function));
1589 createActivationIfNecessary();
1590 emitOpcode(op_new_func_exp);
1591 instructions().append(r0->index());
1592 instructions().append(index);
1596 RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1598 return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
1601 void BytecodeGenerator::createArgumentsIfNecessary()
1603 if (m_codeType != FunctionCode)
1606 if (!m_codeBlock->usesArguments())
1609 if (shouldTearOffArgumentsEagerly())
1612 emitOpcode(op_create_arguments);
1613 instructions().append(m_codeBlock->argumentsRegister().offset());
1614 ASSERT(!hasWatchableVariable(m_codeBlock->argumentsRegister().offset()));
1617 void BytecodeGenerator::createActivationIfNecessary()
1619 if (!m_activationRegister)
1621 emitOpcode(op_create_activation);
1622 instructions().append(m_activationRegister->index());
1625 RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1627 createActivationIfNecessary();
1628 return emitCall(op_call_eval, dst, func, NoExpectedFunction, callArguments, divot, divotStart, divotEnd);
1631 ExpectedFunction BytecodeGenerator::expectedFunctionForIdentifier(const Identifier& identifier)
1633 if (identifier == m_vm->propertyNames->Object)
1634 return ExpectObjectConstructor;
1635 if (identifier == m_vm->propertyNames->Array)
1636 return ExpectArrayConstructor;
1637 return NoExpectedFunction;
1640 ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, Label* done)
1642 RefPtr<Label> realCall = newLabel();
1643 switch (expectedFunction) {
1644 case ExpectObjectConstructor: {
1645 // If the number of arguments is non-zero, then we can't do anything interesting.
1646 if (callArguments.argumentCountIncludingThis() >= 2)
1647 return NoExpectedFunction;
1649 size_t begin = instructions().size();
1650 emitOpcode(op_jneq_ptr);
1651 instructions().append(func->index());
1652 instructions().append(Special::ObjectConstructor);
1653 instructions().append(realCall->bind(begin, instructions().size()));
1655 if (dst != ignoredResult())
1660 case ExpectArrayConstructor: {
1661 // If you're doing anything other than "new Array()" or "new Array(foo)" then we
1662 // don't do inline it, for now. The only reason is that call arguments are in
1663 // the opposite order of what op_new_array expects, so we'd either need to change
1664 // how op_new_array works or we'd need an op_new_array_reverse. Neither of these
1665 // things sounds like it's worth it.
1666 if (callArguments.argumentCountIncludingThis() > 2)
1667 return NoExpectedFunction;
1669 size_t begin = instructions().size();
1670 emitOpcode(op_jneq_ptr);
1671 instructions().append(func->index());
1672 instructions().append(Special::ArrayConstructor);
1673 instructions().append(realCall->bind(begin, instructions().size()));
1675 if (dst != ignoredResult()) {
1676 if (callArguments.argumentCountIncludingThis() == 2) {
1677 emitOpcode(op_new_array_with_size);
1678 instructions().append(dst->index());
1679 instructions().append(callArguments.argumentRegister(0)->index());
1680 instructions().append(newArrayAllocationProfile());
1682 ASSERT(callArguments.argumentCountIncludingThis() == 1);
1683 emitOpcode(op_new_array);
1684 instructions().append(dst->index());
1685 instructions().append(0);
1686 instructions().append(0);
1687 instructions().append(newArrayAllocationProfile());
1694 ASSERT(expectedFunction == NoExpectedFunction);
1695 return NoExpectedFunction;
1698 size_t begin = instructions().size();
1700 instructions().append(done->bind(begin, instructions().size()));
1701 emitLabel(realCall.get());
1703 return expectedFunction;
1706 RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1708 ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
1709 ASSERT(func->refCount());
1711 if (m_shouldEmitProfileHooks)
1712 emitMove(callArguments.profileHookRegister(), func);
1714 // Generate code for arguments.
1715 unsigned argument = 0;
1716 if (callArguments.argumentsNode()) {
1717 ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
1718 if (n && n->m_expr->isSpreadExpression()) {
1719 RELEASE_ASSERT(!n->m_next);
1720 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
1721 expression->emitBytecode(*this, callArguments.argumentRegister(0));
1722 return emitCallVarargs(dst, func, callArguments.thisRegister(), callArguments.argumentRegister(0), newTemporary(), callArguments.profileHookRegister(), divot, divotStart, divotEnd);
1724 for (; n; n = n->m_next)
1725 emitNode(callArguments.argumentRegister(argument++), n);
1728 // Reserve space for call frame.
1729 Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
1730 for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
1731 callFrame.append(newTemporary());
1733 if (m_shouldEmitProfileHooks) {
1734 emitOpcode(op_profile_will_call);
1735 instructions().append(callArguments.profileHookRegister()->index());
1738 emitExpressionInfo(divot, divotStart, divotEnd);
1740 RefPtr<Label> done = newLabel();
1741 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
1744 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1745 UnlinkedValueProfile profile = emitProfiledOpcode(opcodeID);
1747 ASSERT(dst != ignoredResult());
1748 instructions().append(dst->index());
1749 instructions().append(func->index());
1750 instructions().append(callArguments.argumentCountIncludingThis());
1751 instructions().append(callArguments.stackOffset());
1753 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
1755 instructions().append(0);
1757 instructions().append(arrayProfile);
1758 instructions().append(profile);
1760 if (expectedFunction != NoExpectedFunction)
1761 emitLabel(done.get());
1763 if (m_shouldEmitProfileHooks) {
1764 emitOpcode(op_profile_did_call);
1765 instructions().append(callArguments.profileHookRegister()->index());
1771 RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1773 if (m_shouldEmitProfileHooks) {
1774 emitMove(profileHookRegister, func);
1775 emitOpcode(op_profile_will_call);
1776 instructions().append(profileHookRegister->index());
1779 emitExpressionInfo(divot, divotStart, divotEnd);
1782 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1783 UnlinkedValueProfile profile = emitProfiledOpcode(op_call_varargs);
1784 ASSERT(dst != ignoredResult());
1785 instructions().append(dst->index());
1786 instructions().append(func->index());
1787 instructions().append(thisRegister->index());
1788 instructions().append(arguments->index());
1789 instructions().append(firstFreeRegister->index());
1790 instructions().append(arrayProfile);
1791 instructions().append(profile);
1792 if (m_shouldEmitProfileHooks) {
1793 emitOpcode(op_profile_did_call);
1794 instructions().append(profileHookRegister->index());
1799 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
1801 if (m_activationRegister) {
1802 emitOpcode(op_tear_off_activation);
1803 instructions().append(m_activationRegister->index());
1806 if (m_codeBlock->usesArguments() && m_codeBlock->numParameters() != 1 && !isStrictMode()) {
1807 emitOpcode(op_tear_off_arguments);
1808 instructions().append(m_codeBlock->argumentsRegister().offset());
1809 instructions().append(m_activationRegister ? m_activationRegister->index() : emitLoad(0, JSValue())->index());
1812 // Constructors use op_ret_object_or_this to check the result is an
1813 // object, unless we can trivially determine the check is not
1814 // necessary (currently, if the return value is 'this').
1815 if (isConstructor() && (src->index() != m_thisRegister.index())) {
1816 emitOpcode(op_ret_object_or_this);
1817 instructions().append(src->index());
1818 instructions().append(m_thisRegister.index());
1821 return emitUnaryNoDstOp(op_ret, src);
1824 RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src)
1826 emitOpcode(opcodeID);
1827 instructions().append(src->index());
1831 RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1833 ASSERT(func->refCount());
1835 if (m_shouldEmitProfileHooks)
1836 emitMove(callArguments.profileHookRegister(), func);
1838 // Generate code for arguments.
1839 unsigned argument = 0;
1840 if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
1841 for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
1842 emitNode(callArguments.argumentRegister(argument++), n);
1845 if (m_shouldEmitProfileHooks) {
1846 emitOpcode(op_profile_will_call);
1847 instructions().append(callArguments.profileHookRegister()->index());
1850 // Reserve space for call frame.
1851 Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
1852 for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
1853 callFrame.append(newTemporary());
1855 emitExpressionInfo(divot, divotStart, divotEnd);
1857 RefPtr<Label> done = newLabel();
1858 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
1860 UnlinkedValueProfile profile = emitProfiledOpcode(op_construct);
1861 ASSERT(dst != ignoredResult());
1862 instructions().append(dst->index());
1863 instructions().append(func->index());
1864 instructions().append(callArguments.argumentCountIncludingThis());
1865 instructions().append(callArguments.stackOffset());
1867 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
1869 instructions().append(0);
1871 instructions().append(0);
1872 instructions().append(profile);
1874 if (expectedFunction != NoExpectedFunction)
1875 emitLabel(done.get());
1877 if (m_shouldEmitProfileHooks) {
1878 emitOpcode(op_profile_did_call);
1879 instructions().append(callArguments.profileHookRegister()->index());
1885 RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
1887 emitOpcode(op_strcat);
1888 instructions().append(dst->index());
1889 instructions().append(src->index());
1890 instructions().append(count);
1895 void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
1897 emitOpcode(op_to_primitive);
1898 instructions().append(dst->index());
1899 instructions().append(src->index());
1902 RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* scope)
1904 ControlFlowContext context;
1905 context.isFinallyBlock = false;
1906 m_scopeContextStack.append(context);
1907 m_localScopeDepth++;
1909 createActivationIfNecessary();
1910 return emitUnaryNoDstOp(op_push_with_scope, scope);
1913 void BytecodeGenerator::emitPopScope()
1915 ASSERT(m_scopeContextStack.size());
1916 ASSERT(!m_scopeContextStack.last().isFinallyBlock);
1918 emitOpcode(op_pop_scope);
1920 m_scopeContextStack.removeLast();
1921 m_localScopeDepth--;
1924 void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, unsigned line, unsigned charOffset, unsigned lineStart)
1926 #if ENABLE(DEBUG_WITH_BREAKPOINT)
1927 if (debugHookID != DidReachBreakpoint)
1930 if (!m_shouldEmitDebugHooks)
1933 JSTextPosition divot(line, charOffset, lineStart);
1934 emitExpressionInfo(divot, divot, divot);
1935 emitOpcode(op_debug);
1936 instructions().append(debugHookID);
1937 instructions().append(false);
1940 void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock)
1942 // Reclaim free label scopes.
1943 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
1944 m_labelScopes.removeLast();
1946 ControlFlowContext scope;
1947 scope.isFinallyBlock = true;
1948 FinallyContext context = {
1950 static_cast<unsigned>(m_scopeContextStack.size()),
1951 static_cast<unsigned>(m_switchContextStack.size()),
1952 static_cast<unsigned>(m_forInContextStack.size()),
1953 static_cast<unsigned>(m_tryContextStack.size()),
1954 static_cast<unsigned>(m_labelScopes.size()),
1958 scope.finallyContext = context;
1959 m_scopeContextStack.append(scope);
1963 void BytecodeGenerator::popFinallyContext()
1965 ASSERT(m_scopeContextStack.size());
1966 ASSERT(m_scopeContextStack.last().isFinallyBlock);
1967 ASSERT(m_finallyDepth > 0);
1968 m_scopeContextStack.removeLast();
1972 LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
1974 // Reclaim free label scopes.
1976 // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
1977 // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
1978 // size 0, leading to segfaulty badness. We are yet to identify a valid cause within our code to
1979 // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
1980 // loop condition is a workaround.
1981 while (m_labelScopes.size()) {
1982 if (m_labelScopes.last().refCount())
1984 m_labelScopes.removeLast();
1987 if (!m_labelScopes.size())
1990 // We special-case the following, which is a syntax error in Firefox:
1993 if (name.isEmpty()) {
1994 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1995 LabelScope* scope = &m_labelScopes[i];
1996 if (scope->type() != LabelScope::NamedLabel) {
1997 ASSERT(scope->breakTarget());
2004 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2005 LabelScope* scope = &m_labelScopes[i];
2006 if (scope->name() && *scope->name() == name) {
2007 ASSERT(scope->breakTarget());
2014 LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
2016 // Reclaim free label scopes.
2017 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2018 m_labelScopes.removeLast();
2020 if (!m_labelScopes.size())
2023 if (name.isEmpty()) {
2024 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2025 LabelScope* scope = &m_labelScopes[i];
2026 if (scope->type() == LabelScope::Loop) {
2027 ASSERT(scope->continueTarget());
2034 // Continue to the loop nested nearest to the label scope that matches
2036 LabelScope* result = 0;
2037 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2038 LabelScope* scope = &m_labelScopes[i];
2039 if (scope->type() == LabelScope::Loop) {
2040 ASSERT(scope->continueTarget());
2043 if (scope->name() && *scope->name() == name)
2044 return result; // may be 0
2049 void BytecodeGenerator::emitComplexPopScopes(ControlFlowContext* topScope, ControlFlowContext* bottomScope)
2051 while (topScope > bottomScope) {
2052 // First we count the number of dynamic scopes we need to remove to get
2053 // to a finally block.
2054 int nNormalScopes = 0;
2055 while (topScope > bottomScope) {
2056 if (topScope->isFinallyBlock)
2062 if (nNormalScopes) {
2063 // We need to remove a number of dynamic scopes to get to the next
2065 while (nNormalScopes--)
2066 emitOpcode(op_pop_scope);
2068 // If topScope == bottomScope then there isn't a finally block left to emit.
2069 if (topScope == bottomScope)
2073 Vector<ControlFlowContext> savedScopeContextStack;
2074 Vector<SwitchInfo> savedSwitchContextStack;
2075 Vector<ForInContext> savedForInContextStack;
2076 Vector<TryContext> poppedTryContexts;
2077 LabelScopeStore savedLabelScopes;
2078 while (topScope > bottomScope && topScope->isFinallyBlock) {
2079 RefPtr<Label> beforeFinally = emitLabel(newLabel().get());
2081 // Save the current state of the world while instating the state of the world
2082 // for the finally block.
2083 FinallyContext finallyContext = topScope->finallyContext;
2084 bool flipScopes = finallyContext.scopeContextStackSize != m_scopeContextStack.size();
2085 bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size();
2086 bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size();
2087 bool flipTries = finallyContext.tryContextStackSize != m_tryContextStack.size();
2088 bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size();
2089 int topScopeIndex = -1;
2090 int bottomScopeIndex = -1;
2092 topScopeIndex = topScope - m_scopeContextStack.begin();
2093 bottomScopeIndex = bottomScope - m_scopeContextStack.begin();
2094 savedScopeContextStack = m_scopeContextStack;
2095 m_scopeContextStack.shrink(finallyContext.scopeContextStackSize);
2098 savedSwitchContextStack = m_switchContextStack;
2099 m_switchContextStack.shrink(finallyContext.switchContextStackSize);
2102 savedForInContextStack = m_forInContextStack;
2103 m_forInContextStack.shrink(finallyContext.forInContextStackSize);
2106 while (m_tryContextStack.size() != finallyContext.tryContextStackSize) {
2107 ASSERT(m_tryContextStack.size() > finallyContext.tryContextStackSize);
2108 TryContext context = m_tryContextStack.last();
2109 m_tryContextStack.removeLast();
2111 range.start = context.start;
2112 range.end = beforeFinally;
2113 range.tryData = context.tryData;
2114 m_tryRanges.append(range);
2115 poppedTryContexts.append(context);
2118 if (flipLabelScopes) {
2119 savedLabelScopes = m_labelScopes;
2120 while (m_labelScopes.size() > finallyContext.labelScopesSize)
2121 m_labelScopes.removeLast();
2123 int savedFinallyDepth = m_finallyDepth;
2124 m_finallyDepth = finallyContext.finallyDepth;
2125 int savedDynamicScopeDepth = m_localScopeDepth;
2126 m_localScopeDepth = finallyContext.dynamicScopeDepth;
2128 // Emit the finally block.
2129 emitNode(finallyContext.finallyBlock);
2131 RefPtr<Label> afterFinally = emitLabel(newLabel().get());
2133 // Restore the state of the world.
2135 m_scopeContextStack = savedScopeContextStack;
2136 topScope = &m_scopeContextStack[topScopeIndex]; // assert it's within bounds
2137 bottomScope = m_scopeContextStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1.
2140 m_switchContextStack = savedSwitchContextStack;
2142 m_forInContextStack = savedForInContextStack;
2144 ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize);
2145 for (unsigned i = poppedTryContexts.size(); i--;) {
2146 TryContext context = poppedTryContexts[i];
2147 context.start = afterFinally;
2148 m_tryContextStack.append(context);
2150 poppedTryContexts.clear();
2152 if (flipLabelScopes)
2153 m_labelScopes = savedLabelScopes;
2154 m_finallyDepth = savedFinallyDepth;
2155 m_localScopeDepth = savedDynamicScopeDepth;
2162 void BytecodeGenerator::emitPopScopes(int targetScopeDepth)
2164 ASSERT(scopeDepth() - targetScopeDepth >= 0);
2166 size_t scopeDelta = scopeDepth() - targetScopeDepth;
2167 ASSERT(scopeDelta <= m_scopeContextStack.size());
2171 if (!m_finallyDepth) {
2172 while (scopeDelta--)
2173 emitOpcode(op_pop_scope);
2177 emitComplexPopScopes(&m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
2180 RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget)
2182 size_t begin = instructions().size();
2184 emitOpcode(op_get_pnames);
2185 instructions().append(dst->index());
2186 instructions().append(base->index());
2187 instructions().append(i->index());
2188 instructions().append(size->index());
2189 instructions().append(breakTarget->bind(begin, instructions().size()));
2193 RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target)
2195 size_t begin = instructions().size();
2197 emitOpcode(op_next_pname);
2198 instructions().append(dst->index());
2199 instructions().append(base->index());
2200 instructions().append(i->index());
2201 instructions().append(size->index());
2202 instructions().append(iter->index());
2203 instructions().append(target->bind(begin, instructions().size()));
2207 TryData* BytecodeGenerator::pushTry(Label* start)
2210 tryData.target = newLabel();
2211 tryData.targetScopeDepth = UINT_MAX;
2212 m_tryData.append(tryData);
2213 TryData* result = &m_tryData.last();
2215 TryContext tryContext;
2216 tryContext.start = start;
2217 tryContext.tryData = result;
2219 m_tryContextStack.append(tryContext);
2224 RegisterID* BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* targetRegister, Label* end)
2226 m_usesExceptions = true;
2228 ASSERT_UNUSED(tryData, m_tryContextStack.last().tryData == tryData);
2231 tryRange.start = m_tryContextStack.last().start;
2233 tryRange.tryData = m_tryContextStack.last().tryData;
2234 m_tryRanges.append(tryRange);
2235 m_tryContextStack.removeLast();
2237 emitLabel(tryRange.tryData->target.get());
2238 tryRange.tryData->targetScopeDepth = m_localScopeDepth;
2240 emitOpcode(op_catch);
2241 instructions().append(targetRegister->index());
2242 return targetRegister;
2245 void BytecodeGenerator::emitThrowReferenceError(const String& message)
2247 emitOpcode(op_throw_static_error);
2248 instructions().append(addConstantValue(addStringConstant(Identifier(m_vm, message)))->index());
2249 instructions().append(true);
2252 void BytecodeGenerator::emitPushFunctionNameScope(const Identifier& property, RegisterID* value, unsigned attributes)
2254 emitOpcode(op_push_name_scope);
2255 instructions().append(addConstant(property));
2256 instructions().append(value->index());
2257 instructions().append(attributes);
2260 void BytecodeGenerator::emitPushCatchScope(const Identifier& property, RegisterID* value, unsigned attributes)
2262 createActivationIfNecessary();
2264 ControlFlowContext context;
2265 context.isFinallyBlock = false;
2266 m_scopeContextStack.append(context);
2267 m_localScopeDepth++;
2269 emitOpcode(op_push_name_scope);
2270 instructions().append(addConstant(property));
2271 instructions().append(value->index());
2272 instructions().append(attributes);
2275 void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
2277 SwitchInfo info = { static_cast<uint32_t>(instructions().size()), type };
2279 case SwitchInfo::SwitchImmediate:
2280 emitOpcode(op_switch_imm);
2282 case SwitchInfo::SwitchCharacter:
2283 emitOpcode(op_switch_char);
2285 case SwitchInfo::SwitchString:
2286 emitOpcode(op_switch_string);
2289 RELEASE_ASSERT_NOT_REACHED();
2292 instructions().append(0); // place holder for table index
2293 instructions().append(0); // place holder for default target
2294 instructions().append(scrutineeRegister->index());
2295 m_switchContextStack.append(info);
2298 static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
2301 ASSERT(node->isNumber());
2302 double value = static_cast<NumberNode*>(node)->value();
2303 int32_t key = static_cast<int32_t>(value);
2304 ASSERT(key == value);
2310 static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
2313 ASSERT(node->isString());
2314 StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
2315 ASSERT(clause->length() == 1);
2317 int32_t key = (*clause)[0];
2323 static void prepareJumpTableForSwitch(
2324 UnlinkedSimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount,
2325 RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max,
2326 int32_t (*keyGetter)(ExpressionNode*, int32_t min, int32_t max))
2328 jumpTable.min = min;
2329 jumpTable.branchOffsets.resize(max - min + 1);
2330 jumpTable.branchOffsets.fill(0);
2331 for (uint32_t i = 0; i < clauseCount; ++i) {
2332 // We're emitting this after the clause labels should have been fixed, so
2333 // the labels should not be "forward" references
2334 ASSERT(!labels[i]->isForward());
2335 jumpTable.add(keyGetter(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3));
2339 static void prepareJumpTableForStringSwitch(UnlinkedStringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
2341 for (uint32_t i = 0; i < clauseCount; ++i) {
2342 // We're emitting this after the clause labels should have been fixed, so
2343 // the labels should not be "forward" references
2344 ASSERT(!labels[i]->isForward());
2346 ASSERT(nodes[i]->isString());
2347 StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
2348 jumpTable.offsetTable.add(clause, labels[i]->bind(switchAddress, switchAddress + 3));
2352 void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max)
2354 SwitchInfo switchInfo = m_switchContextStack.last();
2355 m_switchContextStack.removeLast();
2357 switch (switchInfo.switchType) {
2358 case SwitchInfo::SwitchImmediate:
2359 case SwitchInfo::SwitchCharacter: {
2360 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfSwitchJumpTables();
2361 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
2363 UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->addSwitchJumpTable();
2364 prepareJumpTableForSwitch(
2365 jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max,
2366 switchInfo.switchType == SwitchInfo::SwitchImmediate
2367 ? keyForImmediateSwitch
2368 : keyForCharacterSwitch);
2372 case SwitchInfo::SwitchString: {
2373 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
2374 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
2376 UnlinkedStringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
2377 prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
2382 RELEASE_ASSERT_NOT_REACHED();
2387 RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
2389 // It would be nice to do an even better job of identifying exactly where the expression is.
2390 // And we could make the caller pass the node pointer in, if there was some way of getting
2391 // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
2392 // is still good enough to get us an accurate line number.
2393 m_expressionTooDeep = true;
2394 return newTemporary();
2397 void BytecodeGenerator::setIsNumericCompareFunction(bool isNumericCompareFunction)
2399 m_codeBlock->setIsNumericCompareFunction(isNumericCompareFunction);
2402 bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
2404 RegisterID* registerID = local(ident).get();
2405 if (!registerID || registerID->index() >= 0)
2407 return registerID->index() == CallFrame::argumentOffset(argumentNumber);
2410 void BytecodeGenerator::emitReadOnlyExceptionIfNeeded()
2412 if (!isStrictMode())
2414 emitOpcode(op_throw_static_error);
2415 instructions().append(addConstantValue(addStringConstant(Identifier(m_vm, StrictModeReadonlyPropertyWriteError)))->index());
2416 instructions().append(false);
2419 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack)
2421 if (subjectNode->isResolveNode()
2422 && willResolveToArguments(static_cast<ResolveNode*>(subjectNode)->identifier())
2423 && !symbolTable().slowArguments()) {
2424 RefPtr<RegisterID> index = emitLoad(newTemporary(), jsNumber(0));
2426 LabelScopePtr scope = newLabelScope(LabelScope::Loop);
2427 RefPtr<RegisterID> value = emitLoad(newTemporary(), jsUndefined());
2429 emitJump(scope->continueTarget());
2431 RefPtr<Label> loopStart = newLabel();
2432 emitLabel(loopStart.get());
2434 emitGetArgumentByVal(value.get(), uncheckedRegisterForArguments(), index.get());
2435 callBack(*this, value.get());
2436 emitInc(index.get());
2437 emitLabel(scope->continueTarget());
2439 RefPtr<RegisterID> length = emitGetArgumentsLength(newTemporary(), uncheckedRegisterForArguments());
2440 emitJumpIfTrue(emitEqualityOp(op_less, newTemporary(), index.get(), length.get()), loopStart.get());
2441 emitLabel(scope->breakTarget());
2445 LabelScopePtr scope = newLabelScope(LabelScope::Loop);
2446 RefPtr<RegisterID> subject = newTemporary();
2447 emitNode(subject.get(), subjectNode);
2448 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), subject.get(), propertyNames().iteratorPrivateName);
2450 CallArguments args(*this, 0);
2451 emitMove(args.thisRegister(), subject.get());
2452 emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd());
2454 RefPtr<RegisterID> iteratorNext = emitGetById(newTemporary(), iterator.get(), propertyNames().iteratorNextPrivateName);
2455 RefPtr<RegisterID> value = newTemporary();
2456 emitLoad(value.get(), jsUndefined());
2458 emitJump(scope->continueTarget());
2460 RefPtr<Label> loopStart = newLabel();
2461 emitLabel(loopStart.get());
2463 callBack(*this, value.get());
2464 emitLabel(scope->continueTarget());
2465 CallArguments nextArguments(*this, 0, 1);
2466 emitMove(nextArguments.thisRegister(), iterator.get());
2467 emitMove(nextArguments.argumentRegister(0), value.get());
2468 emitCall(value.get(), iteratorNext.get(), NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd());
2469 RefPtr<RegisterID> result = newTemporary();
2470 emitJumpIfFalse(emitEqualityOp(op_stricteq, result.get(), value.get(), emitLoad(0, JSValue(vm()->iterationTerminator.get()))), loopStart.get());
2471 emitLabel(scope->breakTarget());