2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "BytecodeGenerator.h"
33 #include "BatchedTransitionOptimizer.h"
34 #include "JSFunction.h"
35 #include "Interpreter.h"
43 The layout of a register frame looks like this:
54 assuming (x) and (y) generated temporaries t1 and t2, you would have
56 ------------------------------------
57 | x | y | g | v2 | v1 | t1 | t2 | <-- value held
58 ------------------------------------
59 | -5 | -4 | -3 | -2 | -1 | +0 | +1 | <-- register index
60 ------------------------------------
61 | params->|<-locals | temps->
63 Because temporary registers are allocated in a stack-like fashion, we
64 can reclaim them with a simple popping algorithm. The same goes for labels.
65 (We never reclaim parameter or local registers, because parameters and
66 locals are DontDelete.)
68 The register layout before a function call looks like this:
78 > <------------------------------
79 < > reserved: call frame | 1 | <-- value held
80 > >snip< <------------------------------
81 < > +0 | +1 | +2 | +3 | +4 | +5 | <-- register index
82 > <------------------------------
83 | params->|<-locals | temps->
85 The call instruction fills in the "call frame" registers. It also pads
86 missing arguments at the end of the call:
88 > <-----------------------------------
89 < > reserved: call frame | 1 | ? | <-- value held ("?" stands for "undefined")
90 > >snip< <-----------------------------------
91 < > +0 | +1 | +2 | +3 | +4 | +5 | +6 | <-- register index
92 > <-----------------------------------
93 | params->|<-locals | temps->
95 After filling in missing arguments, the call instruction sets up the new
96 stack frame to overlap the end of the old stack frame:
98 |----------------------------------> <
99 | reserved: call frame | 1 | ? < > <-- value held ("?" stands for "undefined")
100 |----------------------------------> >snip< <
101 | -7 | -6 | -5 | -4 | -3 | -2 | -1 < > <-- register index
102 |----------------------------------> <
103 | | params->|<-locals | temps->
105 That way, arguments are "copied" into the callee's stack frame for free.
107 If the caller supplies too many arguments, this trick doesn't work. The
108 extra arguments protrude into space reserved for locals and temporaries.
109 In that case, the call instruction makes a real copy of the call frame header,
110 along with just the arguments expected by the callee, leaving the original
111 call frame header and arguments behind. (The call instruction can't just discard
112 extra arguments, because the "arguments" object may access them later.)
113 This copying strategy ensures that all named values will be at the indices
114 expected by the callee.
118 bool BytecodeGenerator::s_dumpsGeneratedCode = false;
121 void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
124 s_dumpsGeneratedCode = dumpsGeneratedCode;
126 UNUSED_PARAM(dumpsGeneratedCode);
130 void BytecodeGenerator::generate()
132 m_codeBlock->thisRegister = m_thisRegister.index();
134 m_scopeNode->emitBytecode(*this);
137 if (s_dumpsGeneratedCode) {
138 JSGlobalObject* globalObject = m_scopeChain->globalObject();
139 m_codeBlock->dump(globalObject->globalExec());
143 m_codeBlock->instructions.shrinkToFit();
144 m_codeBlock->globalResolveInstructions.shrinkToFit();
145 m_codeBlock->propertyAccessInstructions.shrinkToFit();
146 m_codeBlock->callLinkInfos.shrinkToFit();
147 m_codeBlock->linkedCallerList.shrinkToFit();
149 m_codeBlock->identifiers.shrinkToFit();
150 m_codeBlock->functions.shrinkToFit();
151 m_codeBlock->functionExpressions.shrinkToFit();
152 m_codeBlock->constantRegisters.shrinkToFit();
153 m_codeBlock->unexpectedConstants.shrinkToFit();
154 m_codeBlock->regexps.shrinkToFit();
155 m_codeBlock->exceptionHandlers.shrinkToFit();
156 m_codeBlock->expressionInfo.shrinkToFit();
157 m_codeBlock->lineInfo.shrinkToFit();
159 m_codeBlock->immediateSwitchJumpTables.shrinkToFit();
160 m_codeBlock->characterSwitchJumpTables.shrinkToFit();
161 m_codeBlock->stringSwitchJumpTables.shrinkToFit();
165 bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
167 int index = m_calleeRegisters.size();
168 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
169 pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
171 if (!result.second) {
172 r0 = ®isterFor(result.first->second.getIndex());
176 ++m_codeBlock->numVars;
181 bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
183 int index = m_nextGlobalIndex;
184 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
185 pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
188 index = result.first->second.getIndex();
191 m_globals.append(index + m_globalVarStorageOffset);
194 r0 = ®isterFor(index);
195 return result.second;
198 void BytecodeGenerator::allocateConstants(size_t count)
200 m_codeBlock->numConstants = count;
204 m_nextConstantIndex = m_calleeRegisters.size();
206 for (size_t i = 0; i < count; ++i)
208 m_lastConstant = &m_calleeRegisters.last();
211 BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
212 : m_shouldEmitDebugHooks(!!debugger)
213 , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
214 , m_scopeChain(&scopeChain)
215 , m_symbolTable(symbolTable)
216 , m_scopeNode(programNode)
217 , m_codeBlock(codeBlock)
218 , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
220 , m_dynamicScopeDepth(0)
221 , m_codeType(GlobalCode)
222 , m_nextGlobalIndex(-1)
223 , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
224 , m_lastOpcodeID(op_end)
227 if (m_shouldEmitDebugHooks)
228 m_codeBlock->needsFullScopeChain = true;
230 emitOpcode(op_enter);
231 codeBlock->globalData = m_globalData;
233 // FIXME: Move code that modifies the global object to Interpreter::execute.
235 m_codeBlock->numParameters = 1; // Allocate space for "this"
237 JSGlobalObject* globalObject = scopeChain.globalObject();
238 ExecState* exec = globalObject->globalExec();
239 RegisterFile* registerFile = &exec->globalData().interpreter->registerFile();
241 // Shift register indexes in generated code to elide registers allocated by intermediate stack frames.
242 m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->numParameters - registerFile->size();
244 // Add previously defined symbols to bookkeeping.
245 m_globals.grow(symbolTable->size());
246 SymbolTable::iterator end = symbolTable->end();
247 for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
248 registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset);
250 BatchedTransitionOptimizer optimizer(globalObject);
252 const VarStack& varStack = programNode->varStack();
253 const FunctionStack& functionStack = programNode->functionStack();
254 bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals();
255 if (canOptimizeNewGlobals) {
256 // Shift new symbols so they get stored prior to existing symbols.
257 m_nextGlobalIndex -= symbolTable->size();
259 for (size_t i = 0; i < functionStack.size(); ++i) {
260 FuncDeclNode* funcDecl = functionStack[i].get();
261 globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property.
262 emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl);
265 Vector<RegisterID*, 32> newVars;
266 for (size_t i = 0; i < varStack.size(); ++i)
267 if (!globalObject->hasProperty(exec, varStack[i].first))
268 newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
270 allocateConstants(programNode->neededConstants());
272 for (size_t i = 0; i < newVars.size(); ++i)
273 emitLoad(newVars[i], jsUndefined());
275 for (size_t i = 0; i < functionStack.size(); ++i) {
276 FuncDeclNode* funcDecl = functionStack[i].get();
277 globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete);
279 for (size_t i = 0; i < varStack.size(); ++i) {
280 if (globalObject->hasProperty(exec, varStack[i].first))
282 int attributes = DontDelete;
283 if (varStack[i].second & DeclarationStacks::IsConstant)
284 attributes |= ReadOnly;
285 globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
288 allocateConstants(programNode->neededConstants());
292 BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
293 : m_shouldEmitDebugHooks(!!debugger)
294 , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
295 , m_scopeChain(&scopeChain)
296 , m_symbolTable(symbolTable)
297 , m_scopeNode(functionBody)
298 , m_codeBlock(codeBlock)
300 , m_dynamicScopeDepth(0)
301 , m_codeType(FunctionCode)
302 , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
303 , m_lastOpcodeID(op_end)
306 if (m_shouldEmitDebugHooks)
307 m_codeBlock->needsFullScopeChain = true;
309 codeBlock->globalData = m_globalData;
311 bool usesArguments = functionBody->usesArguments();
312 codeBlock->usesArguments = usesArguments;
314 m_argumentsRegister.setIndex(RegisterFile::OptionalCalleeArguments);
315 addVar(propertyNames().arguments, false);
318 if (m_codeBlock->needsFullScopeChain) {
319 ++m_codeBlock->numVars;
320 m_activationRegisterIndex = newRegister()->index();
321 emitOpcode(op_enter_with_activation);
322 instructions().append(m_activationRegisterIndex);
324 emitOpcode(op_enter);
327 emitOpcode(op_create_arguments);
329 const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
330 for (size_t i = 0; i < functionStack.size(); ++i) {
331 FuncDeclNode* funcDecl = functionStack[i].get();
332 const Identifier& ident = funcDecl->m_ident;
333 m_functions.add(ident.ustring().rep());
334 emitNewFunction(addVar(ident, false), funcDecl);
337 const DeclarationStacks::VarStack& varStack = functionBody->varStack();
338 for (size_t i = 0; i < varStack.size(); ++i)
339 addVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
341 const Identifier* parameters = functionBody->parameters();
342 size_t parameterCount = functionBody->parameterCount();
343 m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
344 m_parameters.grow(1 + parameterCount); // reserve space for "this"
346 // Add "this" as a parameter
347 m_thisRegister.setIndex(m_nextParameterIndex);
348 ++m_nextParameterIndex;
349 ++m_codeBlock->numParameters;
351 if (functionBody->usesThis()) {
352 emitOpcode(op_convert_this);
353 instructions().append(m_thisRegister.index());
356 for (size_t i = 0; i < parameterCount; ++i)
357 addParameter(parameters[i]);
359 allocateConstants(functionBody->neededConstants());
362 BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
363 : m_shouldEmitDebugHooks(!!debugger)
364 , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
365 , m_scopeChain(&scopeChain)
366 , m_symbolTable(symbolTable)
367 , m_scopeNode(evalNode)
368 , m_codeBlock(codeBlock)
369 , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
371 , m_dynamicScopeDepth(0)
372 , m_codeType(EvalCode)
373 , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
374 , m_lastOpcodeID(op_end)
377 if (m_shouldEmitDebugHooks)
378 m_codeBlock->needsFullScopeChain = true;
380 emitOpcode(op_enter);
381 codeBlock->globalData = m_globalData;
382 m_codeBlock->numParameters = 1; // Allocate space for "this"
384 allocateConstants(evalNode->neededConstants());
387 RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
389 // Parameters overwrite var declarations, but not function declarations.
390 RegisterID* result = 0;
391 UString::Rep* rep = ident.ustring().rep();
392 if (!m_functions.contains(rep)) {
393 symbolTable().set(rep, m_nextParameterIndex);
394 RegisterID& parameter = registerFor(m_nextParameterIndex);
395 parameter.setIndex(m_nextParameterIndex);
399 // To maintain the calling convention, we have to allocate unique space for
400 // each parameter, even if the parameter doesn't make it into the symbol table.
401 ++m_nextParameterIndex;
402 ++m_codeBlock->numParameters;
406 RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
408 if (ident == propertyNames().thisIdentifier)
409 return &m_thisRegister;
411 if (!shouldOptimizeLocals())
414 SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
418 return ®isterFor(entry.getIndex());
421 RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
423 if (m_codeType == EvalCode)
426 SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
427 ASSERT(!entry.isNull());
429 return ®isterFor(entry.getIndex());
432 bool BytecodeGenerator::isLocal(const Identifier& ident)
434 if (ident == propertyNames().thisIdentifier)
437 return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());
440 bool BytecodeGenerator::isLocalConstant(const Identifier& ident)
442 return symbolTable().get(ident.ustring().rep()).isReadOnly();
445 RegisterID* BytecodeGenerator::newRegister()
447 m_calleeRegisters.append(m_calleeRegisters.size());
448 m_codeBlock->numCalleeRegisters = max<int>(m_codeBlock->numCalleeRegisters, m_calleeRegisters.size());
449 return &m_calleeRegisters.last();
452 RegisterID* BytecodeGenerator::newTemporary()
454 // Reclaim free register IDs.
455 while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
456 m_calleeRegisters.removeLast();
458 RegisterID* result = newRegister();
459 result->setTemporary();
463 RegisterID* BytecodeGenerator::highestUsedRegister()
465 size_t count = m_codeBlock->numCalleeRegisters;
466 while (m_calleeRegisters.size() < count)
468 return &m_calleeRegisters.last();
471 PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
473 // Reclaim free label scopes.
474 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
475 m_labelScopes.removeLast();
477 // Allocate new label scope.
478 LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : 0); // Only loops have continue targets.
479 m_labelScopes.append(scope);
480 return &m_labelScopes.last();
483 PassRefPtr<Label> BytecodeGenerator::newLabel()
485 // Reclaim free label IDs.
486 while (m_labels.size() && !m_labels.last().refCount())
487 m_labels.removeLast();
489 // Allocate new label ID.
490 m_labels.append(m_codeBlock);
491 return &m_labels.last();
494 PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
496 unsigned newLabelIndex = instructions().size();
497 l0->setLocation(newLabelIndex);
499 if (m_codeBlock->jumpTargets.size() != 0) {
500 unsigned lastLabelIndex = m_codeBlock->jumpTargets.last();
501 ASSERT(lastLabelIndex <= newLabelIndex);
502 if (newLabelIndex == lastLabelIndex) {
503 // Peephole optimizations have already been disabled by emitting the last label
508 m_codeBlock->jumpTargets.append(newLabelIndex);
510 // This disables peephole optimizations when an instruction is a jump target
511 m_lastOpcodeID = op_end;
515 void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
517 instructions().append(globalData()->interpreter->getOpcode(opcodeID));
518 m_lastOpcodeID = opcodeID;
521 void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
523 ASSERT(instructions().size() >= 4);
524 size_t size = instructions().size();
525 dstIndex = instructions().at(size - 3).u.operand;
526 src1Index = instructions().at(size - 2).u.operand;
527 src2Index = instructions().at(size - 1).u.operand;
530 void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
532 ASSERT(instructions().size() >= 3);
533 size_t size = instructions().size();
534 dstIndex = instructions().at(size - 2).u.operand;
535 srcIndex = instructions().at(size - 1).u.operand;
538 void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
540 ASSERT(instructions().size() >= 4);
541 instructions().shrink(instructions().size() - 4);
544 void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
546 ASSERT(instructions().size() >= 3);
547 instructions().shrink(instructions().size() - 3);
550 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
552 emitOpcode(target->isForward() ? op_jmp : op_loop);
553 instructions().append(target->offsetFrom(instructions().size()));
557 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
559 if (m_lastOpcodeID == op_less && !target->isForward()) {
564 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
566 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
568 emitOpcode(op_loop_if_less);
569 instructions().append(src1Index);
570 instructions().append(src2Index);
571 instructions().append(target->offsetFrom(instructions().size()));
574 } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {
579 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
581 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
583 emitOpcode(op_loop_if_lesseq);
584 instructions().append(src1Index);
585 instructions().append(src2Index);
586 instructions().append(target->offsetFrom(instructions().size()));
589 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
593 retrieveLastUnaryOp(dstIndex, srcIndex);
595 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
597 emitOpcode(op_jeq_null);
598 instructions().append(srcIndex);
599 instructions().append(target->offsetFrom(instructions().size()));
602 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
606 retrieveLastUnaryOp(dstIndex, srcIndex);
608 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
610 emitOpcode(op_jneq_null);
611 instructions().append(srcIndex);
612 instructions().append(target->offsetFrom(instructions().size()));
617 emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
618 instructions().append(cond->index());
619 instructions().append(target->offsetFrom(instructions().size()));
623 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
625 ASSERT(target->isForward());
627 if (m_lastOpcodeID == op_less) {
632 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
634 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
636 emitOpcode(op_jnless);
637 instructions().append(src1Index);
638 instructions().append(src2Index);
639 instructions().append(target->offsetFrom(instructions().size()));
642 } else if (m_lastOpcodeID == op_not) {
646 retrieveLastUnaryOp(dstIndex, srcIndex);
648 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
650 emitOpcode(op_jtrue);
651 instructions().append(srcIndex);
652 instructions().append(target->offsetFrom(instructions().size()));
655 } else if (m_lastOpcodeID == op_eq_null) {
659 retrieveLastUnaryOp(dstIndex, srcIndex);
661 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
663 emitOpcode(op_jneq_null);
664 instructions().append(srcIndex);
665 instructions().append(target->offsetFrom(instructions().size()));
668 } else if (m_lastOpcodeID == op_neq_null) {
672 retrieveLastUnaryOp(dstIndex, srcIndex);
674 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
676 emitOpcode(op_jeq_null);
677 instructions().append(srcIndex);
678 instructions().append(target->offsetFrom(instructions().size()));
683 emitOpcode(op_jfalse);
684 instructions().append(cond->index());
685 instructions().append(target->offsetFrom(instructions().size()));
689 unsigned BytecodeGenerator::addConstant(FuncDeclNode* n)
691 // No need to explicitly unique function body nodes -- they're unique already.
692 int index = m_codeBlock->functions.size();
693 m_codeBlock->functions.append(n);
697 unsigned BytecodeGenerator::addConstant(FuncExprNode* n)
699 // No need to explicitly unique function expression nodes -- they're unique already.
700 int index = m_codeBlock->functionExpressions.size();
701 m_codeBlock->functionExpressions.append(n);
705 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
707 UString::Rep* rep = ident.ustring().rep();
708 pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->identifiers.size());
709 if (result.second) // new entry
710 m_codeBlock->identifiers.append(Identifier(m_globalData, rep));
712 return result.first->second;
715 RegisterID* BytecodeGenerator::addConstant(JSValue* v)
717 pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_nextConstantIndex);
719 RegisterID& constant = m_calleeRegisters[m_nextConstantIndex];
721 ++m_nextConstantIndex;
723 m_codeBlock->constantRegisters.append(v);
727 return ®isterFor(result.first->second);
730 unsigned BytecodeGenerator::addUnexpectedConstant(JSValue* v)
732 int index = m_codeBlock->unexpectedConstants.size();
733 m_codeBlock->unexpectedConstants.append(v);
737 unsigned BytecodeGenerator::addRegExp(RegExp* r)
739 int index = m_codeBlock->regexps.size();
740 m_codeBlock->regexps.append(r);
744 RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
747 instructions().append(dst->index());
748 instructions().append(src->index());
752 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src)
754 emitOpcode(opcodeID);
755 instructions().append(dst->index());
756 instructions().append(src->index());
760 RegisterID* BytecodeGenerator::emitPreInc(RegisterID* srcDst)
762 emitOpcode(op_pre_inc);
763 instructions().append(srcDst->index());
767 RegisterID* BytecodeGenerator::emitPreDec(RegisterID* srcDst)
769 emitOpcode(op_pre_dec);
770 instructions().append(srcDst->index());
774 RegisterID* BytecodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
776 emitOpcode(op_post_inc);
777 instructions().append(dst->index());
778 instructions().append(srcDst->index());
782 RegisterID* BytecodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
784 emitOpcode(op_post_dec);
785 instructions().append(dst->index());
786 instructions().append(srcDst->index());
790 RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
792 emitOpcode(opcodeID);
793 instructions().append(dst->index());
794 instructions().append(src1->index());
795 instructions().append(src2->index());
797 if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
798 opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub) {
799 instructions().append(types.toInt());
805 RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2)
807 if (m_lastOpcodeID == op_typeof) {
811 retrieveLastUnaryOp(dstIndex, srcIndex);
813 if (src1->index() == dstIndex
814 && src1->isTemporary()
815 && m_codeBlock->isConstantRegisterIndex(src2->index())
816 && m_codeBlock->constantRegisters[src2->index() - m_codeBlock->numVars].jsValue(m_scopeChain->globalObject()->globalExec())->isString()) {
817 const UString& value = asString(m_codeBlock->constantRegisters[src2->index() - m_codeBlock->numVars].jsValue(m_scopeChain->globalObject()->globalExec()))->value();
818 if (value == "undefined") {
820 emitOpcode(op_is_undefined);
821 instructions().append(dst->index());
822 instructions().append(srcIndex);
825 if (value == "boolean") {
827 emitOpcode(op_is_boolean);
828 instructions().append(dst->index());
829 instructions().append(srcIndex);
832 if (value == "number") {
834 emitOpcode(op_is_number);
835 instructions().append(dst->index());
836 instructions().append(srcIndex);
839 if (value == "string") {
841 emitOpcode(op_is_string);
842 instructions().append(dst->index());
843 instructions().append(srcIndex);
846 if (value == "object") {
848 emitOpcode(op_is_object);
849 instructions().append(dst->index());
850 instructions().append(srcIndex);
853 if (value == "function") {
855 emitOpcode(op_is_function);
856 instructions().append(dst->index());
857 instructions().append(srcIndex);
863 emitOpcode(opcodeID);
864 instructions().append(dst->index());
865 instructions().append(src1->index());
866 instructions().append(src2->index());
870 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
872 return emitLoad(dst, jsBoolean(b));
875 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
877 // FIXME: Our hash tables won't hold infinity, so we make a new JSNumberCell each time.
878 // Later we can do the extra work to handle that like the other cases.
879 if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
880 return emitLoad(dst, jsNumber(globalData(), number));
881 JSValue*& valueInMap = m_numberMap.add(number, noValue()).first->second;
883 valueInMap = jsNumber(globalData(), number);
884 return emitLoad(dst, valueInMap);
887 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
889 JSString*& valueInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second;
891 valueInMap = jsOwnedString(globalData(), identifier.ustring());
892 return emitLoad(dst, valueInMap);
895 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue* v)
897 RegisterID* constantID = addConstant(v);
899 return emitMove(dst, constantID);
903 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSCell* cell)
905 JSValue* value = cell;
906 return emitLoad(dst, value);
909 RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b)
911 emitOpcode(op_unexpected_load);
912 instructions().append(dst->index());
913 instructions().append(addUnexpectedConstant(jsBoolean(b)));
917 RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d)
919 emitOpcode(op_unexpected_load);
920 instructions().append(dst->index());
921 instructions().append(addUnexpectedConstant(jsNumber(globalData(), d)));
925 bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject)
927 // Cases where we cannot statically optimize the lookup.
928 if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
930 index = missingSymbolMarker();
932 if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
933 ScopeChainIterator iter = m_scopeChain->begin();
934 globalObject = *iter;
935 ASSERT((++iter) == m_scopeChain->end());
942 ScopeChainIterator iter = m_scopeChain->begin();
943 ScopeChainIterator end = m_scopeChain->end();
944 for (; iter != end; ++iter, ++depth) {
945 JSObject* currentScope = *iter;
946 if (!currentScope->isVariableObject())
948 JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
949 SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.ustring().rep());
951 // Found the property
952 if (!entry.isNull()) {
953 if (entry.isReadOnly() && forWriting) {
955 index = missingSymbolMarker();
957 globalObject = currentVariableObject;
961 index = entry.getIndex();
963 globalObject = currentVariableObject;
966 if (currentVariableObject->isDynamicScope())
970 // Can't locate the property but we're able to avoid a few lookups.
972 index = missingSymbolMarker();
973 JSObject* scope = *iter;
975 globalObject = scope;
979 RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
981 emitOpcode(op_instanceof);
982 instructions().append(dst->index());
983 instructions().append(value->index());
984 instructions().append(base->index());
985 instructions().append(basePrototype->index());
989 RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
993 JSObject* globalObject = 0;
994 if (!findScopedProperty(property, index, depth, false, globalObject) && !globalObject) {
995 // We can't optimise at all :-(
996 emitOpcode(op_resolve);
997 instructions().append(dst->index());
998 instructions().append(addConstant(property));
1002 if (index != missingSymbolMarker()) {
1003 // Directly index the property lookup across multiple scopes. Yay!
1004 return emitGetScopedVar(dst, depth, index, globalObject);
1008 m_codeBlock->globalResolveInstructions.append(instructions().size());
1009 emitOpcode(op_resolve_global);
1010 instructions().append(dst->index());
1011 instructions().append(globalObject);
1012 instructions().append(addConstant(property));
1013 instructions().append(0);
1014 instructions().append(0);
1018 // In this case we are at least able to drop a few scope chains from the
1019 // lookup chain, although we still need to hash from then on.
1020 emitOpcode(op_resolve_skip);
1021 instructions().append(dst->index());
1022 instructions().append(addConstant(property));
1023 instructions().append(depth);
1027 RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue* globalObject)
1030 emitOpcode(op_get_global_var);
1031 instructions().append(dst->index());
1032 instructions().append(asCell(globalObject));
1033 instructions().append(index);
1037 emitOpcode(op_get_scoped_var);
1038 instructions().append(dst->index());
1039 instructions().append(index);
1040 instructions().append(depth);
1044 RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue* globalObject)
1047 emitOpcode(op_put_global_var);
1048 instructions().append(asCell(globalObject));
1049 instructions().append(index);
1050 instructions().append(value->index());
1053 emitOpcode(op_put_scoped_var);
1054 instructions().append(index);
1055 instructions().append(depth);
1056 instructions().append(value->index());
1060 RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
1062 emitOpcode(op_resolve_base);
1063 instructions().append(dst->index());
1064 instructions().append(addConstant(property));
1068 RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
1070 emitOpcode(op_resolve_with_base);
1071 instructions().append(baseDst->index());
1072 instructions().append(propDst->index());
1073 instructions().append(addConstant(property));
1077 RegisterID* BytecodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
1079 emitOpcode(op_resolve_func);
1080 instructions().append(baseDst->index());
1081 instructions().append(funcDst->index());
1082 instructions().append(addConstant(property));
1086 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
1088 m_codeBlock->propertyAccessInstructions.append(instructions().size());
1090 emitOpcode(op_get_by_id);
1091 instructions().append(dst->index());
1092 instructions().append(base->index());
1093 instructions().append(addConstant(property));
1094 instructions().append(0);
1095 instructions().append(0);
1096 instructions().append(0);
1097 instructions().append(0);
1101 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1103 m_codeBlock->propertyAccessInstructions.append(instructions().size());
1105 emitOpcode(op_put_by_id);
1106 instructions().append(base->index());
1107 instructions().append(addConstant(property));
1108 instructions().append(value->index());
1109 instructions().append(0);
1110 instructions().append(0);
1111 instructions().append(0);
1112 instructions().append(0);
1116 RegisterID* BytecodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
1118 emitOpcode(op_put_getter);
1119 instructions().append(base->index());
1120 instructions().append(addConstant(property));
1121 instructions().append(value->index());
1125 RegisterID* BytecodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
1127 emitOpcode(op_put_setter);
1128 instructions().append(base->index());
1129 instructions().append(addConstant(property));
1130 instructions().append(value->index());
1134 RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
1136 emitOpcode(op_del_by_id);
1137 instructions().append(dst->index());
1138 instructions().append(base->index());
1139 instructions().append(addConstant(property));
1143 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1145 emitOpcode(op_get_by_val);
1146 instructions().append(dst->index());
1147 instructions().append(base->index());
1148 instructions().append(property->index());
1152 RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1154 emitOpcode(op_put_by_val);
1155 instructions().append(base->index());
1156 instructions().append(property->index());
1157 instructions().append(value->index());
1161 RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1163 emitOpcode(op_del_by_val);
1164 instructions().append(dst->index());
1165 instructions().append(base->index());
1166 instructions().append(property->index());
1170 RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1172 emitOpcode(op_put_by_index);
1173 instructions().append(base->index());
1174 instructions().append(index);
1175 instructions().append(value->index());
1179 RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
1181 emitOpcode(op_new_object);
1182 instructions().append(dst->index());
1186 RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements)
1188 Vector<RefPtr<RegisterID>, 16> argv;
1189 for (ElementNode* n = elements; n; n = n->next()) {
1192 argv.append(newTemporary());
1193 emitNode(argv.last().get(), n->value());
1195 emitOpcode(op_new_array);
1196 instructions().append(dst->index());
1197 instructions().append(argv.size() ? argv[0]->index() : 0); // argv
1198 instructions().append(argv.size()); // argc
1202 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n)
1204 emitOpcode(op_new_func);
1205 instructions().append(dst->index());
1206 instructions().append(addConstant(n));
1210 RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
1212 emitOpcode(op_new_regexp);
1213 instructions().append(dst->index());
1214 instructions().append(addRegExp(regExp));
1219 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
1221 emitOpcode(op_new_func_exp);
1222 instructions().append(r0->index());
1223 instructions().append(addConstant(n));
1227 RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1229 return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
1232 RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1234 return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
1237 RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1239 ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
1240 ASSERT(func->refCount());
1242 if (m_shouldEmitProfileHooks) {
1243 // If codegen decided to recycle func as this call's destination register,
1244 // we need to undo that optimization here so that func will still be around
1245 // for the sake of op_profile_did_call.
1247 RefPtr<RegisterID> protect = thisRegister;
1248 RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister);
1249 RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func);
1251 thisRegister = movedThisRegister.release().releaseRef();
1252 func = movedFunc.release().releaseRef();
1256 // Generate code for arguments.
1257 Vector<RefPtr<RegisterID>, 16> argv;
1258 argv.append(thisRegister);
1259 for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) {
1260 argv.append(newTemporary());
1261 emitNode(argv.last().get(), n);
1264 // Reserve space for call frame.
1265 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1266 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1267 callFrame.append(newTemporary());
1269 if (m_shouldEmitProfileHooks) {
1270 emitOpcode(op_profile_will_call);
1271 instructions().append(func->index());
1274 emitExpressionInfo(divot, startOffset, endOffset);
1275 m_codeBlock->callLinkInfos.append(CallLinkInfo());
1278 emitOpcode(opcodeID);
1279 instructions().append(dst->index()); // dst
1280 instructions().append(func->index()); // func
1281 instructions().append(argv.size()); // argCount
1282 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
1284 if (m_shouldEmitProfileHooks) {
1285 emitOpcode(op_profile_did_call);
1286 instructions().append(func->index());
1289 thisRegister->deref();
1297 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
1299 if (m_codeBlock->needsFullScopeChain) {
1300 emitOpcode(op_tear_off_activation);
1301 instructions().append(m_activationRegisterIndex);
1302 } else if (m_codeBlock->usesArguments && m_codeBlock->numParameters > 1)
1303 emitOpcode(op_tear_off_arguments);
1305 return emitUnaryNoDstOp(op_ret, src);
1308 RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src)
1310 emitOpcode(opcodeID);
1311 instructions().append(src->index());
1315 RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1317 ASSERT(func->refCount());
1319 if (m_shouldEmitProfileHooks) {
1320 // If codegen decided to recycle func as this call's destination register,
1321 // we need to undo that optimization here so that func will still be around
1322 // for the sake of op_profile_did_call.
1324 RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func);
1325 func = movedFunc.release().releaseRef();
1329 RefPtr<RegisterID> funcProto = newTemporary();
1331 // Generate code for arguments.
1332 Vector<RefPtr<RegisterID>, 16> argv;
1333 argv.append(newTemporary()); // reserve space for "this"
1334 for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() : 0; n; n = n->m_next.get()) {
1335 argv.append(newTemporary());
1336 emitNode(argv.last().get(), n);
1339 if (m_shouldEmitProfileHooks) {
1340 emitOpcode(op_profile_will_call);
1341 instructions().append(func->index());
1345 emitExpressionInfo(divot, startOffset, endOffset);
1346 emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype);
1348 // Reserve space for call frame.
1349 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1350 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1351 callFrame.append(newTemporary());
1353 emitExpressionInfo(divot, startOffset, endOffset);
1354 m_codeBlock->callLinkInfos.append(CallLinkInfo());
1356 emitOpcode(op_construct);
1357 instructions().append(dst->index()); // dst
1358 instructions().append(func->index()); // func
1359 instructions().append(argv.size()); // argCount
1360 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
1361 instructions().append(funcProto->index()); // proto
1362 instructions().append(argv[0]->index()); // thisRegister
1364 emitOpcode(op_construct_verify);
1365 instructions().append(dst->index());
1366 instructions().append(argv[0]->index());
1368 if (m_shouldEmitProfileHooks) {
1369 emitOpcode(op_profile_did_call);
1370 instructions().append(func->index());
1379 RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
1381 ControlFlowContext context;
1382 context.isFinallyBlock = false;
1383 m_scopeContextStack.append(context);
1384 m_dynamicScopeDepth++;
1386 return emitUnaryNoDstOp(op_push_scope, scope);
1389 void BytecodeGenerator::emitPopScope()
1391 ASSERT(m_scopeContextStack.size());
1392 ASSERT(!m_scopeContextStack.last().isFinallyBlock);
1394 emitOpcode(op_pop_scope);
1396 m_scopeContextStack.removeLast();
1397 m_dynamicScopeDepth--;
1400 void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine)
1402 if (!m_shouldEmitDebugHooks)
1404 emitOpcode(op_debug);
1405 instructions().append(debugHookID);
1406 instructions().append(firstLine);
1407 instructions().append(lastLine);
1410 void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst)
1412 ControlFlowContext scope;
1413 scope.isFinallyBlock = true;
1414 FinallyContext context = { target, retAddrDst };
1415 scope.finallyContext = context;
1416 m_scopeContextStack.append(scope);
1420 void BytecodeGenerator::popFinallyContext()
1422 ASSERT(m_scopeContextStack.size());
1423 ASSERT(m_scopeContextStack.last().isFinallyBlock);
1424 ASSERT(m_finallyDepth > 0);
1425 m_scopeContextStack.removeLast();
1429 LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
1431 // Reclaim free label scopes.
1432 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
1433 m_labelScopes.removeLast();
1435 if (!m_labelScopes.size())
1438 // We special-case the following, which is a syntax error in Firefox:
1441 if (name.isEmpty()) {
1442 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1443 LabelScope* scope = &m_labelScopes[i];
1444 if (scope->type() != LabelScope::NamedLabel) {
1445 ASSERT(scope->breakTarget());
1452 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1453 LabelScope* scope = &m_labelScopes[i];
1454 if (scope->name() && *scope->name() == name) {
1455 ASSERT(scope->breakTarget());
1462 LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
1464 // Reclaim free label scopes.
1465 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
1466 m_labelScopes.removeLast();
1468 if (!m_labelScopes.size())
1471 if (name.isEmpty()) {
1472 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1473 LabelScope* scope = &m_labelScopes[i];
1474 if (scope->type() == LabelScope::Loop) {
1475 ASSERT(scope->continueTarget());
1482 // Continue to the loop nested nearest to the label scope that matches
1484 LabelScope* result = 0;
1485 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1486 LabelScope* scope = &m_labelScopes[i];
1487 if (scope->type() == LabelScope::Loop) {
1488 ASSERT(scope->continueTarget());
1491 if (scope->name() && *scope->name() == name)
1492 return result; // may be 0
1497 PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
1499 while (topScope > bottomScope) {
1500 // First we count the number of dynamic scopes we need to remove to get
1501 // to a finally block.
1502 int nNormalScopes = 0;
1503 while (topScope > bottomScope) {
1504 if (topScope->isFinallyBlock)
1510 if (nNormalScopes) {
1511 // We need to remove a number of dynamic scopes to get to the next
1513 emitOpcode(op_jmp_scopes);
1514 instructions().append(nNormalScopes);
1516 // If topScope == bottomScope then there isn't actually a finally block
1517 // left to emit, so make the jmp_scopes jump directly to the target label
1518 if (topScope == bottomScope) {
1519 instructions().append(target->offsetFrom(instructions().size()));
1523 // Otherwise we just use jmp_scopes to pop a group of scopes and go
1524 // to the next instruction
1525 RefPtr<Label> nextInsn = newLabel();
1526 instructions().append(nextInsn->offsetFrom(instructions().size()));
1527 emitLabel(nextInsn.get());
1530 // To get here there must be at least one finally block present
1532 ASSERT(topScope->isFinallyBlock);
1533 emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
1535 if (!topScope->isFinallyBlock)
1537 } while (topScope > bottomScope);
1539 return emitJump(target);
1542 PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetScopeDepth)
1544 ASSERT(scopeDepth() - targetScopeDepth >= 0);
1545 ASSERT(target->isForward());
1547 size_t scopeDelta = scopeDepth() - targetScopeDepth;
1548 ASSERT(scopeDelta <= m_scopeContextStack.size());
1550 return emitJump(target);
1553 return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
1555 emitOpcode(op_jmp_scopes);
1556 instructions().append(scopeDelta);
1557 instructions().append(target->offsetFrom(instructions().size()));
1561 RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target)
1563 emitOpcode(op_next_pname);
1564 instructions().append(dst->index());
1565 instructions().append(iter->index());
1566 instructions().append(target->offsetFrom(instructions().size()));
1570 RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
1572 HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth, 0 };
1573 exceptionHandlers().append(info);
1574 emitOpcode(op_catch);
1575 instructions().append(targetRegister->index());
1576 return targetRegister;
1579 RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue* message)
1581 emitOpcode(op_new_error);
1582 instructions().append(dst->index());
1583 instructions().append(static_cast<int>(type));
1584 instructions().append(addUnexpectedConstant(message));
1588 PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
1591 instructions().append(retAddrDst->index());
1592 instructions().append(finally->offsetFrom(instructions().size()));
1596 void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
1598 emitOpcode(op_sret);
1599 instructions().append(retAddrSrc->index());
1602 void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value)
1604 ControlFlowContext context;
1605 context.isFinallyBlock = false;
1606 m_scopeContextStack.append(context);
1607 m_dynamicScopeDepth++;
1609 emitOpcode(op_push_new_scope);
1610 instructions().append(dst->index());
1611 instructions().append(addConstant(property));
1612 instructions().append(value->index());
1615 void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
1617 SwitchInfo info = { instructions().size(), type };
1619 case SwitchInfo::SwitchImmediate:
1620 emitOpcode(op_switch_imm);
1622 case SwitchInfo::SwitchCharacter:
1623 emitOpcode(op_switch_char);
1625 case SwitchInfo::SwitchString:
1626 emitOpcode(op_switch_string);
1629 ASSERT_NOT_REACHED();
1632 instructions().append(0); // place holder for table index
1633 instructions().append(0); // place holder for default target
1634 instructions().append(scrutineeRegister->index());
1635 m_switchContextStack.append(info);
1638 static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
1641 ASSERT(node->isNumber());
1642 double value = static_cast<NumberNode*>(node)->value();
1643 ASSERT(JSImmediate::from(value));
1644 int32_t key = static_cast<int32_t>(value);
1645 ASSERT(key == value);
1651 static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1653 jumpTable.min = min;
1654 jumpTable.branchOffsets.resize(max - min + 1);
1655 jumpTable.branchOffsets.fill(0);
1656 for (uint32_t i = 0; i < clauseCount; ++i) {
1657 // We're emitting this after the clause labels should have been fixed, so
1658 // the labels should not be "forward" references
1659 ASSERT(!labels[i]->isForward());
1660 jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress));
1664 static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
1667 ASSERT(node->isString());
1668 UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep();
1669 ASSERT(clause->size() == 1);
1671 int32_t key = clause->data()[0];
1677 static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1679 jumpTable.min = min;
1680 jumpTable.branchOffsets.resize(max - min + 1);
1681 jumpTable.branchOffsets.fill(0);
1682 for (uint32_t i = 0; i < clauseCount; ++i) {
1683 // We're emitting this after the clause labels should have been fixed, so
1684 // the labels should not be "forward" references
1685 ASSERT(!labels[i]->isForward());
1686 jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress));
1690 static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
1692 for (uint32_t i = 0; i < clauseCount; ++i) {
1693 // We're emitting this after the clause labels should have been fixed, so
1694 // the labels should not be "forward" references
1695 ASSERT(!labels[i]->isForward());
1697 ASSERT(nodes[i]->isString());
1698 UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
1699 OffsetLocation location;
1700 location.branchOffset = labels[i]->offsetFrom(switchAddress);
1702 location.ctiOffset = 0;
1704 jumpTable.offsetTable.add(clause, location);
1708 void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max)
1710 SwitchInfo switchInfo = m_switchContextStack.last();
1711 m_switchContextStack.removeLast();
1712 if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
1713 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->immediateSwitchJumpTables.size();
1714 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
1716 m_codeBlock->immediateSwitchJumpTables.append(SimpleJumpTable());
1717 SimpleJumpTable& jumpTable = m_codeBlock->immediateSwitchJumpTables.last();
1719 prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
1720 } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
1721 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->characterSwitchJumpTables.size();
1722 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
1724 m_codeBlock->characterSwitchJumpTables.append(SimpleJumpTable());
1725 SimpleJumpTable& jumpTable = m_codeBlock->characterSwitchJumpTables.last();
1727 prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
1729 ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
1730 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->stringSwitchJumpTables.size();
1731 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
1733 m_codeBlock->stringSwitchJumpTables.append(StringJumpTable());
1734 StringJumpTable& jumpTable = m_codeBlock->stringSwitchJumpTables.last();
1736 prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes);
1740 RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
1742 // It would be nice to do an even better job of identifying exactly where the expression is.
1743 // And we could make the caller pass the node pointer in, if there was some way of getting
1744 // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
1745 // is still good enough to get us an accurate line number.
1746 emitExpressionInfo(0, 0, 0);
1747 RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep"));
1748 emitThrow(exception);