]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecompiler/BytecodeGenerator.cpp
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / bytecompiler / BytecodeGenerator.cpp
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
17 *
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.
28 */
29
30#include "config.h"
31#include "BytecodeGenerator.h"
32
33#include "BatchedTransitionOptimizer.h"
34#include "JSFunction.h"
35#include "Interpreter.h"
14957cd0 36#include "ScopeChain.h"
9dae56ea
A
37#include "UString.h"
38
39using namespace std;
40
41namespace JSC {
42
43/*
44 The layout of a register frame looks like this:
45
46 For
47
48 function f(x, y) {
49 var v1;
50 function g() { }
51 var v2;
52 return (x) * (y);
53 }
54
55 assuming (x) and (y) generated temporaries t1 and t2, you would have
56
57 ------------------------------------
58 | x | y | g | v2 | v1 | t1 | t2 | <-- value held
59 ------------------------------------
60 | -5 | -4 | -3 | -2 | -1 | +0 | +1 | <-- register index
61 ------------------------------------
62 | params->|<-locals | temps->
63
64 Because temporary registers are allocated in a stack-like fashion, we
65 can reclaim them with a simple popping algorithm. The same goes for labels.
66 (We never reclaim parameter or local registers, because parameters and
67 locals are DontDelete.)
68
69 The register layout before a function call looks like this:
70
71 For
72
73 function f(x, y)
74 {
75 }
76
77 f(1);
78
79 > <------------------------------
80 < > reserved: call frame | 1 | <-- value held
81 > >snip< <------------------------------
82 < > +0 | +1 | +2 | +3 | +4 | +5 | <-- register index
83 > <------------------------------
84 | params->|<-locals | temps->
85
86 The call instruction fills in the "call frame" registers. It also pads
87 missing arguments at the end of the call:
88
89 > <-----------------------------------
90 < > reserved: call frame | 1 | ? | <-- value held ("?" stands for "undefined")
91 > >snip< <-----------------------------------
92 < > +0 | +1 | +2 | +3 | +4 | +5 | +6 | <-- register index
93 > <-----------------------------------
94 | params->|<-locals | temps->
95
96 After filling in missing arguments, the call instruction sets up the new
97 stack frame to overlap the end of the old stack frame:
98
99 |----------------------------------> <
100 | reserved: call frame | 1 | ? < > <-- value held ("?" stands for "undefined")
101 |----------------------------------> >snip< <
102 | -7 | -6 | -5 | -4 | -3 | -2 | -1 < > <-- register index
103 |----------------------------------> <
104 | | params->|<-locals | temps->
105
106 That way, arguments are "copied" into the callee's stack frame for free.
107
108 If the caller supplies too many arguments, this trick doesn't work. The
109 extra arguments protrude into space reserved for locals and temporaries.
110 In that case, the call instruction makes a real copy of the call frame header,
111 along with just the arguments expected by the callee, leaving the original
112 call frame header and arguments behind. (The call instruction can't just discard
113 extra arguments, because the "arguments" object may access them later.)
114 This copying strategy ensures that all named values will be at the indices
115 expected by the callee.
116*/
117
118#ifndef NDEBUG
119static bool s_dumpsGeneratedCode = false;
120#endif
121
122void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
123{
124#ifndef NDEBUG
125 s_dumpsGeneratedCode = dumpsGeneratedCode;
126#else
127 UNUSED_PARAM(dumpsGeneratedCode);
128#endif
129}
130
131bool BytecodeGenerator::dumpsGeneratedCode()
132{
133#ifndef NDEBUG
134 return s_dumpsGeneratedCode;
135#else
136 return false;
137#endif
138}
139
14957cd0 140JSObject* BytecodeGenerator::generate()
9dae56ea
A
141{
142 m_codeBlock->setThisRegister(m_thisRegister.index());
143
144 m_scopeNode->emitBytecode(*this);
145
146#ifndef NDEBUG
147 m_codeBlock->setInstructionCount(m_codeBlock->instructions().size());
148
149 if (s_dumpsGeneratedCode)
14957cd0 150 m_codeBlock->dump(m_scopeChain->globalObject->globalExec());
9dae56ea
A
151#endif
152
153 if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
154 symbolTable().clear();
9dae56ea
A
155
156 m_codeBlock->shrinkToFit();
14957cd0
A
157
158 if (m_expressionTooDeep)
159 return createOutOfMemoryError(m_scopeChain->globalObject.get());
160 return 0;
9dae56ea
A
161}
162
163bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
164{
165 int index = m_calleeRegisters.size();
166 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
14957cd0 167 pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry);
9dae56ea
A
168
169 if (!result.second) {
170 r0 = &registerFor(result.first->second.getIndex());
171 return false;
172 }
173
14957cd0 174 r0 = addVar();
9dae56ea
A
175 return true;
176}
177
178bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
179{
180 int index = m_nextGlobalIndex;
181 SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
14957cd0 182 pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry);
9dae56ea
A
183
184 if (!result.second)
185 index = result.first->second.getIndex();
186 else {
187 --m_nextGlobalIndex;
188 m_globals.append(index + m_globalVarStorageOffset);
189 }
190
191 r0 = &registerFor(index);
192 return result.second;
193}
194
ba379fdc 195void BytecodeGenerator::preserveLastVar()
9dae56ea 196{
ba379fdc
A
197 if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
198 m_lastVar = &m_calleeRegisters.last();
9dae56ea
A
199}
200
14957cd0
A
201BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
202 : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
203 , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
204 , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
205 , m_scopeChain(*scopeChain->globalData, scopeChain)
9dae56ea
A
206 , m_symbolTable(symbolTable)
207 , m_scopeNode(programNode)
208 , m_codeBlock(codeBlock)
209 , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
210 , m_finallyDepth(0)
211 , m_dynamicScopeDepth(0)
212 , m_baseScopeDepth(0)
213 , m_codeType(GlobalCode)
214 , m_nextGlobalIndex(-1)
ba379fdc
A
215 , m_nextConstantOffset(0)
216 , m_globalConstantIndex(0)
14957cd0
A
217 , m_hasCreatedActivation(true)
218 , m_firstLazyFunction(0)
219 , m_lastLazyFunction(0)
220 , m_globalData(scopeChain->globalData)
9dae56ea 221 , m_lastOpcodeID(op_end)
14957cd0
A
222#ifndef NDEBUG
223 , m_lastOpcodePosition(0)
224#endif
225 , m_stack(m_globalData->stack())
226 , m_usesExceptions(false)
227 , m_expressionTooDeep(false)
9dae56ea
A
228{
229 if (m_shouldEmitDebugHooks)
230 m_codeBlock->setNeedsFullScopeChain(true);
231
232 emitOpcode(op_enter);
233 codeBlock->setGlobalData(m_globalData);
234
235 // FIXME: Move code that modifies the global object to Interpreter::execute.
236
237 m_codeBlock->m_numParameters = 1; // Allocate space for "this"
238
14957cd0 239 JSGlobalObject* globalObject = scopeChain->globalObject.get();
9dae56ea
A
240 ExecState* exec = globalObject->globalExec();
241 RegisterFile* registerFile = &exec->globalData().interpreter->registerFile();
242
243 // Shift register indexes in generated code to elide registers allocated by intermediate stack frames.
244 m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters - registerFile->size();
245
246 // Add previously defined symbols to bookkeeping.
247 m_globals.grow(symbolTable->size());
248 SymbolTable::iterator end = symbolTable->end();
249 for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
250 registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset);
14957cd0
A
251
252 BatchedTransitionOptimizer optimizer(*m_globalData, globalObject);
9dae56ea
A
253
254 const VarStack& varStack = programNode->varStack();
255 const FunctionStack& functionStack = programNode->functionStack();
256 bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals();
257 if (canOptimizeNewGlobals) {
258 // Shift new symbols so they get stored prior to existing symbols.
259 m_nextGlobalIndex -= symbolTable->size();
260
14957cd0
A
261 HashSet<StringImpl*, IdentifierRepHash> newGlobals;
262 Vector<std::pair<int, bool>, 16> functionInfo(functionStack.size());
263 for (size_t i = 0; i < functionStack.size(); ++i) {
264 FunctionBodyNode* function = functionStack[i];
265 globalObject->removeDirect(*m_globalData, function->ident()); // Make sure our new function is not shadowed by an old property.
266 SymbolTableEntry entry = symbolTable->inlineGet(function->ident().impl());
267
268 if (entry.isNull())
269 newGlobals.add(function->ident().impl());
270 functionInfo[i] = make_pair(entry.getIndex(), entry.isReadOnly());
271 }
272
273 Vector<bool, 16> shouldCreateVar(varStack.size());
274 for (size_t i = 0; i < varStack.size(); ++i) {
275 if (newGlobals.contains(varStack[i].first->impl()) || globalObject->hasProperty(exec, *varStack[i].first)) {
276 shouldCreateVar[i] = false;
277 continue;
278 }
279 shouldCreateVar[i] = true;
280 newGlobals.add(varStack[i].first->impl());
281 }
282
283 int expectedSize = symbolTable->size() + newGlobals.size();
284 globalObject->resizeRegisters(symbolTable->size(), expectedSize);
285
9dae56ea 286 for (size_t i = 0; i < functionStack.size(); ++i) {
f9bf01c6 287 FunctionBodyNode* function = functionStack[i];
14957cd0
A
288 if (functionInfo[i].second)
289 continue;
290 RegisterID* dst = addGlobalVar(function->ident(), false);
291 JSValue value = new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain);
292 globalObject->registerAt(dst->index() - m_globalVarStorageOffset).set(*m_globalData, globalObject, value);
9dae56ea
A
293 }
294
14957cd0
A
295 for (size_t i = 0; i < varStack.size(); ++i) {
296 if (!shouldCreateVar[i])
297 continue;
298 addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
299 }
300 if (symbolTable->size() != expectedSize)
301 CRASH();
9dae56ea 302
ba379fdc 303 preserveLastVar();
9dae56ea
A
304 } else {
305 for (size_t i = 0; i < functionStack.size(); ++i) {
f9bf01c6 306 FunctionBodyNode* function = functionStack[i];
14957cd0 307 globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain), DontDelete);
9dae56ea
A
308 }
309 for (size_t i = 0; i < varStack.size(); ++i) {
14957cd0 310 if (globalObject->symbolTableHasProperty(*varStack[i].first) || globalObject->hasProperty(exec, *varStack[i].first))
9dae56ea
A
311 continue;
312 int attributes = DontDelete;
313 if (varStack[i].second & DeclarationStacks::IsConstant)
314 attributes |= ReadOnly;
f9bf01c6 315 globalObject->putWithAttributes(exec, *varStack[i].first, jsUndefined(), attributes);
9dae56ea
A
316 }
317
ba379fdc 318 preserveLastVar();
9dae56ea 319 }
14957cd0 320 codeBlock->m_numCapturedVars = codeBlock->m_numVars;
9dae56ea
A
321}
322
14957cd0
A
323BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainNode* scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
324 : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
325 , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
326 , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
327 , m_scopeChain(*scopeChain->globalData, scopeChain)
9dae56ea
A
328 , m_symbolTable(symbolTable)
329 , m_scopeNode(functionBody)
330 , m_codeBlock(codeBlock)
14957cd0 331 , m_activationRegister(0)
9dae56ea
A
332 , m_finallyDepth(0)
333 , m_dynamicScopeDepth(0)
334 , m_baseScopeDepth(0)
335 , m_codeType(FunctionCode)
ba379fdc
A
336 , m_nextConstantOffset(0)
337 , m_globalConstantIndex(0)
14957cd0
A
338 , m_hasCreatedActivation(false)
339 , m_firstLazyFunction(0)
340 , m_lastLazyFunction(0)
341 , m_globalData(scopeChain->globalData)
9dae56ea 342 , m_lastOpcodeID(op_end)
14957cd0
A
343#ifndef NDEBUG
344 , m_lastOpcodePosition(0)
345#endif
346 , m_stack(m_globalData->stack())
347 , m_usesExceptions(false)
348 , m_expressionTooDeep(false)
9dae56ea
A
349{
350 if (m_shouldEmitDebugHooks)
351 m_codeBlock->setNeedsFullScopeChain(true);
352
353 codeBlock->setGlobalData(m_globalData);
14957cd0
A
354
355 emitOpcode(op_enter);
356 if (m_codeBlock->needsFullScopeChain()) {
357 m_activationRegister = addVar();
358 emitInitLazyRegister(m_activationRegister);
359 m_codeBlock->setActivationRegister(m_activationRegister->index());
9dae56ea
A
360 }
361
14957cd0
A
362 // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
363 // object, if created.
364 if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) {
365 RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
366 RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'.
367
368 // We can save a little space by hard-coding the knowledge that the two
369 // 'arguments' values are stored in consecutive registers, and storing
370 // only the index of the assignable one.
371 codeBlock->setArgumentsRegister(argumentsRegister->index());
372 ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
9dae56ea 373
14957cd0
A
374 emitInitLazyRegister(argumentsRegister);
375 emitInitLazyRegister(unmodifiedArgumentsRegister);
376
377 if (m_codeBlock->isStrictMode()) {
378 emitOpcode(op_create_arguments);
379 instructions().append(argumentsRegister->index());
380 }
ba379fdc
A
381
382 // The debugger currently retrieves the arguments object from an activation rather than pulling
383 // it from a call frame. In the long-term it should stop doing that (<rdar://problem/6911886>),
384 // but for now we force eager creation of the arguments object when debugging.
14957cd0 385 if (m_shouldEmitDebugHooks) {
ba379fdc 386 emitOpcode(op_create_arguments);
14957cd0
A
387 instructions().append(argumentsRegister->index());
388 }
ba379fdc 389 }
9dae56ea
A
390
391 const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
14957cd0
A
392 const DeclarationStacks::VarStack& varStack = functionBody->varStack();
393
394 // Captured variables and functions go first so that activations don't have
395 // to step over the non-captured locals to mark them.
396 m_hasCreatedActivation = false;
397 if (functionBody->hasCapturedVariables()) {
398 for (size_t i = 0; i < functionStack.size(); ++i) {
399 FunctionBodyNode* function = functionStack[i];
400 const Identifier& ident = function->ident();
401 if (functionBody->captures(ident)) {
402 if (!m_hasCreatedActivation) {
403 m_hasCreatedActivation = true;
404 emitOpcode(op_create_activation);
405 instructions().append(m_activationRegister->index());
406 }
407 m_functions.add(ident.impl());
408 emitNewFunction(addVar(ident, false), function);
409 }
410 }
411 for (size_t i = 0; i < varStack.size(); ++i) {
412 const Identifier& ident = *varStack[i].first;
413 if (functionBody->captures(ident))
414 addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
415 }
416 }
417 bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
418 if (!canLazilyCreateFunctions && !m_hasCreatedActivation) {
419 m_hasCreatedActivation = true;
420 emitOpcode(op_create_activation);
421 instructions().append(m_activationRegister->index());
422 }
423
424 codeBlock->m_numCapturedVars = codeBlock->m_numVars;
425 m_firstLazyFunction = codeBlock->m_numVars;
9dae56ea 426 for (size_t i = 0; i < functionStack.size(); ++i) {
f9bf01c6
A
427 FunctionBodyNode* function = functionStack[i];
428 const Identifier& ident = function->ident();
14957cd0
A
429 if (!functionBody->captures(ident)) {
430 m_functions.add(ident.impl());
431 RefPtr<RegisterID> reg = addVar(ident, false);
432 // Don't lazily create functions that override the name 'arguments'
433 // as this would complicate lazy instantiation of actual arguments.
434 if (!canLazilyCreateFunctions || ident == propertyNames().arguments)
435 emitNewFunction(reg.get(), function);
436 else {
437 emitInitLazyRegister(reg.get());
438 m_lazyFunctions.set(reg->index(), function);
439 }
440 }
9dae56ea 441 }
14957cd0
A
442 m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
443 for (size_t i = 0; i < varStack.size(); ++i) {
444 const Identifier& ident = *varStack[i].first;
445 if (!functionBody->captures(ident))
446 addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
447 }
448
449 if (m_shouldEmitDebugHooks)
450 codeBlock->m_numCapturedVars = codeBlock->m_numVars;
9dae56ea 451
f9bf01c6
A
452 FunctionParameters& parameters = *functionBody->parameters();
453 size_t parameterCount = parameters.size();
14957cd0 454 int nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
9dae56ea
A
455 m_parameters.grow(1 + parameterCount); // reserve space for "this"
456
457 // Add "this" as a parameter
14957cd0 458 m_thisRegister.setIndex(nextParameterIndex);
9dae56ea 459 ++m_codeBlock->m_numParameters;
9dae56ea
A
460
461 for (size_t i = 0; i < parameterCount; ++i)
14957cd0 462 addParameter(parameters[i], ++nextParameterIndex);
9dae56ea 463
ba379fdc 464 preserveLastVar();
14957cd0
A
465
466 if (isConstructor()) {
467 RefPtr<RegisterID> func = newTemporary();
468 RefPtr<RegisterID> funcProto = newTemporary();
469
470 emitOpcode(op_get_callee);
471 instructions().append(func->index());
472 // Load prototype.
473 emitGetById(funcProto.get(), func.get(), globalData()->propertyNames->prototype);
474
475 emitOpcode(op_create_this);
476 instructions().append(m_thisRegister.index());
477 instructions().append(funcProto->index());
478 } else if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
479 if (codeBlock->isStrictMode())
480 emitOpcode(op_convert_this_strict);
481 else
482 emitOpcode(op_convert_this);
483 instructions().append(m_thisRegister.index());
484 }
9dae56ea
A
485}
486
14957cd0
A
487BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
488 : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
489 , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
490 , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
491 , m_scopeChain(*scopeChain->globalData, scopeChain)
9dae56ea
A
492 , m_symbolTable(symbolTable)
493 , m_scopeNode(evalNode)
494 , m_codeBlock(codeBlock)
495 , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
496 , m_finallyDepth(0)
497 , m_dynamicScopeDepth(0)
498 , m_baseScopeDepth(codeBlock->baseScopeDepth())
499 , m_codeType(EvalCode)
ba379fdc
A
500 , m_nextConstantOffset(0)
501 , m_globalConstantIndex(0)
14957cd0
A
502 , m_hasCreatedActivation(true)
503 , m_firstLazyFunction(0)
504 , m_lastLazyFunction(0)
505 , m_globalData(scopeChain->globalData)
9dae56ea 506 , m_lastOpcodeID(op_end)
14957cd0
A
507#ifndef NDEBUG
508 , m_lastOpcodePosition(0)
509#endif
510 , m_stack(m_globalData->stack())
511 , m_usesExceptions(false)
512 , m_expressionTooDeep(false)
9dae56ea
A
513{
514 if (m_shouldEmitDebugHooks || m_baseScopeDepth)
515 m_codeBlock->setNeedsFullScopeChain(true);
516
517 emitOpcode(op_enter);
518 codeBlock->setGlobalData(m_globalData);
519 m_codeBlock->m_numParameters = 1; // Allocate space for "this"
520
f9bf01c6
A
521 const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
522 for (size_t i = 0; i < functionStack.size(); ++i)
523 m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i]));
524
525 const DeclarationStacks::VarStack& varStack = evalNode->varStack();
526 unsigned numVariables = varStack.size();
527 Vector<Identifier> variables;
528 variables.reserveCapacity(numVariables);
529 for (size_t i = 0; i < numVariables; ++i)
530 variables.append(*varStack[i].first);
531 codeBlock->adoptVariables(variables);
14957cd0 532 codeBlock->m_numCapturedVars = codeBlock->m_numVars;
ba379fdc 533 preserveLastVar();
9dae56ea
A
534}
535
14957cd0
A
536RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg)
537{
538 emitOpcode(op_init_lazy_reg);
539 instructions().append(reg->index());
540 return reg;
541}
542
543void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex)
9dae56ea
A
544{
545 // Parameters overwrite var declarations, but not function declarations.
14957cd0 546 StringImpl* rep = ident.impl();
9dae56ea 547 if (!m_functions.contains(rep)) {
14957cd0
A
548 symbolTable().set(rep, parameterIndex);
549 RegisterID& parameter = registerFor(parameterIndex);
550 parameter.setIndex(parameterIndex);
9dae56ea
A
551 }
552
553 // To maintain the calling convention, we have to allocate unique space for
554 // each parameter, even if the parameter doesn't make it into the symbol table.
9dae56ea 555 ++m_codeBlock->m_numParameters;
9dae56ea
A
556}
557
558RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
559{
560 if (ident == propertyNames().thisIdentifier)
561 return &m_thisRegister;
562
563 if (!shouldOptimizeLocals())
564 return 0;
565
14957cd0 566 SymbolTableEntry entry = symbolTable().get(ident.impl());
9dae56ea
A
567 if (entry.isNull())
568 return 0;
569
ba379fdc
A
570 if (ident == propertyNames().arguments)
571 createArgumentsIfNecessary();
572
14957cd0 573 return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
ba379fdc
A
574}
575
576bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
577{
578 if (ident != propertyNames().arguments)
579 return false;
580
581 if (!shouldOptimizeLocals())
582 return false;
583
14957cd0 584 SymbolTableEntry entry = symbolTable().get(ident.impl());
ba379fdc
A
585 if (entry.isNull())
586 return false;
587
588 if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
589 return true;
590
591 return false;
592}
593
594RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
595{
596 ASSERT(willResolveToArguments(propertyNames().arguments));
597
14957cd0 598 SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.impl());
ba379fdc 599 ASSERT(!entry.isNull());
9dae56ea
A
600 return &registerFor(entry.getIndex());
601}
602
14957cd0
A
603RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
604{
605 if (m_lastLazyFunction <= reg->index() || reg->index() < m_firstLazyFunction)
606 return reg;
607 emitLazyNewFunction(reg, m_lazyFunctions.get(reg->index()));
608 return reg;
609}
610
9dae56ea
A
611RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
612{
613 if (m_codeType == EvalCode)
614 return 0;
615
14957cd0 616 SymbolTableEntry entry = symbolTable().get(ident.impl());
f9bf01c6
A
617 if (entry.isNull())
618 return 0;
9dae56ea 619
14957cd0 620 return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
9dae56ea
A
621}
622
623bool BytecodeGenerator::isLocal(const Identifier& ident)
624{
625 if (ident == propertyNames().thisIdentifier)
626 return true;
627
14957cd0 628 return shouldOptimizeLocals() && symbolTable().contains(ident.impl());
9dae56ea
A
629}
630
631bool BytecodeGenerator::isLocalConstant(const Identifier& ident)
632{
14957cd0 633 return symbolTable().get(ident.impl()).isReadOnly();
9dae56ea
A
634}
635
636RegisterID* BytecodeGenerator::newRegister()
637{
638 m_calleeRegisters.append(m_calleeRegisters.size());
639 m_codeBlock->m_numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size());
640 return &m_calleeRegisters.last();
641}
642
643RegisterID* BytecodeGenerator::newTemporary()
644{
645 // Reclaim free register IDs.
646 while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
647 m_calleeRegisters.removeLast();
648
649 RegisterID* result = newRegister();
650 result->setTemporary();
651 return result;
652}
653
654RegisterID* BytecodeGenerator::highestUsedRegister()
655{
656 size_t count = m_codeBlock->m_numCalleeRegisters;
657 while (m_calleeRegisters.size() < count)
658 newRegister();
659 return &m_calleeRegisters.last();
660}
661
662PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
663{
664 // Reclaim free label scopes.
665 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
666 m_labelScopes.removeLast();
667
668 // Allocate new label scope.
f9bf01c6 669 LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
9dae56ea
A
670 m_labelScopes.append(scope);
671 return &m_labelScopes.last();
672}
673
674PassRefPtr<Label> BytecodeGenerator::newLabel()
675{
676 // Reclaim free label IDs.
677 while (m_labels.size() && !m_labels.last().refCount())
678 m_labels.removeLast();
679
680 // Allocate new label ID.
681 m_labels.append(m_codeBlock);
682 return &m_labels.last();
683}
684
685PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
686{
687 unsigned newLabelIndex = instructions().size();
688 l0->setLocation(newLabelIndex);
689
690 if (m_codeBlock->numberOfJumpTargets()) {
691 unsigned lastLabelIndex = m_codeBlock->lastJumpTarget();
692 ASSERT(lastLabelIndex <= newLabelIndex);
693 if (newLabelIndex == lastLabelIndex) {
694 // Peephole optimizations have already been disabled by emitting the last label
695 return l0;
696 }
697 }
698
699 m_codeBlock->addJumpTarget(newLabelIndex);
700
701 // This disables peephole optimizations when an instruction is a jump target
702 m_lastOpcodeID = op_end;
703 return l0;
704}
705
706void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
707{
14957cd0
A
708#ifndef NDEBUG
709 size_t opcodePosition = instructions().size();
710 ASSERT(opcodePosition - m_lastOpcodePosition == opcodeLength(m_lastOpcodeID) || m_lastOpcodeID == op_end);
711 m_lastOpcodePosition = opcodePosition;
712#endif
9dae56ea
A
713 instructions().append(globalData()->interpreter->getOpcode(opcodeID));
714 m_lastOpcodeID = opcodeID;
715}
716
717void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
718{
719 ASSERT(instructions().size() >= 4);
720 size_t size = instructions().size();
721 dstIndex = instructions().at(size - 3).u.operand;
722 src1Index = instructions().at(size - 2).u.operand;
723 src2Index = instructions().at(size - 1).u.operand;
724}
725
726void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
727{
728 ASSERT(instructions().size() >= 3);
729 size_t size = instructions().size();
730 dstIndex = instructions().at(size - 2).u.operand;
731 srcIndex = instructions().at(size - 1).u.operand;
732}
733
734void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
735{
736 ASSERT(instructions().size() >= 4);
737 instructions().shrink(instructions().size() - 4);
14957cd0 738 m_lastOpcodeID = op_end;
9dae56ea
A
739}
740
741void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
742{
743 ASSERT(instructions().size() >= 3);
744 instructions().shrink(instructions().size() - 3);
14957cd0 745 m_lastOpcodeID = op_end;
9dae56ea
A
746}
747
748PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
749{
f9bf01c6 750 size_t begin = instructions().size();
9dae56ea 751 emitOpcode(target->isForward() ? op_jmp : op_loop);
f9bf01c6 752 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
753 return target;
754}
755
756PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
757{
f9bf01c6 758 if (m_lastOpcodeID == op_less) {
9dae56ea
A
759 int dstIndex;
760 int src1Index;
761 int src2Index;
762
763 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
764
765 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
766 rewindBinaryOp();
f9bf01c6
A
767
768 size_t begin = instructions().size();
769 emitOpcode(target->isForward() ? op_jless : op_loop_if_less);
9dae56ea
A
770 instructions().append(src1Index);
771 instructions().append(src2Index);
f9bf01c6 772 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
773 return target;
774 }
4e4e5a6f 775 } else if (m_lastOpcodeID == op_lesseq) {
9dae56ea
A
776 int dstIndex;
777 int src1Index;
778 int src2Index;
779
780 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
781
782 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
783 rewindBinaryOp();
f9bf01c6
A
784
785 size_t begin = instructions().size();
4e4e5a6f 786 emitOpcode(target->isForward() ? op_jlesseq : op_loop_if_lesseq);
9dae56ea
A
787 instructions().append(src1Index);
788 instructions().append(src2Index);
f9bf01c6 789 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
790 return target;
791 }
792 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
793 int dstIndex;
794 int srcIndex;
795
796 retrieveLastUnaryOp(dstIndex, srcIndex);
797
798 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
799 rewindUnaryOp();
f9bf01c6
A
800
801 size_t begin = instructions().size();
9dae56ea
A
802 emitOpcode(op_jeq_null);
803 instructions().append(srcIndex);
f9bf01c6 804 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
805 return target;
806 }
807 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
808 int dstIndex;
809 int srcIndex;
810
811 retrieveLastUnaryOp(dstIndex, srcIndex);
812
813 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
814 rewindUnaryOp();
f9bf01c6
A
815
816 size_t begin = instructions().size();
9dae56ea
A
817 emitOpcode(op_jneq_null);
818 instructions().append(srcIndex);
f9bf01c6 819 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
820 return target;
821 }
822 }
823
f9bf01c6
A
824 size_t begin = instructions().size();
825
9dae56ea
A
826 emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
827 instructions().append(cond->index());
f9bf01c6 828 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
829 return target;
830}
831
832PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
833{
f9bf01c6 834 if (m_lastOpcodeID == op_less && target->isForward()) {
9dae56ea
A
835 int dstIndex;
836 int src1Index;
837 int src2Index;
838
839 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
840
841 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
842 rewindBinaryOp();
f9bf01c6
A
843
844 size_t begin = instructions().size();
9dae56ea
A
845 emitOpcode(op_jnless);
846 instructions().append(src1Index);
847 instructions().append(src2Index);
f9bf01c6 848 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
849 return target;
850 }
f9bf01c6 851 } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
ba379fdc
A
852 int dstIndex;
853 int src1Index;
854 int src2Index;
855
856 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
857
858 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
859 rewindBinaryOp();
f9bf01c6
A
860
861 size_t begin = instructions().size();
ba379fdc
A
862 emitOpcode(op_jnlesseq);
863 instructions().append(src1Index);
864 instructions().append(src2Index);
f9bf01c6 865 instructions().append(target->bind(begin, instructions().size()));
ba379fdc
A
866 return target;
867 }
9dae56ea
A
868 } else if (m_lastOpcodeID == op_not) {
869 int dstIndex;
870 int srcIndex;
871
872 retrieveLastUnaryOp(dstIndex, srcIndex);
873
874 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
875 rewindUnaryOp();
f9bf01c6
A
876
877 size_t begin = instructions().size();
878 emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
9dae56ea 879 instructions().append(srcIndex);
f9bf01c6 880 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
881 return target;
882 }
f9bf01c6 883 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
9dae56ea
A
884 int dstIndex;
885 int srcIndex;
886
887 retrieveLastUnaryOp(dstIndex, srcIndex);
888
889 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
890 rewindUnaryOp();
f9bf01c6
A
891
892 size_t begin = instructions().size();
9dae56ea
A
893 emitOpcode(op_jneq_null);
894 instructions().append(srcIndex);
f9bf01c6 895 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
896 return target;
897 }
f9bf01c6 898 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
9dae56ea
A
899 int dstIndex;
900 int srcIndex;
901
902 retrieveLastUnaryOp(dstIndex, srcIndex);
903
904 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
905 rewindUnaryOp();
f9bf01c6
A
906
907 size_t begin = instructions().size();
9dae56ea
A
908 emitOpcode(op_jeq_null);
909 instructions().append(srcIndex);
f9bf01c6 910 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
911 return target;
912 }
913 }
914
f9bf01c6
A
915 size_t begin = instructions().size();
916 emitOpcode(target->isForward() ? op_jfalse : op_loop_if_false);
9dae56ea 917 instructions().append(cond->index());
f9bf01c6 918 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
919 return target;
920}
921
ba379fdc
A
922PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
923{
f9bf01c6
A
924 size_t begin = instructions().size();
925
ba379fdc
A
926 emitOpcode(op_jneq_ptr);
927 instructions().append(cond->index());
14957cd0 928 instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->callFunction()));
f9bf01c6 929 instructions().append(target->bind(begin, instructions().size()));
ba379fdc
A
930 return target;
931}
932
933PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
934{
f9bf01c6
A
935 size_t begin = instructions().size();
936
ba379fdc
A
937 emitOpcode(op_jneq_ptr);
938 instructions().append(cond->index());
14957cd0 939 instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->applyFunction()));
f9bf01c6 940 instructions().append(target->bind(begin, instructions().size()));
ba379fdc
A
941 return target;
942}
943
9dae56ea
A
944unsigned BytecodeGenerator::addConstant(const Identifier& ident)
945{
14957cd0 946 StringImpl* rep = ident.impl();
9dae56ea
A
947 pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
948 if (result.second) // new entry
949 m_codeBlock->addIdentifier(Identifier(m_globalData, rep));
950
951 return result.first->second;
952}
953
ba379fdc 954RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
9dae56ea 955{
ba379fdc 956 int index = m_nextConstantOffset;
9dae56ea 957
ba379fdc
A
958 pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
959 if (result.second) {
960 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
961 ++m_nextConstantOffset;
14957cd0 962 m_codeBlock->addConstant(JSValue(v));
ba379fdc
A
963 } else
964 index = result.first->second;
9dae56ea 965
ba379fdc 966 return &m_constantPoolRegisters[index];
9dae56ea
A
967}
968
969unsigned BytecodeGenerator::addRegExp(RegExp* r)
970{
971 return m_codeBlock->addRegExp(r);
972}
973
974RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
975{
976 emitOpcode(op_mov);
977 instructions().append(dst->index());
978 instructions().append(src->index());
979 return dst;
980}
981
982RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src)
983{
984 emitOpcode(opcodeID);
985 instructions().append(dst->index());
986 instructions().append(src->index());
987 return dst;
988}
989
990RegisterID* BytecodeGenerator::emitPreInc(RegisterID* srcDst)
991{
992 emitOpcode(op_pre_inc);
993 instructions().append(srcDst->index());
994 return srcDst;
995}
996
997RegisterID* BytecodeGenerator::emitPreDec(RegisterID* srcDst)
998{
999 emitOpcode(op_pre_dec);
1000 instructions().append(srcDst->index());
1001 return srcDst;
1002}
1003
1004RegisterID* BytecodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
1005{
1006 emitOpcode(op_post_inc);
1007 instructions().append(dst->index());
1008 instructions().append(srcDst->index());
1009 return dst;
1010}
1011
1012RegisterID* BytecodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
1013{
1014 emitOpcode(op_post_dec);
1015 instructions().append(dst->index());
1016 instructions().append(srcDst->index());
1017 return dst;
1018}
1019
1020RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
1021{
1022 emitOpcode(opcodeID);
1023 instructions().append(dst->index());
1024 instructions().append(src1->index());
1025 instructions().append(src2->index());
1026
1027 if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
ba379fdc 1028 opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
9dae56ea 1029 instructions().append(types.toInt());
9dae56ea
A
1030
1031 return dst;
1032}
1033
1034RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2)
1035{
1036 if (m_lastOpcodeID == op_typeof) {
1037 int dstIndex;
1038 int srcIndex;
1039
1040 retrieveLastUnaryOp(dstIndex, srcIndex);
1041
1042 if (src1->index() == dstIndex
1043 && src1->isTemporary()
1044 && m_codeBlock->isConstantRegisterIndex(src2->index())
14957cd0
A
1045 && m_codeBlock->constantRegister(src2->index()).get().isString()) {
1046 const UString& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
9dae56ea
A
1047 if (value == "undefined") {
1048 rewindUnaryOp();
1049 emitOpcode(op_is_undefined);
1050 instructions().append(dst->index());
1051 instructions().append(srcIndex);
1052 return dst;
1053 }
1054 if (value == "boolean") {
1055 rewindUnaryOp();
1056 emitOpcode(op_is_boolean);
1057 instructions().append(dst->index());
1058 instructions().append(srcIndex);
1059 return dst;
1060 }
1061 if (value == "number") {
1062 rewindUnaryOp();
1063 emitOpcode(op_is_number);
1064 instructions().append(dst->index());
1065 instructions().append(srcIndex);
1066 return dst;
1067 }
1068 if (value == "string") {
1069 rewindUnaryOp();
1070 emitOpcode(op_is_string);
1071 instructions().append(dst->index());
1072 instructions().append(srcIndex);
1073 return dst;
1074 }
1075 if (value == "object") {
1076 rewindUnaryOp();
1077 emitOpcode(op_is_object);
1078 instructions().append(dst->index());
1079 instructions().append(srcIndex);
1080 return dst;
1081 }
1082 if (value == "function") {
1083 rewindUnaryOp();
1084 emitOpcode(op_is_function);
1085 instructions().append(dst->index());
1086 instructions().append(srcIndex);
1087 return dst;
1088 }
1089 }
1090 }
1091
1092 emitOpcode(opcodeID);
1093 instructions().append(dst->index());
1094 instructions().append(src1->index());
1095 instructions().append(src2->index());
1096 return dst;
1097}
1098
1099RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
1100{
1101 return emitLoad(dst, jsBoolean(b));
1102}
1103
1104RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
1105{
14957cd0
A
1106 // FIXME: Our hash tables won't hold infinity, so we make a new JSValue each time.
1107 // Later we can do the extra work to handle that like the other cases. They also don't
1108 // work correctly with NaN as a key.
1109 if (isnan(number) || number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
1110 return emitLoad(dst, jsNumber(number));
ba379fdc 1111 JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second;
9dae56ea 1112 if (!valueInMap)
14957cd0 1113 valueInMap = jsNumber(number);
9dae56ea
A
1114 return emitLoad(dst, valueInMap);
1115}
1116
1117RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
1118{
14957cd0 1119 JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second;
9dae56ea
A
1120 if (!stringInMap)
1121 stringInMap = jsOwnedString(globalData(), identifier.ustring());
ba379fdc 1122 return emitLoad(dst, JSValue(stringInMap));
9dae56ea
A
1123}
1124
ba379fdc 1125RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
9dae56ea 1126{
ba379fdc 1127 RegisterID* constantID = addConstantValue(v);
9dae56ea
A
1128 if (dst)
1129 return emitMove(dst, constantID);
1130 return constantID;
1131}
1132
4e4e5a6f 1133bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, bool& requiresDynamicChecks, JSObject*& globalObject)
9dae56ea
A
1134{
1135 // Cases where we cannot statically optimize the lookup.
1136 if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
1137 stackDepth = 0;
1138 index = missingSymbolMarker();
1139
1140 if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
1141 ScopeChainIterator iter = m_scopeChain->begin();
14957cd0 1142 globalObject = iter->get();
9dae56ea
A
1143 ASSERT((++iter) == m_scopeChain->end());
1144 }
1145 return false;
1146 }
1147
1148 size_t depth = 0;
4e4e5a6f 1149 requiresDynamicChecks = false;
9dae56ea
A
1150 ScopeChainIterator iter = m_scopeChain->begin();
1151 ScopeChainIterator end = m_scopeChain->end();
1152 for (; iter != end; ++iter, ++depth) {
14957cd0 1153 JSObject* currentScope = iter->get();
9dae56ea
A
1154 if (!currentScope->isVariableObject())
1155 break;
1156 JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
14957cd0 1157 SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
9dae56ea
A
1158
1159 // Found the property
1160 if (!entry.isNull()) {
1161 if (entry.isReadOnly() && forWriting) {
1162 stackDepth = 0;
1163 index = missingSymbolMarker();
1164 if (++iter == end)
1165 globalObject = currentVariableObject;
1166 return false;
1167 }
14957cd0 1168 stackDepth = depth + m_codeBlock->needsFullScopeChain();
9dae56ea
A
1169 index = entry.getIndex();
1170 if (++iter == end)
1171 globalObject = currentVariableObject;
1172 return true;
1173 }
4e4e5a6f
A
1174 bool scopeRequiresDynamicChecks = false;
1175 if (currentVariableObject->isDynamicScope(scopeRequiresDynamicChecks))
9dae56ea 1176 break;
4e4e5a6f 1177 requiresDynamicChecks |= scopeRequiresDynamicChecks;
9dae56ea 1178 }
9dae56ea 1179 // Can't locate the property but we're able to avoid a few lookups.
14957cd0 1180 stackDepth = depth + m_codeBlock->needsFullScopeChain();
9dae56ea 1181 index = missingSymbolMarker();
14957cd0 1182 JSObject* scope = iter->get();
9dae56ea
A
1183 if (++iter == end)
1184 globalObject = scope;
1185 return true;
1186}
1187
14957cd0
A
1188void BytecodeGenerator::emitCheckHasInstance(RegisterID* base)
1189{
1190 emitOpcode(op_check_has_instance);
1191 instructions().append(base->index());
1192}
1193
9dae56ea
A
1194RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
1195{
1196 emitOpcode(op_instanceof);
1197 instructions().append(dst->index());
1198 instructions().append(value->index());
1199 instructions().append(base->index());
1200 instructions().append(basePrototype->index());
1201 return dst;
1202}
1203
14957cd0
A
1204static const unsigned maxGlobalResolves = 128;
1205
1206bool BytecodeGenerator::shouldAvoidResolveGlobal()
1207{
1208 return m_codeBlock->globalResolveInfoCount() > maxGlobalResolves && !m_labelScopes.size();
1209}
1210
9dae56ea
A
1211RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
1212{
1213 size_t depth = 0;
1214 int index = 0;
1215 JSObject* globalObject = 0;
4e4e5a6f
A
1216 bool requiresDynamicChecks = false;
1217 if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) && !globalObject) {
9dae56ea
A
1218 // We can't optimise at all :-(
1219 emitOpcode(op_resolve);
1220 instructions().append(dst->index());
1221 instructions().append(addConstant(property));
1222 return dst;
1223 }
14957cd0
A
1224 if (shouldAvoidResolveGlobal()) {
1225 globalObject = 0;
1226 requiresDynamicChecks = true;
1227 }
1228
9dae56ea
A
1229 if (globalObject) {
1230 bool forceGlobalResolve = false;
9dae56ea 1231
4e4e5a6f 1232 if (index != missingSymbolMarker() && !forceGlobalResolve && !requiresDynamicChecks) {
9dae56ea
A
1233 // Directly index the property lookup across multiple scopes.
1234 return emitGetScopedVar(dst, depth, index, globalObject);
1235 }
1236
1237#if ENABLE(JIT)
1238 m_codeBlock->addGlobalResolveInfo(instructions().size());
14957cd0
A
1239#endif
1240#if ENABLE(INTERPRETER)
9dae56ea
A
1241 m_codeBlock->addGlobalResolveInstruction(instructions().size());
1242#endif
4e4e5a6f 1243 emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
9dae56ea 1244 instructions().append(dst->index());
9dae56ea
A
1245 instructions().append(addConstant(property));
1246 instructions().append(0);
1247 instructions().append(0);
4e4e5a6f
A
1248 if (requiresDynamicChecks)
1249 instructions().append(depth);
1250 return dst;
1251 }
1252
1253 if (requiresDynamicChecks) {
1254 // If we get here we have eval nested inside a |with| just give up
1255 emitOpcode(op_resolve);
1256 instructions().append(dst->index());
1257 instructions().append(addConstant(property));
9dae56ea
A
1258 return dst;
1259 }
1260
1261 if (index != missingSymbolMarker()) {
1262 // Directly index the property lookup across multiple scopes.
1263 return emitGetScopedVar(dst, depth, index, globalObject);
1264 }
1265
1266 // In this case we are at least able to drop a few scope chains from the
1267 // lookup chain, although we still need to hash from then on.
1268 emitOpcode(op_resolve_skip);
1269 instructions().append(dst->index());
1270 instructions().append(addConstant(property));
1271 instructions().append(depth);
1272 return dst;
1273}
1274
ba379fdc 1275RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
9dae56ea
A
1276{
1277 if (globalObject) {
1278 emitOpcode(op_get_global_var);
1279 instructions().append(dst->index());
9dae56ea
A
1280 instructions().append(index);
1281 return dst;
1282 }
1283
1284 emitOpcode(op_get_scoped_var);
1285 instructions().append(dst->index());
1286 instructions().append(index);
1287 instructions().append(depth);
1288 return dst;
1289}
1290
ba379fdc 1291RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue globalObject)
9dae56ea
A
1292{
1293 if (globalObject) {
1294 emitOpcode(op_put_global_var);
9dae56ea
A
1295 instructions().append(index);
1296 instructions().append(value->index());
1297 return value;
1298 }
1299 emitOpcode(op_put_scoped_var);
1300 instructions().append(index);
1301 instructions().append(depth);
1302 instructions().append(value->index());
1303 return value;
1304}
1305
1306RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
1307{
ba379fdc
A
1308 size_t depth = 0;
1309 int index = 0;
1310 JSObject* globalObject = 0;
4e4e5a6f
A
1311 bool requiresDynamicChecks = false;
1312 findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
1313 if (!globalObject || requiresDynamicChecks) {
ba379fdc
A
1314 // We can't optimise at all :-(
1315 emitOpcode(op_resolve_base);
1316 instructions().append(dst->index());
1317 instructions().append(addConstant(property));
14957cd0 1318 instructions().append(false);
ba379fdc
A
1319 return dst;
1320 }
1321
1322 // Global object is the base
1323 return emitLoad(dst, JSValue(globalObject));
9dae56ea
A
1324}
1325
14957cd0
A
1326RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Identifier& property)
1327{
1328 if (!m_codeBlock->isStrictMode())
1329 return emitResolveBase(dst, property);
1330 size_t depth = 0;
1331 int index = 0;
1332 JSObject* globalObject = 0;
1333 bool requiresDynamicChecks = false;
1334 findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
1335 if (!globalObject || requiresDynamicChecks) {
1336 // We can't optimise at all :-(
1337 emitOpcode(op_resolve_base);
1338 instructions().append(dst->index());
1339 instructions().append(addConstant(property));
1340 instructions().append(true);
1341 return dst;
1342 }
1343
1344 // Global object is the base
1345 RefPtr<RegisterID> result = emitLoad(dst, JSValue(globalObject));
1346 emitOpcode(op_ensure_property_exists);
1347 instructions().append(dst->index());
1348 instructions().append(addConstant(property));
1349 return result.get();
1350}
1351
9dae56ea
A
1352RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
1353{
ba379fdc
A
1354 size_t depth = 0;
1355 int index = 0;
1356 JSObject* globalObject = 0;
4e4e5a6f
A
1357 bool requiresDynamicChecks = false;
1358 if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
ba379fdc
A
1359 // We can't optimise at all :-(
1360 emitOpcode(op_resolve_with_base);
1361 instructions().append(baseDst->index());
1362 instructions().append(propDst->index());
1363 instructions().append(addConstant(property));
1364 return baseDst;
1365 }
1366
1367 bool forceGlobalResolve = false;
ba379fdc
A
1368
1369 // Global object is the base
1370 emitLoad(baseDst, JSValue(globalObject));
1371
1372 if (index != missingSymbolMarker() && !forceGlobalResolve) {
1373 // Directly index the property lookup across multiple scopes.
1374 emitGetScopedVar(propDst, depth, index, globalObject);
1375 return baseDst;
1376 }
14957cd0
A
1377 if (shouldAvoidResolveGlobal()) {
1378 emitOpcode(op_resolve);
1379 instructions().append(propDst->index());
1380 instructions().append(addConstant(property));
1381 return baseDst;
1382 }
ba379fdc
A
1383#if ENABLE(JIT)
1384 m_codeBlock->addGlobalResolveInfo(instructions().size());
14957cd0
A
1385#endif
1386#if ENABLE(INTERPRETER)
ba379fdc
A
1387 m_codeBlock->addGlobalResolveInstruction(instructions().size());
1388#endif
4e4e5a6f 1389 emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
9dae56ea
A
1390 instructions().append(propDst->index());
1391 instructions().append(addConstant(property));
ba379fdc
A
1392 instructions().append(0);
1393 instructions().append(0);
4e4e5a6f
A
1394 if (requiresDynamicChecks)
1395 instructions().append(depth);
9dae56ea
A
1396 return baseDst;
1397}
1398
ba379fdc 1399void BytecodeGenerator::emitMethodCheck()
9dae56ea 1400{
ba379fdc 1401 emitOpcode(op_method_check);
9dae56ea
A
1402}
1403
1404RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
1405{
1406#if ENABLE(JIT)
f9bf01c6 1407 m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
14957cd0
A
1408#endif
1409
1410#if ENABLE(INTERPRETER)
9dae56ea
A
1411 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1412#endif
1413
1414 emitOpcode(op_get_by_id);
1415 instructions().append(dst->index());
1416 instructions().append(base->index());
1417 instructions().append(addConstant(property));
1418 instructions().append(0);
1419 instructions().append(0);
1420 instructions().append(0);
1421 instructions().append(0);
1422 return dst;
1423}
1424
14957cd0
A
1425RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterID* base)
1426{
1427 emitOpcode(op_get_arguments_length);
1428 instructions().append(dst->index());
1429 ASSERT(base->index() == m_codeBlock->argumentsRegister());
1430 instructions().append(base->index());
1431 instructions().append(addConstant(propertyNames().length));
1432 return dst;
1433}
1434
9dae56ea
A
1435RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1436{
1437#if ENABLE(JIT)
f9bf01c6 1438 m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
14957cd0
A
1439#endif
1440#if ENABLE(INTERPRETER)
9dae56ea
A
1441 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1442#endif
1443
1444 emitOpcode(op_put_by_id);
1445 instructions().append(base->index());
1446 instructions().append(addConstant(property));
1447 instructions().append(value->index());
1448 instructions().append(0);
1449 instructions().append(0);
1450 instructions().append(0);
1451 instructions().append(0);
4e4e5a6f
A
1452 instructions().append(0);
1453 return value;
1454}
1455
1456RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1457{
1458#if ENABLE(JIT)
1459 m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
14957cd0
A
1460#endif
1461#if ENABLE(INTERPRETER)
4e4e5a6f
A
1462 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1463#endif
1464
1465 emitOpcode(op_put_by_id);
1466 instructions().append(base->index());
1467 instructions().append(addConstant(property));
1468 instructions().append(value->index());
1469 instructions().append(0);
1470 instructions().append(0);
1471 instructions().append(0);
1472 instructions().append(0);
1473 instructions().append(property != m_globalData->propertyNames->underscoreProto);
9dae56ea
A
1474 return value;
1475}
1476
1477RegisterID* BytecodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
1478{
1479 emitOpcode(op_put_getter);
1480 instructions().append(base->index());
1481 instructions().append(addConstant(property));
1482 instructions().append(value->index());
1483 return value;
1484}
1485
1486RegisterID* BytecodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
1487{
1488 emitOpcode(op_put_setter);
1489 instructions().append(base->index());
1490 instructions().append(addConstant(property));
1491 instructions().append(value->index());
1492 return value;
1493}
1494
1495RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
1496{
1497 emitOpcode(op_del_by_id);
1498 instructions().append(dst->index());
1499 instructions().append(base->index());
1500 instructions().append(addConstant(property));
1501 return dst;
1502}
1503
14957cd0
A
1504RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1505{
1506 emitOpcode(op_get_argument_by_val);
1507 instructions().append(dst->index());
1508 ASSERT(base->index() == m_codeBlock->argumentsRegister());
1509 instructions().append(base->index());
1510 instructions().append(property->index());
1511 return dst;
1512}
1513
9dae56ea
A
1514RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1515{
f9bf01c6
A
1516 for (size_t i = m_forInContextStack.size(); i > 0; i--) {
1517 ForInContext& context = m_forInContextStack[i - 1];
1518 if (context.propertyRegister == property) {
1519 emitOpcode(op_get_by_pname);
1520 instructions().append(dst->index());
1521 instructions().append(base->index());
1522 instructions().append(property->index());
1523 instructions().append(context.expectedSubscriptRegister->index());
1524 instructions().append(context.iterRegister->index());
1525 instructions().append(context.indexRegister->index());
1526 return dst;
1527 }
1528 }
9dae56ea
A
1529 emitOpcode(op_get_by_val);
1530 instructions().append(dst->index());
1531 instructions().append(base->index());
1532 instructions().append(property->index());
1533 return dst;
1534}
1535
1536RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1537{
1538 emitOpcode(op_put_by_val);
1539 instructions().append(base->index());
1540 instructions().append(property->index());
1541 instructions().append(value->index());
1542 return value;
1543}
1544
1545RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1546{
1547 emitOpcode(op_del_by_val);
1548 instructions().append(dst->index());
1549 instructions().append(base->index());
1550 instructions().append(property->index());
1551 return dst;
1552}
1553
1554RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1555{
1556 emitOpcode(op_put_by_index);
1557 instructions().append(base->index());
1558 instructions().append(index);
1559 instructions().append(value->index());
1560 return value;
1561}
1562
1563RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
1564{
1565 emitOpcode(op_new_object);
1566 instructions().append(dst->index());
1567 return dst;
1568}
1569
14957cd0
A
1570unsigned BytecodeGenerator::addConstantBuffer(unsigned length)
1571{
1572 return m_codeBlock->addConstantBuffer(length);
1573}
1574
1575JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
1576{
1577 JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second;
1578 if (!stringInMap) {
1579 stringInMap = jsString(globalData(), identifier.ustring());
1580 addConstantValue(stringInMap);
1581 }
1582 return stringInMap;
1583}
1584
1585RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length)
9dae56ea 1586{
14957cd0
A
1587#if !ASSERT_DISABLED
1588 unsigned checkLength = 0;
1589#endif
1590 bool hadVariableExpression = false;
1591 if (length) {
1592 for (ElementNode* n = elements; n; n = n->next()) {
1593 if (!n->value()->isNumber() && !n->value()->isString()) {
1594 hadVariableExpression = true;
1595 break;
1596 }
1597 if (n->elision())
1598 break;
1599#if !ASSERT_DISABLED
1600 checkLength++;
1601#endif
1602 }
1603 if (!hadVariableExpression) {
1604 ASSERT(length == checkLength);
1605 unsigned constantBufferIndex = addConstantBuffer(length);
1606 JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex);
1607 unsigned index = 0;
1608 for (ElementNode* n = elements; index < length; n = n->next()) {
1609 if (n->value()->isNumber())
1610 constantBuffer[index++] = jsNumber(static_cast<NumberNode*>(n->value())->value());
1611 else {
1612 ASSERT(n->value()->isString());
1613 constantBuffer[index++] = addStringConstant(static_cast<StringNode*>(n->value())->value());
1614 }
1615 }
1616 emitOpcode(op_new_array_buffer);
1617 instructions().append(dst->index());
1618 instructions().append(constantBufferIndex);
1619 instructions().append(length);
1620 return dst;
1621 }
1622 }
1623
9dae56ea
A
1624 Vector<RefPtr<RegisterID>, 16> argv;
1625 for (ElementNode* n = elements; n; n = n->next()) {
1626 if (n->elision())
1627 break;
1628 argv.append(newTemporary());
1629 // op_new_array requires the initial values to be a sequential range of registers
1630 ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
1631 emitNode(argv.last().get(), n->value());
1632 }
1633 emitOpcode(op_new_array);
1634 instructions().append(dst->index());
1635 instructions().append(argv.size() ? argv[0]->index() : 0); // argv
1636 instructions().append(argv.size()); // argc
1637 return dst;
1638}
1639
f9bf01c6 1640RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
9dae56ea 1641{
14957cd0
A
1642 return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)), false);
1643}
1644
1645RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function)
1646{
1647 std::pair<FunctionOffsetMap::iterator, bool> ptr = m_functionOffsets.add(function, 0);
1648 if (ptr.second)
1649 ptr.first->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
1650 return emitNewFunctionInternal(dst, ptr.first->second, true);
1651}
f9bf01c6 1652
14957cd0
A
1653RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck)
1654{
1655 createActivationIfNecessary();
9dae56ea
A
1656 emitOpcode(op_new_func);
1657 instructions().append(dst->index());
f9bf01c6 1658 instructions().append(index);
14957cd0 1659 instructions().append(doNullCheck);
9dae56ea
A
1660 return dst;
1661}
1662
1663RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
1664{
1665 emitOpcode(op_new_regexp);
1666 instructions().append(dst->index());
1667 instructions().append(addRegExp(regExp));
1668 return dst;
1669}
1670
9dae56ea
A
1671RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
1672{
f9bf01c6
A
1673 FunctionBodyNode* function = n->body();
1674 unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
14957cd0
A
1675
1676 createActivationIfNecessary();
9dae56ea
A
1677 emitOpcode(op_new_func_exp);
1678 instructions().append(r0->index());
f9bf01c6 1679 instructions().append(index);
9dae56ea
A
1680 return r0;
1681}
1682
14957cd0 1683RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
9dae56ea 1684{
14957cd0 1685 return emitCall(op_call, dst, func, callArguments, divot, startOffset, endOffset);
9dae56ea
A
1686}
1687
ba379fdc
A
1688void BytecodeGenerator::createArgumentsIfNecessary()
1689{
14957cd0
A
1690 if (m_codeType != FunctionCode)
1691 return;
1692
1693 if (!m_codeBlock->usesArguments())
1694 return;
1695
1696 // If we're in strict mode we tear off the arguments on function
1697 // entry, so there's no need to check if we need to create them
1698 // now
1699 if (m_codeBlock->isStrictMode())
1700 return;
1701
1702 emitOpcode(op_create_arguments);
1703 instructions().append(m_codeBlock->argumentsRegister());
ba379fdc
A
1704}
1705
14957cd0 1706void BytecodeGenerator::createActivationIfNecessary()
9dae56ea 1707{
14957cd0
A
1708 if (m_hasCreatedActivation)
1709 return;
1710 if (!m_codeBlock->needsFullScopeChain())
1711 return;
1712 emitOpcode(op_create_activation);
1713 instructions().append(m_activationRegister->index());
9dae56ea
A
1714}
1715
14957cd0
A
1716RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
1717{
1718 return emitCall(op_call_eval, dst, func, callArguments, divot, startOffset, endOffset);
1719}
1720
1721RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
9dae56ea
A
1722{
1723 ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
1724 ASSERT(func->refCount());
9dae56ea 1725
14957cd0
A
1726 if (m_shouldEmitProfileHooks)
1727 emitMove(callArguments.profileHookRegister(), func);
9dae56ea
A
1728
1729 // Generate code for arguments.
14957cd0
A
1730 unsigned argumentIndex = 0;
1731 for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
1732 emitNode(callArguments.argumentRegister(argumentIndex++), n);
9dae56ea
A
1733
1734 // Reserve space for call frame.
1735 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1736 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1737 callFrame.append(newTemporary());
1738
1739 if (m_shouldEmitProfileHooks) {
1740 emitOpcode(op_profile_will_call);
14957cd0 1741 instructions().append(callArguments.profileHookRegister()->index());
9dae56ea
A
1742 }
1743
1744 emitExpressionInfo(divot, startOffset, endOffset);
1745
1746#if ENABLE(JIT)
1747 m_codeBlock->addCallLinkInfo();
1748#endif
1749
1750 // Emit call.
1751 emitOpcode(opcodeID);
9dae56ea 1752 instructions().append(func->index()); // func
14957cd0
A
1753 instructions().append(callArguments.count()); // argCount
1754 instructions().append(callArguments.callFrame()); // registerOffset
1755 if (dst != ignoredResult()) {
1756 emitOpcode(op_call_put_result);
1757 instructions().append(dst->index()); // dst
1758 }
9dae56ea
A
1759
1760 if (m_shouldEmitProfileHooks) {
1761 emitOpcode(op_profile_did_call);
14957cd0 1762 instructions().append(callArguments.profileHookRegister()->index());
9dae56ea
A
1763 }
1764
1765 return dst;
1766}
1767
14957cd0 1768RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* arguments)
ba379fdc
A
1769{
1770 ASSERT(argCountDst->index() < arguments->index());
1771 emitOpcode(op_load_varargs);
1772 instructions().append(argCountDst->index());
1773 instructions().append(arguments->index());
14957cd0 1774 instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
ba379fdc
A
1775 return argCountDst;
1776}
1777
1778RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCountRegister, unsigned divot, unsigned startOffset, unsigned endOffset)
1779{
1780 ASSERT(func->refCount());
1781 ASSERT(thisRegister->refCount());
1782 ASSERT(dst != func);
1783 if (m_shouldEmitProfileHooks) {
1784 emitOpcode(op_profile_will_call);
1785 instructions().append(func->index());
ba379fdc
A
1786 }
1787
1788 emitExpressionInfo(divot, startOffset, endOffset);
1789
1790 // Emit call.
1791 emitOpcode(op_call_varargs);
ba379fdc
A
1792 instructions().append(func->index()); // func
1793 instructions().append(argCountRegister->index()); // arg count
1794 instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
14957cd0
A
1795 if (dst != ignoredResult()) {
1796 emitOpcode(op_call_put_result);
1797 instructions().append(dst->index()); // dst
1798 }
ba379fdc
A
1799 if (m_shouldEmitProfileHooks) {
1800 emitOpcode(op_profile_did_call);
1801 instructions().append(func->index());
1802 }
1803 return dst;
1804}
1805
9dae56ea
A
1806RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
1807{
1808 if (m_codeBlock->needsFullScopeChain()) {
1809 emitOpcode(op_tear_off_activation);
14957cd0
A
1810 instructions().append(m_activationRegister->index());
1811 instructions().append(m_codeBlock->argumentsRegister());
1812 } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1
1813 && !m_codeBlock->isStrictMode()) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
9dae56ea 1814 emitOpcode(op_tear_off_arguments);
14957cd0
A
1815 instructions().append(m_codeBlock->argumentsRegister());
1816 }
9dae56ea 1817
14957cd0
A
1818 // Constructors use op_ret_object_or_this to check the result is an
1819 // object, unless we can trivially determine the check is not
1820 // necessary (currently, if the return value is 'this').
1821 if (isConstructor() && (src->index() != m_thisRegister.index())) {
1822 emitOpcode(op_ret_object_or_this);
1823 instructions().append(src->index());
1824 instructions().append(m_thisRegister.index());
1825 return src;
1826 }
9dae56ea
A
1827 return emitUnaryNoDstOp(op_ret, src);
1828}
1829
1830RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src)
1831{
1832 emitOpcode(opcodeID);
1833 instructions().append(src->index());
1834 return src;
1835}
1836
14957cd0 1837RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
9dae56ea
A
1838{
1839 ASSERT(func->refCount());
1840
14957cd0
A
1841 if (m_shouldEmitProfileHooks)
1842 emitMove(callArguments.profileHookRegister(), func);
9dae56ea
A
1843
1844 // Generate code for arguments.
14957cd0
A
1845 unsigned argumentIndex = 0;
1846 if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
1847 for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
1848 emitNode(callArguments.argumentRegister(argumentIndex++), n);
9dae56ea
A
1849 }
1850
1851 if (m_shouldEmitProfileHooks) {
1852 emitOpcode(op_profile_will_call);
14957cd0 1853 instructions().append(callArguments.profileHookRegister()->index());
9dae56ea
A
1854 }
1855
9dae56ea
A
1856 // Reserve space for call frame.
1857 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1858 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1859 callFrame.append(newTemporary());
1860
1861 emitExpressionInfo(divot, startOffset, endOffset);
1862
1863#if ENABLE(JIT)
1864 m_codeBlock->addCallLinkInfo();
1865#endif
1866
1867 emitOpcode(op_construct);
9dae56ea 1868 instructions().append(func->index()); // func
14957cd0
A
1869 instructions().append(callArguments.count()); // argCount
1870 instructions().append(callArguments.callFrame()); // registerOffset
1871 if (dst != ignoredResult()) {
1872 emitOpcode(op_call_put_result);
1873 instructions().append(dst->index()); // dst
1874 }
9dae56ea
A
1875
1876 if (m_shouldEmitProfileHooks) {
1877 emitOpcode(op_profile_did_call);
14957cd0 1878 instructions().append(callArguments.profileHookRegister()->index());
9dae56ea
A
1879 }
1880
1881 return dst;
1882}
1883
ba379fdc
A
1884RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
1885{
1886 emitOpcode(op_strcat);
1887 instructions().append(dst->index());
1888 instructions().append(src->index());
1889 instructions().append(count);
1890
1891 return dst;
1892}
1893
1894void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
1895{
1896 emitOpcode(op_to_primitive);
1897 instructions().append(dst->index());
1898 instructions().append(src->index());
1899}
1900
9dae56ea
A
1901RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
1902{
1903 ASSERT(scope->isTemporary());
1904 ControlFlowContext context;
1905 context.isFinallyBlock = false;
1906 m_scopeContextStack.append(context);
1907 m_dynamicScopeDepth++;
1908
1909 return emitUnaryNoDstOp(op_push_scope, scope);
1910}
1911
1912void BytecodeGenerator::emitPopScope()
1913{
1914 ASSERT(m_scopeContextStack.size());
1915 ASSERT(!m_scopeContextStack.last().isFinallyBlock);
1916
1917 emitOpcode(op_pop_scope);
1918
1919 m_scopeContextStack.removeLast();
1920 m_dynamicScopeDepth--;
1921}
1922
1923void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine)
1924{
4e4e5a6f
A
1925#if ENABLE(DEBUG_WITH_BREAKPOINT)
1926 if (debugHookID != DidReachBreakpoint)
1927 return;
1928#else
9dae56ea
A
1929 if (!m_shouldEmitDebugHooks)
1930 return;
4e4e5a6f 1931#endif
9dae56ea
A
1932 emitOpcode(op_debug);
1933 instructions().append(debugHookID);
1934 instructions().append(firstLine);
1935 instructions().append(lastLine);
1936}
1937
1938void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst)
1939{
1940 ControlFlowContext scope;
1941 scope.isFinallyBlock = true;
1942 FinallyContext context = { target, retAddrDst };
1943 scope.finallyContext = context;
1944 m_scopeContextStack.append(scope);
1945 m_finallyDepth++;
1946}
1947
1948void BytecodeGenerator::popFinallyContext()
1949{
1950 ASSERT(m_scopeContextStack.size());
1951 ASSERT(m_scopeContextStack.last().isFinallyBlock);
1952 ASSERT(m_finallyDepth > 0);
1953 m_scopeContextStack.removeLast();
1954 m_finallyDepth--;
1955}
1956
1957LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
1958{
1959 // Reclaim free label scopes.
ba379fdc
A
1960 //
1961 // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
1962 // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
1963 // size 0, leading to segfaulty badness. We are yet to identify a valid cause within our code to
1964 // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
1965 // loop condition is a workaround.
1966 while (m_labelScopes.size()) {
1967 if (m_labelScopes.last().refCount())
1968 break;
9dae56ea 1969 m_labelScopes.removeLast();
ba379fdc 1970 }
9dae56ea
A
1971
1972 if (!m_labelScopes.size())
1973 return 0;
1974
1975 // We special-case the following, which is a syntax error in Firefox:
1976 // label:
1977 // break;
1978 if (name.isEmpty()) {
1979 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1980 LabelScope* scope = &m_labelScopes[i];
1981 if (scope->type() != LabelScope::NamedLabel) {
1982 ASSERT(scope->breakTarget());
1983 return scope;
1984 }
1985 }
1986 return 0;
1987 }
1988
1989 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1990 LabelScope* scope = &m_labelScopes[i];
1991 if (scope->name() && *scope->name() == name) {
1992 ASSERT(scope->breakTarget());
1993 return scope;
1994 }
1995 }
1996 return 0;
1997}
1998
1999LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
2000{
2001 // Reclaim free label scopes.
2002 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2003 m_labelScopes.removeLast();
2004
2005 if (!m_labelScopes.size())
2006 return 0;
2007
2008 if (name.isEmpty()) {
2009 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2010 LabelScope* scope = &m_labelScopes[i];
2011 if (scope->type() == LabelScope::Loop) {
2012 ASSERT(scope->continueTarget());
2013 return scope;
2014 }
2015 }
2016 return 0;
2017 }
2018
2019 // Continue to the loop nested nearest to the label scope that matches
2020 // 'name'.
2021 LabelScope* result = 0;
2022 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2023 LabelScope* scope = &m_labelScopes[i];
2024 if (scope->type() == LabelScope::Loop) {
2025 ASSERT(scope->continueTarget());
2026 result = scope;
2027 }
2028 if (scope->name() && *scope->name() == name)
2029 return result; // may be 0
2030 }
2031 return 0;
2032}
2033
2034PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
2035{
2036 while (topScope > bottomScope) {
2037 // First we count the number of dynamic scopes we need to remove to get
2038 // to a finally block.
2039 int nNormalScopes = 0;
2040 while (topScope > bottomScope) {
2041 if (topScope->isFinallyBlock)
2042 break;
2043 ++nNormalScopes;
2044 --topScope;
2045 }
2046
2047 if (nNormalScopes) {
f9bf01c6
A
2048 size_t begin = instructions().size();
2049
9dae56ea
A
2050 // We need to remove a number of dynamic scopes to get to the next
2051 // finally block
2052 emitOpcode(op_jmp_scopes);
2053 instructions().append(nNormalScopes);
2054
2055 // If topScope == bottomScope then there isn't actually a finally block
2056 // left to emit, so make the jmp_scopes jump directly to the target label
2057 if (topScope == bottomScope) {
f9bf01c6 2058 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
2059 return target;
2060 }
2061
2062 // Otherwise we just use jmp_scopes to pop a group of scopes and go
2063 // to the next instruction
2064 RefPtr<Label> nextInsn = newLabel();
f9bf01c6 2065 instructions().append(nextInsn->bind(begin, instructions().size()));
9dae56ea
A
2066 emitLabel(nextInsn.get());
2067 }
2068
ba379fdc 2069 while (topScope > bottomScope && topScope->isFinallyBlock) {
9dae56ea
A
2070 emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
2071 --topScope;
ba379fdc 2072 }
9dae56ea
A
2073 }
2074 return emitJump(target);
2075}
2076
2077PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetScopeDepth)
2078{
2079 ASSERT(scopeDepth() - targetScopeDepth >= 0);
2080 ASSERT(target->isForward());
2081
2082 size_t scopeDelta = scopeDepth() - targetScopeDepth;
2083 ASSERT(scopeDelta <= m_scopeContextStack.size());
2084 if (!scopeDelta)
2085 return emitJump(target);
2086
2087 if (m_finallyDepth)
2088 return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
2089
f9bf01c6
A
2090 size_t begin = instructions().size();
2091
9dae56ea
A
2092 emitOpcode(op_jmp_scopes);
2093 instructions().append(scopeDelta);
f9bf01c6 2094 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
2095 return target;
2096}
2097
f9bf01c6 2098RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget)
9dae56ea 2099{
f9bf01c6
A
2100 size_t begin = instructions().size();
2101
2102 emitOpcode(op_get_pnames);
2103 instructions().append(dst->index());
2104 instructions().append(base->index());
2105 instructions().append(i->index());
2106 instructions().append(size->index());
2107 instructions().append(breakTarget->bind(begin, instructions().size()));
2108 return dst;
2109}
2110
2111RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target)
2112{
2113 size_t begin = instructions().size();
2114
9dae56ea
A
2115 emitOpcode(op_next_pname);
2116 instructions().append(dst->index());
f9bf01c6
A
2117 instructions().append(base->index());
2118 instructions().append(i->index());
2119 instructions().append(size->index());
9dae56ea 2120 instructions().append(iter->index());
f9bf01c6 2121 instructions().append(target->bind(begin, instructions().size()));
9dae56ea
A
2122 return dst;
2123}
2124
2125RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
2126{
14957cd0 2127 m_usesExceptions = true;
9dae56ea 2128#if ENABLE(JIT)
f9bf01c6 2129 HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
9dae56ea 2130#else
f9bf01c6 2131 HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
9dae56ea
A
2132#endif
2133
2134 m_codeBlock->addExceptionHandler(info);
2135 emitOpcode(op_catch);
2136 instructions().append(targetRegister->index());
2137 return targetRegister;
2138}
2139
14957cd0 2140void BytecodeGenerator::emitThrowReferenceError(const UString& message)
9dae56ea 2141{
14957cd0
A
2142 emitOpcode(op_throw_reference_error);
2143 instructions().append(addConstantValue(jsString(globalData(), message))->index());
9dae56ea
A
2144}
2145
2146PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
2147{
f9bf01c6
A
2148 size_t begin = instructions().size();
2149
9dae56ea
A
2150 emitOpcode(op_jsr);
2151 instructions().append(retAddrDst->index());
f9bf01c6 2152 instructions().append(finally->bind(begin, instructions().size()));
ba379fdc 2153 emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
9dae56ea
A
2154 return finally;
2155}
2156
2157void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
2158{
2159 emitOpcode(op_sret);
2160 instructions().append(retAddrSrc->index());
2161}
2162
f9bf01c6 2163void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
9dae56ea
A
2164{
2165 ControlFlowContext context;
2166 context.isFinallyBlock = false;
2167 m_scopeContextStack.append(context);
2168 m_dynamicScopeDepth++;
ba379fdc 2169
9dae56ea
A
2170 emitOpcode(op_push_new_scope);
2171 instructions().append(dst->index());
2172 instructions().append(addConstant(property));
2173 instructions().append(value->index());
2174}
2175
2176void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
2177{
2178 SwitchInfo info = { instructions().size(), type };
2179 switch (type) {
2180 case SwitchInfo::SwitchImmediate:
2181 emitOpcode(op_switch_imm);
2182 break;
2183 case SwitchInfo::SwitchCharacter:
2184 emitOpcode(op_switch_char);
2185 break;
2186 case SwitchInfo::SwitchString:
2187 emitOpcode(op_switch_string);
2188 break;
2189 default:
2190 ASSERT_NOT_REACHED();
2191 }
2192
2193 instructions().append(0); // place holder for table index
2194 instructions().append(0); // place holder for default target
2195 instructions().append(scrutineeRegister->index());
2196 m_switchContextStack.append(info);
2197}
2198
2199static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
2200{
2201 UNUSED_PARAM(max);
2202 ASSERT(node->isNumber());
2203 double value = static_cast<NumberNode*>(node)->value();
2204 int32_t key = static_cast<int32_t>(value);
9dae56ea
A
2205 ASSERT(key == value);
2206 ASSERT(key >= min);
2207 ASSERT(key <= max);
2208 return key - min;
2209}
2210
2211static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
2212{
2213 jumpTable.min = min;
2214 jumpTable.branchOffsets.resize(max - min + 1);
2215 jumpTable.branchOffsets.fill(0);
2216 for (uint32_t i = 0; i < clauseCount; ++i) {
2217 // We're emitting this after the clause labels should have been fixed, so
2218 // the labels should not be "forward" references
2219 ASSERT(!labels[i]->isForward());
f9bf01c6 2220 jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3));
9dae56ea
A
2221 }
2222}
2223
2224static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
2225{
2226 UNUSED_PARAM(max);
2227 ASSERT(node->isString());
14957cd0 2228 StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
4e4e5a6f 2229 ASSERT(clause->length() == 1);
9dae56ea 2230
4e4e5a6f 2231 int32_t key = clause->characters()[0];
9dae56ea
A
2232 ASSERT(key >= min);
2233 ASSERT(key <= max);
2234 return key - min;
2235}
2236
2237static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
2238{
2239 jumpTable.min = min;
2240 jumpTable.branchOffsets.resize(max - min + 1);
2241 jumpTable.branchOffsets.fill(0);
2242 for (uint32_t i = 0; i < clauseCount; ++i) {
2243 // We're emitting this after the clause labels should have been fixed, so
2244 // the labels should not be "forward" references
2245 ASSERT(!labels[i]->isForward());
f9bf01c6 2246 jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3));
9dae56ea
A
2247 }
2248}
2249
2250static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
2251{
2252 for (uint32_t i = 0; i < clauseCount; ++i) {
2253 // We're emitting this after the clause labels should have been fixed, so
2254 // the labels should not be "forward" references
2255 ASSERT(!labels[i]->isForward());
2256
2257 ASSERT(nodes[i]->isString());
14957cd0 2258 StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
9dae56ea 2259 OffsetLocation location;
f9bf01c6 2260 location.branchOffset = labels[i]->bind(switchAddress, switchAddress + 3);
9dae56ea
A
2261 jumpTable.offsetTable.add(clause, location);
2262 }
2263}
2264
2265void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max)
2266{
2267 SwitchInfo switchInfo = m_switchContextStack.last();
2268 m_switchContextStack.removeLast();
2269 if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
2270 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
f9bf01c6 2271 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
9dae56ea
A
2272
2273 SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
f9bf01c6 2274 prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
9dae56ea
A
2275 } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
2276 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
f9bf01c6 2277 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
9dae56ea
A
2278
2279 SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
f9bf01c6 2280 prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
9dae56ea
A
2281 } else {
2282 ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
2283 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
f9bf01c6 2284 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
9dae56ea
A
2285
2286 StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
f9bf01c6 2287 prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
9dae56ea
A
2288 }
2289}
2290
2291RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
2292{
2293 // It would be nice to do an even better job of identifying exactly where the expression is.
2294 // And we could make the caller pass the node pointer in, if there was some way of getting
2295 // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
2296 // is still good enough to get us an accurate line number.
14957cd0
A
2297 m_expressionTooDeep = true;
2298 return newTemporary();
2299}
2300
2301void BytecodeGenerator::setIsNumericCompareFunction(bool isNumericCompareFunction)
2302{
2303 m_codeBlock->setIsNumericCompareFunction(isNumericCompareFunction);
2304}
2305
2306int BytecodeGenerator::argumentNumberFor(const Identifier& ident)
2307{
2308 int parameterCount = m_parameters.size(); // includes 'this'
2309 RegisterID* registerID = registerFor(ident);
2310 if (!registerID)
2311 return 0;
2312 int index = registerID->index() + RegisterFile::CallFrameHeaderSize + parameterCount;
2313 return (index > 0 && index < parameterCount) ? index : 0;
9dae56ea
A
2314}
2315
2316} // namespace JSC