]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecompiler/BytecodeGenerator.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecompiler / BytecodeGenerator.cpp
1 /*
2 * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 * Copyright (C) 2012 Igalia, S.L.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "BytecodeGenerator.h"
33
34 #include "BuiltinExecutables.h"
35 #include "Interpreter.h"
36 #include "JSFunction.h"
37 #include "JSLexicalEnvironment.h"
38 #include "JSNameScope.h"
39 #include "JSTemplateRegistryKey.h"
40 #include "LowLevelInterpreter.h"
41 #include "JSCInlines.h"
42 #include "Options.h"
43 #include "StackAlignment.h"
44 #include "StrongInlines.h"
45 #include "UnlinkedCodeBlock.h"
46 #include "UnlinkedInstructionStream.h"
47 #include <wtf/StdLibExtras.h>
48 #include <wtf/text/WTFString.h>
49
50 using namespace std;
51
52 namespace JSC {
53
54 void Label::setLocation(unsigned location)
55 {
56 m_location = location;
57
58 unsigned size = m_unresolvedJumps.size();
59 for (unsigned i = 0; i < size; ++i)
60 m_generator.instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first;
61 }
62
63 ParserError BytecodeGenerator::generate()
64 {
65 SamplingRegion samplingRegion("Bytecode Generation");
66
67 m_codeBlock->setThisRegister(m_thisRegister.virtualRegister());
68
69 // If we have declared a variable named "arguments" and we are using arguments then we should
70 // perform that assignment now.
71 if (m_needToInitializeArguments)
72 initializeVariable(variable(propertyNames().arguments), m_argumentsRegister);
73
74 for (size_t i = 0; i < m_destructuringParameters.size(); i++) {
75 auto& entry = m_destructuringParameters[i];
76 entry.second->bindValue(*this, entry.first.get());
77 }
78
79 {
80 RefPtr<RegisterID> temp = newTemporary();
81 RefPtr<RegisterID> globalScope = scopeRegister(); // FIXME: With lexical scoping, this won't always be the global object: https://bugs.webkit.org/show_bug.cgi?id=142944
82 for (auto functionPair : m_functionsToInitialize) {
83 FunctionBodyNode* functionBody = functionPair.first;
84 FunctionVariableType functionType = functionPair.second;
85 emitNewFunction(temp.get(), functionBody);
86 if (functionType == NormalFunctionVariable)
87 initializeVariable(variable(functionBody->ident()) , temp.get());
88 else if (functionType == GlobalFunctionVariable)
89 emitPutToScope(globalScope.get(), Variable(functionBody->ident()), temp.get(), ThrowIfNotFound);
90 else
91 RELEASE_ASSERT_NOT_REACHED();
92 }
93 }
94
95 bool callingClassConstructor = constructorKind() != ConstructorKind::None && !isConstructor();
96 if (!callingClassConstructor)
97 m_scopeNode->emitBytecode(*this);
98
99 m_staticPropertyAnalyzer.kill();
100
101 for (unsigned i = 0; i < m_tryRanges.size(); ++i) {
102 TryRange& range = m_tryRanges[i];
103 int start = range.start->bind();
104 int end = range.end->bind();
105
106 // This will happen for empty try blocks and for some cases of finally blocks:
107 //
108 // try {
109 // try {
110 // } finally {
111 // return 42;
112 // // *HERE*
113 // }
114 // } finally {
115 // print("things");
116 // }
117 //
118 // The return will pop scopes to execute the outer finally block. But this includes
119 // popping the try context for the inner try. The try context is live in the fall-through
120 // part of the finally block not because we will emit a handler that overlaps the finally,
121 // but because we haven't yet had a chance to plant the catch target. Then when we finish
122 // emitting code for the outer finally block, we repush the try contex, this time with a
123 // new start index. But that means that the start index for the try range corresponding
124 // to the inner-finally-following-the-return (marked as "*HERE*" above) will be greater
125 // than the end index of the try block. This is harmless since end < start handlers will
126 // never get matched in our logic, but we do the runtime a favor and choose to not emit
127 // such handlers at all.
128 if (end <= start)
129 continue;
130
131 ASSERT(range.tryData->targetScopeDepth != UINT_MAX);
132 ASSERT(range.tryData->handlerType != HandlerType::Illegal);
133 UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
134 static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->targetScopeDepth,
135 range.tryData->handlerType);
136 m_codeBlock->addExceptionHandler(info);
137 }
138
139 m_codeBlock->setInstructions(std::make_unique<UnlinkedInstructionStream>(m_instructions));
140
141 m_codeBlock->shrinkToFit();
142
143 if (m_codeBlock->symbolTable() && !m_codeBlock->vm()->typeProfiler())
144 m_codeBlock->setSymbolTable(m_codeBlock->symbolTable()->cloneScopePart(*m_codeBlock->vm()));
145
146 if (m_expressionTooDeep)
147 return ParserError(ParserError::OutOfMemory);
148 return ParserError(ParserError::ErrorNone);
149 }
150
151 BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
152 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
153 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
154 , m_scopeNode(programNode)
155 , m_codeBlock(vm, codeBlock)
156 , m_thisRegister(CallFrame::thisArgumentOffset())
157 , m_codeType(GlobalCode)
158 , m_vm(&vm)
159 {
160 for (auto& constantRegister : m_linkTimeConstantRegisters)
161 constantRegister = nullptr;
162
163 m_codeBlock->setNumParameters(1); // Allocate space for "this"
164
165 emitOpcode(op_enter);
166
167 allocateAndEmitScope();
168
169 const VarStack& varStack = programNode->varStack();
170 const FunctionStack& functionStack = programNode->functionStack();
171
172 for (size_t i = 0; i < functionStack.size(); ++i) {
173 FunctionBodyNode* function = functionStack[i];
174 m_functionsToInitialize.append(std::make_pair(function, GlobalFunctionVariable));
175 }
176
177 for (size_t i = 0; i < varStack.size(); ++i)
178 codeBlock->addVariableDeclaration(varStack[i].first, !!(varStack[i].second & DeclarationStacks::IsConstant));
179
180 }
181
182 BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
183 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
184 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
185 , m_symbolTable(codeBlock->symbolTable())
186 , m_scopeNode(functionNode)
187 , m_codeBlock(vm, codeBlock)
188 , m_codeType(FunctionCode)
189 , m_vm(&vm)
190 , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
191 {
192 for (auto& constantRegister : m_linkTimeConstantRegisters)
193 constantRegister = nullptr;
194
195 if (m_isBuiltinFunction)
196 m_shouldEmitDebugHooks = false;
197
198 m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
199 Vector<Identifier> boundParameterProperties;
200 FunctionParameters& parameters = *functionNode->parameters();
201 for (size_t i = 0; i < parameters.size(); i++) {
202 auto pattern = parameters.at(i);
203 if (pattern->isBindingNode())
204 continue;
205 pattern->collectBoundIdentifiers(boundParameterProperties);
206 continue;
207 }
208
209 bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || m_codeBlock->needsFullScopeChain();
210 bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval();
211 bool needsArguments = functionNode->usesArguments() || codeBlock->usesEval();
212
213 auto captures = [&] (UniquedStringImpl* uid) -> bool {
214 if (shouldCaptureAllOfTheThings)
215 return true;
216 if (!shouldCaptureSomeOfTheThings)
217 return false;
218 if (needsArguments && uid == propertyNames().arguments.impl()) {
219 // Actually, we only need to capture the arguments object when we "need full activation"
220 // because of name scopes. But historically we did it this way, so for now we just preserve
221 // the old behavior.
222 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=143072
223 return true;
224 }
225 return functionNode->captures(uid);
226 };
227 auto varKind = [&] (UniquedStringImpl* uid) -> VarKind {
228 return captures(uid) ? VarKind::Scope : VarKind::Stack;
229 };
230
231 emitOpcode(op_enter);
232
233 allocateAndEmitScope();
234
235 m_calleeRegister.setIndex(JSStack::Callee);
236
237 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())
238 && functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode())) {
239 // When we do this, we should make our local scope stack know about the function name symbol
240 // table. Currently this works because bytecode linking creates a phony name scope.
241 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
242 // Also, we could create the scope once per JSFunction instance that needs it. That wouldn't
243 // be any more correct, but it would be more performant.
244 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141887
245 emitPushFunctionNameScope(m_scopeRegister, functionNode->ident(), &m_calleeRegister, ReadOnly | DontDelete);
246 }
247
248 if (shouldCaptureSomeOfTheThings) {
249 m_lexicalEnvironmentRegister = addVar();
250 m_codeBlock->setActivationRegister(m_lexicalEnvironmentRegister->virtualRegister());
251 emitOpcode(op_create_lexical_environment);
252 instructions().append(m_lexicalEnvironmentRegister->index());
253 instructions().append(scopeRegister()->index());
254 emitOpcode(op_mov);
255 instructions().append(scopeRegister()->index());
256 instructions().append(m_lexicalEnvironmentRegister->index());
257 }
258
259 // Make sure the code block knows about all of our parameters, and make sure that parameters
260 // needing destructuring are noted.
261 m_parameters.grow(parameters.size() + 1); // reserve space for "this"
262 m_thisRegister.setIndex(initializeNextParameter()->index()); // this
263 for (unsigned i = 0; i < parameters.size(); ++i) {
264 auto pattern = parameters.at(i);
265 RegisterID* reg = initializeNextParameter();
266 if (!pattern->isBindingNode())
267 m_destructuringParameters.append(std::make_pair(reg, pattern));
268 }
269
270 // Figure out some interesting facts about our arguments.
271 bool capturesAnyArgumentByName = false;
272 if (functionNode->hasCapturedVariables()) {
273 FunctionParameters& parameters = *functionNode->parameters();
274 for (size_t i = 0; i < parameters.size(); ++i) {
275 auto pattern = parameters.at(i);
276 if (!pattern->isBindingNode())
277 continue;
278 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
279 capturesAnyArgumentByName |= captures(ident.impl());
280 }
281 }
282
283 if (capturesAnyArgumentByName)
284 ASSERT(m_lexicalEnvironmentRegister);
285
286 // Need to know what our functions are called. Parameters have some goofy behaviors when it
287 // comes to functions of the same name.
288 for (FunctionBodyNode* function : functionNode->functionStack())
289 m_functions.add(function->ident().impl());
290
291 if (needsArguments) {
292 // Create the arguments object now. We may put the arguments object into the activation if
293 // it is captured. Either way, we create two arguments object variables: one is our
294 // private variable that is immutable, and another that is the user-visible variable. The
295 // immutable one is only used here, or during formal parameter resolutions if we opt for
296 // DirectArguments.
297
298 m_argumentsRegister = addVar();
299 m_argumentsRegister->ref();
300 }
301
302 if (needsArguments && !codeBlock->isStrictMode()) {
303 // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we
304 // use DirectArguments. With ScopedArguments, we lift all of our arguments into the
305 // activation.
306
307 if (capturesAnyArgumentByName) {
308 m_symbolTable->setArgumentsLength(vm, parameters.size());
309
310 // For each parameter, we have two possibilities:
311 // Either it's a binding node with no function overlap, in which case it gets a name
312 // in the symbol table - or it just gets space reserved in the symbol table. Either
313 // way we lift the value into the scope.
314 for (unsigned i = 0; i < parameters.size(); ++i) {
315 ScopeOffset offset = m_symbolTable->takeNextScopeOffset();
316 m_symbolTable->setArgumentOffset(vm, i, offset);
317 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i))) {
318 VarOffset varOffset(offset);
319 SymbolTableEntry entry(varOffset);
320 // Stores to these variables via the ScopedArguments object will not do
321 // notifyWrite(), since that would be cumbersome. Also, watching formal
322 // parameters when "arguments" is in play is unlikely to be super profitable.
323 // So, we just disable it.
324 entry.disableWatching();
325 m_symbolTable->set(name, entry);
326 }
327 emitOpcode(op_put_to_scope);
328 instructions().append(m_lexicalEnvironmentRegister->index());
329 instructions().append(UINT_MAX);
330 instructions().append(virtualRegisterForArgument(1 + i).offset());
331 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand());
332 instructions().append(0);
333 instructions().append(offset.offset());
334 }
335
336 // This creates a scoped arguments object and copies the overflow arguments into the
337 // scope. It's the equivalent of calling ScopedArguments::createByCopying().
338 emitOpcode(op_create_scoped_arguments);
339 instructions().append(m_argumentsRegister->index());
340 instructions().append(m_lexicalEnvironmentRegister->index());
341 } else {
342 // We're going to put all parameters into the DirectArguments object. First ensure
343 // that the symbol table knows that this is happening.
344 for (unsigned i = 0; i < parameters.size(); ++i) {
345 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i)))
346 m_symbolTable->set(name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i))));
347 }
348
349 emitOpcode(op_create_direct_arguments);
350 instructions().append(m_argumentsRegister->index());
351 }
352 } else {
353 // Create the formal parameters the normal way. Any of them could be captured, or not. If
354 // captured, lift them into the scope.
355 for (unsigned i = 0; i < parameters.size(); ++i) {
356 UniquedStringImpl* name = visibleNameForParameter(parameters.at(i));
357 if (!name)
358 continue;
359
360 if (!captures(name)) {
361 // This is the easy case - just tell the symbol table about the argument. It will
362 // be accessed directly.
363 m_symbolTable->set(name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i))));
364 continue;
365 }
366
367 ScopeOffset offset = m_symbolTable->takeNextScopeOffset();
368 const Identifier& ident =
369 static_cast<const BindingNode*>(parameters.at(i))->boundProperty();
370 m_symbolTable->set(name, SymbolTableEntry(VarOffset(offset)));
371
372 emitOpcode(op_put_to_scope);
373 instructions().append(m_lexicalEnvironmentRegister->index());
374 instructions().append(addConstant(ident));
375 instructions().append(virtualRegisterForArgument(1 + i).offset());
376 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand());
377 instructions().append(0);
378 instructions().append(offset.offset());
379 }
380 }
381
382 if (needsArguments && codeBlock->isStrictMode()) {
383 // Allocate an out-of-bands arguments object.
384 emitOpcode(op_create_out_of_band_arguments);
385 instructions().append(m_argumentsRegister->index());
386 }
387
388 // Now declare all variables.
389 for (const Identifier& ident : boundParameterProperties)
390 createVariable(ident, varKind(ident.impl()), IsVariable);
391 for (FunctionBodyNode* function : functionNode->functionStack()) {
392 const Identifier& ident = function->ident();
393 createVariable(ident, varKind(ident.impl()), IsVariable);
394 m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
395 }
396 for (auto& entry : functionNode->varStack()) {
397 ConstantMode constantMode = modeForIsConstant(entry.second & DeclarationStacks::IsConstant);
398 // Variables named "arguments" are never const.
399 if (entry.first == propertyNames().arguments)
400 constantMode = IsVariable;
401 createVariable(entry.first, varKind(entry.first.impl()), constantMode, IgnoreExisting);
402 }
403
404 // There are some variables that need to be preinitialized to something other than Undefined:
405 //
406 // - "arguments": unless it's used as a function or parameter, this should refer to the
407 // arguments object.
408 //
409 // - callee: unless it's used as a var, function, or parameter, this should refer to the
410 // callee (i.e. our function).
411 //
412 // - functions: these always override everything else.
413 //
414 // The most logical way to do all of this is to initialize none of the variables until now,
415 // and then initialize them in BytecodeGenerator::generate() in such an order that the rules
416 // for how these things override each other end up holding. We would initialize the callee
417 // first, then "arguments", then all arguments, then the functions.
418 //
419 // But some arguments are already initialized by default, since if they aren't captured and we
420 // don't have "arguments" then we just point the symbol table at the stack slot of those
421 // arguments. We end up initializing the rest of the arguments that have an uncomplicated
422 // binding (i.e. don't involve destructuring) above when figuring out how to lay them out,
423 // because that's just the simplest thing. This means that when we initialize them, we have to
424 // watch out for the things that override arguments (namely, functions).
425 //
426 // We also initialize callee here as well, just because it's so weird. We know whether we want
427 // to do this because we can just check if it's in the symbol table.
428 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())
429 && !functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode())
430 && m_symbolTable->get(functionNode->ident().impl()).isNull()) {
431 if (captures(functionNode->ident().impl())) {
432 ScopeOffset offset;
433 {
434 ConcurrentJITLocker locker(m_symbolTable->m_lock);
435 offset = m_symbolTable->takeNextScopeOffset(locker);
436 m_symbolTable->add(
437 locker, functionNode->ident().impl(),
438 SymbolTableEntry(VarOffset(offset), ReadOnly));
439 }
440
441 emitOpcode(op_put_to_scope);
442 instructions().append(m_lexicalEnvironmentRegister->index());
443 instructions().append(addConstant(functionNode->ident()));
444 instructions().append(m_calleeRegister.index());
445 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand());
446 instructions().append(0);
447 instructions().append(offset.offset());
448 } else {
449 m_symbolTable->add(
450 functionNode->ident().impl(),
451 SymbolTableEntry(VarOffset(m_calleeRegister.virtualRegister()), ReadOnly));
452 }
453 }
454
455 // This is our final act of weirdness. "arguments" is overridden by everything except the
456 // callee. We add it to the symbol table if it's not already there and it's not an argument.
457 if (needsArguments) {
458 // If "arguments" is overridden by a function or destructuring parameter name, then it's
459 // OK for us to call createVariable() because it won't change anything. It's also OK for
460 // us to them tell BytecodeGenerator::generate() to write to it because it will do so
461 // before it initializes functions and destructuring parameters. But if "arguments" is
462 // overridden by a "simple" function parameter, then we have to bail: createVariable()
463 // would assert and BytecodeGenerator::generate() would write the "arguments" after the
464 // argument value had already been properly initialized.
465
466 bool haveParameterNamedArguments = false;
467 for (unsigned i = 0; i < parameters.size(); ++i) {
468 UniquedStringImpl* name = visibleNameForParameter(parameters.at(i));
469 if (name == propertyNames().arguments.impl()) {
470 haveParameterNamedArguments = true;
471 break;
472 }
473 }
474
475 if (!haveParameterNamedArguments) {
476 createVariable(
477 propertyNames().arguments, varKind(propertyNames().arguments.impl()), IsVariable);
478 m_needToInitializeArguments = true;
479 }
480 }
481
482 if (isConstructor()) {
483 if (constructorKind() == ConstructorKind::Derived) {
484 m_newTargetRegister = addVar();
485 emitMove(m_newTargetRegister, &m_thisRegister);
486 emitMoveEmptyValue(&m_thisRegister);
487 } else
488 emitCreateThis(&m_thisRegister);
489 } else if (constructorKind() != ConstructorKind::None) {
490 emitThrowTypeError("Cannot call a class constructor");
491 } else if (functionNode->usesThis() || codeBlock->usesEval()) {
492 m_codeBlock->addPropertyAccessInstruction(instructions().size());
493 emitOpcode(op_to_this);
494 instructions().append(kill(&m_thisRegister));
495 instructions().append(0);
496 instructions().append(0);
497 }
498 }
499
500 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)
501 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
502 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
503 , m_symbolTable(codeBlock->symbolTable())
504 , m_scopeNode(evalNode)
505 , m_codeBlock(vm, codeBlock)
506 , m_thisRegister(CallFrame::thisArgumentOffset())
507 , m_codeType(EvalCode)
508 , m_vm(&vm)
509 {
510 for (auto& constantRegister : m_linkTimeConstantRegisters)
511 constantRegister = nullptr;
512
513 m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
514 m_codeBlock->setNumParameters(1);
515
516 emitOpcode(op_enter);
517
518 allocateAndEmitScope();
519
520 const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
521 for (size_t i = 0; i < functionStack.size(); ++i)
522 m_codeBlock->addFunctionDecl(makeFunction(functionStack[i]));
523
524 const DeclarationStacks::VarStack& varStack = evalNode->varStack();
525 unsigned numVariables = varStack.size();
526 Vector<Identifier, 0, UnsafeVectorOverflow> variables;
527 variables.reserveCapacity(numVariables);
528 for (size_t i = 0; i < numVariables; ++i) {
529 ASSERT(varStack[i].first.impl()->isAtomic() || varStack[i].first.impl()->isSymbol());
530 variables.append(varStack[i].first);
531 }
532 codeBlock->adoptVariables(variables);
533 }
534
535 BytecodeGenerator::~BytecodeGenerator()
536 {
537 }
538
539 RegisterID* BytecodeGenerator::initializeNextParameter()
540 {
541 VirtualRegister reg = virtualRegisterForArgument(m_codeBlock->numParameters());
542 RegisterID& parameter = registerFor(reg);
543 parameter.setIndex(reg.offset());
544 m_codeBlock->addParameter();
545 return &parameter;
546 }
547
548 UniquedStringImpl* BytecodeGenerator::visibleNameForParameter(DestructuringPatternNode* pattern)
549 {
550 if (pattern->isBindingNode()) {
551 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
552 if (!m_functions.contains(ident.impl()))
553 return ident.impl();
554 }
555 return nullptr;
556 }
557
558 RegisterID* BytecodeGenerator::newRegister()
559 {
560 m_calleeRegisters.append(virtualRegisterForLocal(m_calleeRegisters.size()));
561 int numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size());
562 numCalleeRegisters = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numCalleeRegisters);
563 m_codeBlock->m_numCalleeRegisters = numCalleeRegisters;
564 return &m_calleeRegisters.last();
565 }
566
567 RegisterID* BytecodeGenerator::newTemporary()
568 {
569 // Reclaim free register IDs.
570 while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
571 m_calleeRegisters.removeLast();
572
573 RegisterID* result = newRegister();
574 result->setTemporary();
575 return result;
576 }
577
578 LabelScopePtr BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
579 {
580 // Reclaim free label scopes.
581 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
582 m_labelScopes.removeLast();
583
584 // Allocate new label scope.
585 LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
586 m_labelScopes.append(scope);
587 return LabelScopePtr(m_labelScopes, m_labelScopes.size() - 1);
588 }
589
590 PassRefPtr<Label> BytecodeGenerator::newLabel()
591 {
592 // Reclaim free label IDs.
593 while (m_labels.size() && !m_labels.last().refCount())
594 m_labels.removeLast();
595
596 // Allocate new label ID.
597 m_labels.append(*this);
598 return &m_labels.last();
599 }
600
601 PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
602 {
603 unsigned newLabelIndex = instructions().size();
604 l0->setLocation(newLabelIndex);
605
606 if (m_codeBlock->numberOfJumpTargets()) {
607 unsigned lastLabelIndex = m_codeBlock->lastJumpTarget();
608 ASSERT(lastLabelIndex <= newLabelIndex);
609 if (newLabelIndex == lastLabelIndex) {
610 // Peephole optimizations have already been disabled by emitting the last label
611 return l0;
612 }
613 }
614
615 m_codeBlock->addJumpTarget(newLabelIndex);
616
617 // This disables peephole optimizations when an instruction is a jump target
618 m_lastOpcodeID = op_end;
619 return l0;
620 }
621
622 void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
623 {
624 #ifndef NDEBUG
625 size_t opcodePosition = instructions().size();
626 ASSERT(opcodePosition - m_lastOpcodePosition == opcodeLength(m_lastOpcodeID) || m_lastOpcodeID == op_end);
627 m_lastOpcodePosition = opcodePosition;
628 #endif
629 instructions().append(opcodeID);
630 m_lastOpcodeID = opcodeID;
631 }
632
633 UnlinkedArrayProfile BytecodeGenerator::newArrayProfile()
634 {
635 return m_codeBlock->addArrayProfile();
636 }
637
638 UnlinkedArrayAllocationProfile BytecodeGenerator::newArrayAllocationProfile()
639 {
640 return m_codeBlock->addArrayAllocationProfile();
641 }
642
643 UnlinkedObjectAllocationProfile BytecodeGenerator::newObjectAllocationProfile()
644 {
645 return m_codeBlock->addObjectAllocationProfile();
646 }
647
648 UnlinkedValueProfile BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
649 {
650 UnlinkedValueProfile result = m_codeBlock->addValueProfile();
651 emitOpcode(opcodeID);
652 return result;
653 }
654
655 void BytecodeGenerator::emitLoopHint()
656 {
657 emitOpcode(op_loop_hint);
658 }
659
660 void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
661 {
662 ASSERT(instructions().size() >= 4);
663 size_t size = instructions().size();
664 dstIndex = instructions().at(size - 3).u.operand;
665 src1Index = instructions().at(size - 2).u.operand;
666 src2Index = instructions().at(size - 1).u.operand;
667 }
668
669 void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
670 {
671 ASSERT(instructions().size() >= 3);
672 size_t size = instructions().size();
673 dstIndex = instructions().at(size - 2).u.operand;
674 srcIndex = instructions().at(size - 1).u.operand;
675 }
676
677 void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
678 {
679 ASSERT(instructions().size() >= 4);
680 instructions().shrink(instructions().size() - 4);
681 m_lastOpcodeID = op_end;
682 }
683
684 void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
685 {
686 ASSERT(instructions().size() >= 3);
687 instructions().shrink(instructions().size() - 3);
688 m_lastOpcodeID = op_end;
689 }
690
691 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
692 {
693 size_t begin = instructions().size();
694 emitOpcode(op_jmp);
695 instructions().append(target->bind(begin, instructions().size()));
696 return target;
697 }
698
699 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
700 {
701 if (m_lastOpcodeID == op_less) {
702 int dstIndex;
703 int src1Index;
704 int src2Index;
705
706 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
707
708 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
709 rewindBinaryOp();
710
711 size_t begin = instructions().size();
712 emitOpcode(op_jless);
713 instructions().append(src1Index);
714 instructions().append(src2Index);
715 instructions().append(target->bind(begin, instructions().size()));
716 return target;
717 }
718 } else if (m_lastOpcodeID == op_lesseq) {
719 int dstIndex;
720 int src1Index;
721 int src2Index;
722
723 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
724
725 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
726 rewindBinaryOp();
727
728 size_t begin = instructions().size();
729 emitOpcode(op_jlesseq);
730 instructions().append(src1Index);
731 instructions().append(src2Index);
732 instructions().append(target->bind(begin, instructions().size()));
733 return target;
734 }
735 } else if (m_lastOpcodeID == op_greater) {
736 int dstIndex;
737 int src1Index;
738 int src2Index;
739
740 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
741
742 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
743 rewindBinaryOp();
744
745 size_t begin = instructions().size();
746 emitOpcode(op_jgreater);
747 instructions().append(src1Index);
748 instructions().append(src2Index);
749 instructions().append(target->bind(begin, instructions().size()));
750 return target;
751 }
752 } else if (m_lastOpcodeID == op_greatereq) {
753 int dstIndex;
754 int src1Index;
755 int src2Index;
756
757 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
758
759 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
760 rewindBinaryOp();
761
762 size_t begin = instructions().size();
763 emitOpcode(op_jgreatereq);
764 instructions().append(src1Index);
765 instructions().append(src2Index);
766 instructions().append(target->bind(begin, instructions().size()));
767 return target;
768 }
769 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
770 int dstIndex;
771 int srcIndex;
772
773 retrieveLastUnaryOp(dstIndex, srcIndex);
774
775 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
776 rewindUnaryOp();
777
778 size_t begin = instructions().size();
779 emitOpcode(op_jeq_null);
780 instructions().append(srcIndex);
781 instructions().append(target->bind(begin, instructions().size()));
782 return target;
783 }
784 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
785 int dstIndex;
786 int srcIndex;
787
788 retrieveLastUnaryOp(dstIndex, srcIndex);
789
790 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
791 rewindUnaryOp();
792
793 size_t begin = instructions().size();
794 emitOpcode(op_jneq_null);
795 instructions().append(srcIndex);
796 instructions().append(target->bind(begin, instructions().size()));
797 return target;
798 }
799 }
800
801 size_t begin = instructions().size();
802
803 emitOpcode(op_jtrue);
804 instructions().append(cond->index());
805 instructions().append(target->bind(begin, instructions().size()));
806 return target;
807 }
808
809 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
810 {
811 if (m_lastOpcodeID == op_less && target->isForward()) {
812 int dstIndex;
813 int src1Index;
814 int src2Index;
815
816 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
817
818 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
819 rewindBinaryOp();
820
821 size_t begin = instructions().size();
822 emitOpcode(op_jnless);
823 instructions().append(src1Index);
824 instructions().append(src2Index);
825 instructions().append(target->bind(begin, instructions().size()));
826 return target;
827 }
828 } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
829 int dstIndex;
830 int src1Index;
831 int src2Index;
832
833 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
834
835 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
836 rewindBinaryOp();
837
838 size_t begin = instructions().size();
839 emitOpcode(op_jnlesseq);
840 instructions().append(src1Index);
841 instructions().append(src2Index);
842 instructions().append(target->bind(begin, instructions().size()));
843 return target;
844 }
845 } else if (m_lastOpcodeID == op_greater && target->isForward()) {
846 int dstIndex;
847 int src1Index;
848 int src2Index;
849
850 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
851
852 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
853 rewindBinaryOp();
854
855 size_t begin = instructions().size();
856 emitOpcode(op_jngreater);
857 instructions().append(src1Index);
858 instructions().append(src2Index);
859 instructions().append(target->bind(begin, instructions().size()));
860 return target;
861 }
862 } else if (m_lastOpcodeID == op_greatereq && target->isForward()) {
863 int dstIndex;
864 int src1Index;
865 int src2Index;
866
867 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
868
869 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
870 rewindBinaryOp();
871
872 size_t begin = instructions().size();
873 emitOpcode(op_jngreatereq);
874 instructions().append(src1Index);
875 instructions().append(src2Index);
876 instructions().append(target->bind(begin, instructions().size()));
877 return target;
878 }
879 } else if (m_lastOpcodeID == op_not) {
880 int dstIndex;
881 int srcIndex;
882
883 retrieveLastUnaryOp(dstIndex, srcIndex);
884
885 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
886 rewindUnaryOp();
887
888 size_t begin = instructions().size();
889 emitOpcode(op_jtrue);
890 instructions().append(srcIndex);
891 instructions().append(target->bind(begin, instructions().size()));
892 return target;
893 }
894 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
895 int dstIndex;
896 int srcIndex;
897
898 retrieveLastUnaryOp(dstIndex, srcIndex);
899
900 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
901 rewindUnaryOp();
902
903 size_t begin = instructions().size();
904 emitOpcode(op_jneq_null);
905 instructions().append(srcIndex);
906 instructions().append(target->bind(begin, instructions().size()));
907 return target;
908 }
909 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
910 int dstIndex;
911 int srcIndex;
912
913 retrieveLastUnaryOp(dstIndex, srcIndex);
914
915 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
916 rewindUnaryOp();
917
918 size_t begin = instructions().size();
919 emitOpcode(op_jeq_null);
920 instructions().append(srcIndex);
921 instructions().append(target->bind(begin, instructions().size()));
922 return target;
923 }
924 }
925
926 size_t begin = instructions().size();
927 emitOpcode(op_jfalse);
928 instructions().append(cond->index());
929 instructions().append(target->bind(begin, instructions().size()));
930 return target;
931 }
932
933 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
934 {
935 size_t begin = instructions().size();
936
937 emitOpcode(op_jneq_ptr);
938 instructions().append(cond->index());
939 instructions().append(Special::CallFunction);
940 instructions().append(target->bind(begin, instructions().size()));
941 return target;
942 }
943
944 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
945 {
946 size_t begin = instructions().size();
947
948 emitOpcode(op_jneq_ptr);
949 instructions().append(cond->index());
950 instructions().append(Special::ApplyFunction);
951 instructions().append(target->bind(begin, instructions().size()));
952 return target;
953 }
954
955 bool BytecodeGenerator::hasConstant(const Identifier& ident) const
956 {
957 UniquedStringImpl* rep = ident.impl();
958 return m_identifierMap.contains(rep);
959 }
960
961 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
962 {
963 UniquedStringImpl* rep = ident.impl();
964 IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
965 if (result.isNewEntry)
966 m_codeBlock->addIdentifier(ident);
967
968 return result.iterator->value;
969 }
970
971 // We can't hash JSValue(), so we use a dedicated data member to cache it.
972 RegisterID* BytecodeGenerator::addConstantEmptyValue()
973 {
974 if (!m_emptyValueRegister) {
975 int index = m_nextConstantOffset;
976 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
977 ++m_nextConstantOffset;
978 m_codeBlock->addConstant(JSValue());
979 m_emptyValueRegister = &m_constantPoolRegisters[index];
980 }
981
982 return m_emptyValueRegister;
983 }
984
985 RegisterID* BytecodeGenerator::addConstantValue(JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
986 {
987 if (!v)
988 return addConstantEmptyValue();
989
990 int index = m_nextConstantOffset;
991
992 EncodedJSValueWithRepresentation valueMapKey { JSValue::encode(v), sourceCodeRepresentation };
993 JSValueMap::AddResult result = m_jsValueMap.add(valueMapKey, m_nextConstantOffset);
994 if (result.isNewEntry) {
995 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
996 ++m_nextConstantOffset;
997 m_codeBlock->addConstant(v, sourceCodeRepresentation);
998 } else
999 index = result.iterator->value;
1000 return &m_constantPoolRegisters[index];
1001 }
1002
1003 RegisterID* BytecodeGenerator::emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant type)
1004 {
1005 unsigned constantIndex = static_cast<unsigned>(type);
1006 if (!m_linkTimeConstantRegisters[constantIndex]) {
1007 int index = m_nextConstantOffset;
1008 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1009 ++m_nextConstantOffset;
1010 m_codeBlock->addConstant(type);
1011 m_linkTimeConstantRegisters[constantIndex] = &m_constantPoolRegisters[index];
1012 }
1013
1014 emitOpcode(op_mov);
1015 instructions().append(dst->index());
1016 instructions().append(m_linkTimeConstantRegisters[constantIndex]->index());
1017
1018 return dst;
1019 }
1020
1021 unsigned BytecodeGenerator::addRegExp(RegExp* r)
1022 {
1023 return m_codeBlock->addRegExp(r);
1024 }
1025
1026 RegisterID* BytecodeGenerator::emitMoveEmptyValue(RegisterID* dst)
1027 {
1028 RefPtr<RegisterID> emptyValue = addConstantEmptyValue();
1029
1030 emitOpcode(op_mov);
1031 instructions().append(dst->index());
1032 instructions().append(emptyValue->index());
1033 return dst;
1034 }
1035
1036 RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
1037 {
1038 ASSERT(src != m_emptyValueRegister);
1039
1040 m_staticPropertyAnalyzer.mov(dst->index(), src->index());
1041 emitOpcode(op_mov);
1042 instructions().append(dst->index());
1043 instructions().append(src->index());
1044
1045 if (!dst->isTemporary() && vm()->typeProfiler())
1046 emitProfileType(dst, ProfileTypeBytecodeHasGlobalID, nullptr);
1047
1048 return dst;
1049 }
1050
1051 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src)
1052 {
1053 emitOpcode(opcodeID);
1054 instructions().append(dst->index());
1055 instructions().append(src->index());
1056 return dst;
1057 }
1058
1059 RegisterID* BytecodeGenerator::emitInc(RegisterID* srcDst)
1060 {
1061 emitOpcode(op_inc);
1062 instructions().append(srcDst->index());
1063 return srcDst;
1064 }
1065
1066 RegisterID* BytecodeGenerator::emitDec(RegisterID* srcDst)
1067 {
1068 emitOpcode(op_dec);
1069 instructions().append(srcDst->index());
1070 return srcDst;
1071 }
1072
1073 RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
1074 {
1075 emitOpcode(opcodeID);
1076 instructions().append(dst->index());
1077 instructions().append(src1->index());
1078 instructions().append(src2->index());
1079
1080 if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
1081 opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
1082 instructions().append(types.toInt());
1083
1084 return dst;
1085 }
1086
1087 RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2)
1088 {
1089 if (m_lastOpcodeID == op_typeof) {
1090 int dstIndex;
1091 int srcIndex;
1092
1093 retrieveLastUnaryOp(dstIndex, srcIndex);
1094
1095 if (src1->index() == dstIndex
1096 && src1->isTemporary()
1097 && m_codeBlock->isConstantRegisterIndex(src2->index())
1098 && m_codeBlock->constantRegister(src2->index()).get().isString()) {
1099 const String& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
1100 if (value == "undefined") {
1101 rewindUnaryOp();
1102 emitOpcode(op_is_undefined);
1103 instructions().append(dst->index());
1104 instructions().append(srcIndex);
1105 return dst;
1106 }
1107 if (value == "boolean") {
1108 rewindUnaryOp();
1109 emitOpcode(op_is_boolean);
1110 instructions().append(dst->index());
1111 instructions().append(srcIndex);
1112 return dst;
1113 }
1114 if (value == "number") {
1115 rewindUnaryOp();
1116 emitOpcode(op_is_number);
1117 instructions().append(dst->index());
1118 instructions().append(srcIndex);
1119 return dst;
1120 }
1121 if (value == "string") {
1122 rewindUnaryOp();
1123 emitOpcode(op_is_string);
1124 instructions().append(dst->index());
1125 instructions().append(srcIndex);
1126 return dst;
1127 }
1128 if (value == "object") {
1129 rewindUnaryOp();
1130 emitOpcode(op_is_object_or_null);
1131 instructions().append(dst->index());
1132 instructions().append(srcIndex);
1133 return dst;
1134 }
1135 if (value == "function") {
1136 rewindUnaryOp();
1137 emitOpcode(op_is_function);
1138 instructions().append(dst->index());
1139 instructions().append(srcIndex);
1140 return dst;
1141 }
1142 }
1143 }
1144
1145 emitOpcode(opcodeID);
1146 instructions().append(dst->index());
1147 instructions().append(src1->index());
1148 instructions().append(src2->index());
1149 return dst;
1150 }
1151
1152 void BytecodeGenerator::emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
1153 {
1154 unsigned start = startDivot.offset; // Ranges are inclusive of their endpoints, AND 0 indexed.
1155 unsigned end = endDivot.offset - 1; // End Ranges already go one past the inclusive range, so subtract 1.
1156 unsigned instructionOffset = instructions().size() - 1;
1157 m_codeBlock->addTypeProfilerExpressionInfo(instructionOffset, start, end);
1158 }
1159
1160 void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const Identifier* identifier)
1161 {
1162 if (flag == ProfileTypeBytecodeGetFromScope || flag == ProfileTypeBytecodePutToScope)
1163 RELEASE_ASSERT(identifier);
1164
1165 // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
1166 emitOpcode(op_profile_type);
1167 instructions().append(registerToProfile->index());
1168 instructions().append(0);
1169 instructions().append(flag);
1170 instructions().append(identifier ? addConstant(*identifier) : 0);
1171 instructions().append(resolveType());
1172 }
1173
1174 void BytecodeGenerator::emitProfileControlFlow(int textOffset)
1175 {
1176 if (vm()->controlFlowProfiler()) {
1177 RELEASE_ASSERT(textOffset >= 0);
1178 size_t bytecodeOffset = instructions().size();
1179 m_codeBlock->addOpProfileControlFlowBytecodeOffset(bytecodeOffset);
1180
1181 emitOpcode(op_profile_control_flow);
1182 instructions().append(textOffset);
1183 }
1184 }
1185
1186 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
1187 {
1188 return emitLoad(dst, jsBoolean(b));
1189 }
1190
1191 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
1192 {
1193 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
1194 if (!stringInMap)
1195 stringInMap = jsOwnedString(vm(), identifier.string());
1196 return emitLoad(dst, JSValue(stringInMap));
1197 }
1198
1199 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
1200 {
1201 RegisterID* constantID = addConstantValue(v, sourceCodeRepresentation);
1202 if (dst)
1203 return emitMove(dst, constantID);
1204 return constantID;
1205 }
1206
1207 RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst)
1208 {
1209 if (!m_globalObjectRegister) {
1210 int index = m_nextConstantOffset;
1211 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1212 ++m_nextConstantOffset;
1213 m_codeBlock->addConstant(JSValue());
1214 m_globalObjectRegister = &m_constantPoolRegisters[index];
1215 m_codeBlock->setGlobalObjectRegister(VirtualRegister(index));
1216 }
1217 if (dst)
1218 emitMove(dst, m_globalObjectRegister);
1219 return m_globalObjectRegister;
1220 }
1221
1222 Variable BytecodeGenerator::variable(const Identifier& property)
1223 {
1224 if (property == propertyNames().thisIdentifier) {
1225 return Variable(
1226 property, VarOffset(thisRegister()->virtualRegister()), thisRegister(),
1227 ReadOnly, Variable::SpecialVariable);
1228 }
1229
1230 if (!shouldOptimizeLocals())
1231 return Variable(property);
1232
1233 SymbolTableEntry entry = symbolTable().get(property.impl());
1234 if (entry.isNull())
1235 return Variable(property);
1236
1237 if (entry.varOffset().isScope() && m_localScopeDepth) {
1238 // FIXME: We should be able to statically resolve through our local scopes.
1239 // https://bugs.webkit.org/show_bug.cgi?id=141885
1240 return Variable(property);
1241 }
1242
1243 return variableForLocalEntry(property, entry);
1244 }
1245
1246 Variable BytecodeGenerator::variablePerSymbolTable(const Identifier& property)
1247 {
1248 SymbolTableEntry entry = symbolTable().get(property.impl());
1249 if (entry.isNull())
1250 return Variable(property);
1251
1252 return variableForLocalEntry(property, entry);
1253 }
1254
1255 Variable BytecodeGenerator::variableForLocalEntry(
1256 const Identifier& property, const SymbolTableEntry& entry)
1257 {
1258 VarOffset offset = entry.varOffset();
1259
1260 RegisterID* local;
1261 if (offset.isStack())
1262 local = &registerFor(offset.stackOffset());
1263 else
1264 local = nullptr;
1265
1266 return Variable(property, offset, local, entry.getAttributes(), Variable::NormalVariable);
1267 }
1268
1269 void BytecodeGenerator::createVariable(
1270 const Identifier& property, VarKind varKind, ConstantMode constantMode,
1271 ExistingVariableMode existingVariableMode)
1272 {
1273 ASSERT(property != propertyNames().thisIdentifier);
1274
1275 ConcurrentJITLocker locker(symbolTable().m_lock);
1276 SymbolTableEntry entry = symbolTable().get(locker, property.impl());
1277
1278 if (!entry.isNull()) {
1279 if (existingVariableMode == IgnoreExisting)
1280 return;
1281
1282 // Do some checks to ensure that the variable we're being asked to create is sufficiently
1283 // compatible with the one we have already created.
1284
1285 VarOffset offset = entry.varOffset();
1286
1287 // We can't change our minds about whether it's captured.
1288 if (offset.kind() != varKind || constantMode != entry.constantMode()) {
1289 dataLog(
1290 "Trying to add variable called ", property, " as ", varKind, "/", constantMode,
1291 " but it was already added as ", offset, "/", entry.constantMode(), ".\n");
1292 RELEASE_ASSERT_NOT_REACHED();
1293 }
1294
1295 return;
1296 }
1297
1298 VarOffset varOffset;
1299 if (varKind == VarKind::Scope)
1300 varOffset = VarOffset(symbolTable().takeNextScopeOffset(locker));
1301 else {
1302 ASSERT(varKind == VarKind::Stack);
1303 varOffset = VarOffset(virtualRegisterForLocal(m_calleeRegisters.size()));
1304 }
1305 SymbolTableEntry newEntry(varOffset, constantMode == IsConstant ? ReadOnly : 0);
1306 symbolTable().add(locker, property.impl(), newEntry);
1307
1308 if (varKind == VarKind::Stack) {
1309 RegisterID* local = addVar();
1310 RELEASE_ASSERT(local->index() == varOffset.stackOffset().offset());
1311 }
1312 }
1313
1314 void BytecodeGenerator::emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target)
1315 {
1316 size_t begin = instructions().size();
1317 emitOpcode(op_check_has_instance);
1318 instructions().append(dst->index());
1319 instructions().append(value->index());
1320 instructions().append(base->index());
1321 instructions().append(target->bind(begin, instructions().size()));
1322 }
1323
1324 // Indicates the least upper bound of resolve type based on local scope. The bytecode linker
1325 // will start with this ResolveType and compute the least upper bound including intercepting scopes.
1326 ResolveType BytecodeGenerator::resolveType()
1327 {
1328 if (m_localScopeDepth)
1329 return Dynamic;
1330 if (m_symbolTable && m_symbolTable->usesNonStrictEval())
1331 return GlobalPropertyWithVarInjectionChecks;
1332 return GlobalProperty;
1333 }
1334
1335 RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Variable& variable)
1336 {
1337 switch (variable.offset().kind()) {
1338 case VarKind::Stack:
1339 return nullptr;
1340
1341 case VarKind::DirectArgument:
1342 return argumentsRegister();
1343
1344 case VarKind::Scope:
1345 // This always refers to the activation that *we* allocated, and not the current scope that code
1346 // lives in. Note that this will change once we have proper support for block scoping. Once that
1347 // changes, it will be correct for this code to return scopeRegister(). The only reason why we
1348 // don't do that already is that m_lexicalEnvironment is required by ConstDeclNode. ConstDeclNode
1349 // requires weird things because it is a shameful pile of nonsense, but block scoping would make
1350 // that code sensible and obviate the need for us to do bad things.
1351 return m_lexicalEnvironmentRegister;
1352
1353 case VarKind::Invalid:
1354 // Indicates non-local resolution.
1355
1356 ASSERT(!m_symbolTable || !m_symbolTable->contains(variable.ident().impl()) || resolveType() == Dynamic);
1357
1358 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1359
1360 // resolve_scope dst, id, ResolveType, depth
1361 emitOpcode(op_resolve_scope);
1362 dst = tempDestination(dst);
1363 instructions().append(kill(dst));
1364 instructions().append(scopeRegister()->index());
1365 instructions().append(addConstant(variable.ident()));
1366 instructions().append(resolveType());
1367 instructions().append(0);
1368 instructions().append(0);
1369 return dst;
1370 }
1371
1372 RELEASE_ASSERT_NOT_REACHED();
1373 return nullptr;
1374 }
1375
1376 RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable& variable, ResolveMode resolveMode)
1377 {
1378 switch (variable.offset().kind()) {
1379 case VarKind::Stack:
1380 return emitMove(dst, variable.local());
1381
1382 case VarKind::DirectArgument: {
1383 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_arguments);
1384 instructions().append(kill(dst));
1385 instructions().append(scope->index());
1386 instructions().append(variable.offset().capturedArgumentsOffset().offset());
1387 instructions().append(profile);
1388 return dst;
1389 }
1390
1391 case VarKind::Scope:
1392 case VarKind::Invalid: {
1393 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1394
1395 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
1396 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope);
1397 instructions().append(kill(dst));
1398 instructions().append(scope->index());
1399 instructions().append(addConstant(variable.ident()));
1400 instructions().append(ResolveModeAndType(resolveMode, variable.offset().isScope() ? LocalClosureVar : resolveType()).operand());
1401 instructions().append(0);
1402 instructions().append(variable.offset().isScope() ? variable.offset().scopeOffset().offset() : 0);
1403 instructions().append(profile);
1404 return dst;
1405 } }
1406
1407 RELEASE_ASSERT_NOT_REACHED();
1408 }
1409
1410 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Variable& variable, RegisterID* value, ResolveMode resolveMode)
1411 {
1412 switch (variable.offset().kind()) {
1413 case VarKind::Stack:
1414 emitMove(variable.local(), value);
1415 return value;
1416
1417 case VarKind::DirectArgument:
1418 emitOpcode(op_put_to_arguments);
1419 instructions().append(scope->index());
1420 instructions().append(variable.offset().capturedArgumentsOffset().offset());
1421 instructions().append(value->index());
1422 return value;
1423
1424 case VarKind::Scope:
1425 case VarKind::Invalid: {
1426 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1427
1428 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
1429 emitOpcode(op_put_to_scope);
1430 instructions().append(scope->index());
1431 instructions().append(addConstant(variable.ident()));
1432 instructions().append(value->index());
1433 ScopeOffset offset;
1434 if (variable.offset().isScope()) {
1435 offset = variable.offset().scopeOffset();
1436 instructions().append(ResolveModeAndType(resolveMode, LocalClosureVar).operand());
1437 } else {
1438 ASSERT(resolveType() != LocalClosureVar);
1439 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
1440 }
1441 instructions().append(0);
1442 instructions().append(!!offset ? offset.offset() : 0);
1443 return value;
1444 } }
1445
1446 RELEASE_ASSERT_NOT_REACHED();
1447 }
1448
1449 RegisterID* BytecodeGenerator::initializeVariable(const Variable& variable, RegisterID* value)
1450 {
1451 RegisterID* scope;
1452 switch (variable.offset().kind()) {
1453 case VarKind::Stack:
1454 scope = nullptr;
1455 break;
1456
1457 case VarKind::DirectArgument:
1458 scope = argumentsRegister();
1459 break;
1460
1461 case VarKind::Scope:
1462 scope = scopeRegister();
1463 break;
1464
1465 default:
1466 scope = nullptr;
1467 RELEASE_ASSERT_NOT_REACHED();
1468 break;
1469 }
1470
1471 return emitPutToScope(scope, variable, value, ThrowIfNotFound);
1472 }
1473
1474 RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype)
1475 {
1476 emitOpcode(op_instanceof);
1477 instructions().append(dst->index());
1478 instructions().append(value->index());
1479 instructions().append(basePrototype->index());
1480 return dst;
1481 }
1482
1483 RegisterID* BytecodeGenerator::emitInitGlobalConst(const Identifier& identifier, RegisterID* value)
1484 {
1485 ASSERT(m_codeType == GlobalCode);
1486 emitOpcode(op_init_global_const_nop);
1487 instructions().append(0);
1488 instructions().append(value->index());
1489 instructions().append(0);
1490 instructions().append(addConstant(identifier));
1491 return value;
1492 }
1493
1494 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
1495 {
1496 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1497
1498 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_id);
1499 instructions().append(kill(dst));
1500 instructions().append(base->index());
1501 instructions().append(addConstant(property));
1502 instructions().append(0);
1503 instructions().append(0);
1504 instructions().append(0);
1505 instructions().append(0);
1506 instructions().append(profile);
1507 return dst;
1508 }
1509
1510 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1511 {
1512 unsigned propertyIndex = addConstant(property);
1513
1514 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1515
1516 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1517
1518 emitOpcode(op_put_by_id);
1519 instructions().append(base->index());
1520 instructions().append(propertyIndex);
1521 instructions().append(value->index());
1522 instructions().append(0);
1523 instructions().append(0);
1524 instructions().append(0);
1525 instructions().append(0);
1526 instructions().append(0);
1527
1528 return value;
1529 }
1530
1531 RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType putType)
1532 {
1533 ASSERT(!parseIndex(property));
1534 unsigned propertyIndex = addConstant(property);
1535
1536 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1537
1538 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1539
1540 emitOpcode(op_put_by_id);
1541 instructions().append(base->index());
1542 instructions().append(propertyIndex);
1543 instructions().append(value->index());
1544 instructions().append(0);
1545 instructions().append(0);
1546 instructions().append(0);
1547 instructions().append(0);
1548 instructions().append(putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto);
1549 return value;
1550 }
1551
1552 void BytecodeGenerator::emitPutGetterById(RegisterID* base, const Identifier& property, RegisterID* getter)
1553 {
1554 unsigned propertyIndex = addConstant(property);
1555 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1556
1557 emitOpcode(op_put_getter_by_id);
1558 instructions().append(base->index());
1559 instructions().append(propertyIndex);
1560 instructions().append(getter->index());
1561 }
1562
1563 void BytecodeGenerator::emitPutSetterById(RegisterID* base, const Identifier& property, RegisterID* setter)
1564 {
1565 unsigned propertyIndex = addConstant(property);
1566 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1567
1568 emitOpcode(op_put_setter_by_id);
1569 instructions().append(base->index());
1570 instructions().append(propertyIndex);
1571 instructions().append(setter->index());
1572 }
1573
1574 void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter)
1575 {
1576 unsigned propertyIndex = addConstant(property);
1577
1578 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1579
1580 emitOpcode(op_put_getter_setter);
1581 instructions().append(base->index());
1582 instructions().append(propertyIndex);
1583 instructions().append(getter->index());
1584 instructions().append(setter->index());
1585 }
1586
1587 RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
1588 {
1589 emitOpcode(op_del_by_id);
1590 instructions().append(dst->index());
1591 instructions().append(base->index());
1592 instructions().append(addConstant(property));
1593 return dst;
1594 }
1595
1596 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1597 {
1598 for (size_t i = m_forInContextStack.size(); i > 0; i--) {
1599 ForInContext* context = m_forInContextStack[i - 1].get();
1600 if (context->local() != property)
1601 continue;
1602
1603 if (!context->isValid())
1604 break;
1605
1606 if (context->type() == ForInContext::IndexedForInContextType) {
1607 property = static_cast<IndexedForInContext*>(context)->index();
1608 break;
1609 }
1610
1611 ASSERT(context->type() == ForInContext::StructureForInContextType);
1612 StructureForInContext* structureContext = static_cast<StructureForInContext*>(context);
1613 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_direct_pname);
1614 instructions().append(kill(dst));
1615 instructions().append(base->index());
1616 instructions().append(property->index());
1617 instructions().append(structureContext->index()->index());
1618 instructions().append(structureContext->enumerator()->index());
1619 instructions().append(profile);
1620 return dst;
1621 }
1622
1623 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1624 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val);
1625 instructions().append(kill(dst));
1626 instructions().append(base->index());
1627 instructions().append(property->index());
1628 instructions().append(arrayProfile);
1629 instructions().append(profile);
1630 return dst;
1631 }
1632
1633 RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1634 {
1635 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1636 emitOpcode(op_put_by_val);
1637 instructions().append(base->index());
1638 instructions().append(property->index());
1639 instructions().append(value->index());
1640 instructions().append(arrayProfile);
1641
1642 return value;
1643 }
1644
1645 RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1646 {
1647 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1648 emitOpcode(op_put_by_val_direct);
1649 instructions().append(base->index());
1650 instructions().append(property->index());
1651 instructions().append(value->index());
1652 instructions().append(arrayProfile);
1653 return value;
1654 }
1655
1656 RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1657 {
1658 emitOpcode(op_del_by_val);
1659 instructions().append(dst->index());
1660 instructions().append(base->index());
1661 instructions().append(property->index());
1662 return dst;
1663 }
1664
1665 RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1666 {
1667 emitOpcode(op_put_by_index);
1668 instructions().append(base->index());
1669 instructions().append(index);
1670 instructions().append(value->index());
1671 return value;
1672 }
1673
1674 RegisterID* BytecodeGenerator::emitCreateThis(RegisterID* dst)
1675 {
1676 size_t begin = instructions().size();
1677 m_staticPropertyAnalyzer.createThis(m_thisRegister.index(), begin + 3);
1678
1679 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1680 emitOpcode(op_create_this);
1681 instructions().append(m_thisRegister.index());
1682 instructions().append(m_thisRegister.index());
1683 instructions().append(0);
1684 instructions().append(0);
1685 return dst;
1686 }
1687
1688 void BytecodeGenerator::emitTDZCheck(RegisterID* target)
1689 {
1690 emitOpcode(op_check_tdz);
1691 instructions().append(target->index());
1692 }
1693
1694 RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
1695 {
1696 size_t begin = instructions().size();
1697 m_staticPropertyAnalyzer.newObject(dst->index(), begin + 2);
1698
1699 emitOpcode(op_new_object);
1700 instructions().append(dst->index());
1701 instructions().append(0);
1702 instructions().append(newObjectAllocationProfile());
1703 return dst;
1704 }
1705
1706 unsigned BytecodeGenerator::addConstantBuffer(unsigned length)
1707 {
1708 return m_codeBlock->addConstantBuffer(length);
1709 }
1710
1711 JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
1712 {
1713 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
1714 if (!stringInMap) {
1715 stringInMap = jsString(vm(), identifier.string());
1716 addConstantValue(stringInMap);
1717 }
1718 return stringInMap;
1719 }
1720
1721 JSTemplateRegistryKey* BytecodeGenerator::addTemplateRegistryKeyConstant(const TemplateRegistryKey& templateRegistryKey)
1722 {
1723 JSTemplateRegistryKey*& templateRegistryKeyInMap = m_templateRegistryKeyMap.add(templateRegistryKey, nullptr).iterator->value;
1724 if (!templateRegistryKeyInMap) {
1725 templateRegistryKeyInMap = JSTemplateRegistryKey::create(*vm(), templateRegistryKey);
1726 addConstantValue(templateRegistryKeyInMap);
1727 }
1728 return templateRegistryKeyInMap;
1729 }
1730
1731 RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length)
1732 {
1733 #if !ASSERT_DISABLED
1734 unsigned checkLength = 0;
1735 #endif
1736 bool hadVariableExpression = false;
1737 if (length) {
1738 for (ElementNode* n = elements; n; n = n->next()) {
1739 if (!n->value()->isConstant()) {
1740 hadVariableExpression = true;
1741 break;
1742 }
1743 if (n->elision())
1744 break;
1745 #if !ASSERT_DISABLED
1746 checkLength++;
1747 #endif
1748 }
1749 if (!hadVariableExpression) {
1750 ASSERT(length == checkLength);
1751 unsigned constantBufferIndex = addConstantBuffer(length);
1752 JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex).data();
1753 unsigned index = 0;
1754 for (ElementNode* n = elements; index < length; n = n->next()) {
1755 ASSERT(n->value()->isConstant());
1756 constantBuffer[index++] = static_cast<ConstantNode*>(n->value())->jsValue(*this);
1757 }
1758 emitOpcode(op_new_array_buffer);
1759 instructions().append(dst->index());
1760 instructions().append(constantBufferIndex);
1761 instructions().append(length);
1762 instructions().append(newArrayAllocationProfile());
1763 return dst;
1764 }
1765 }
1766
1767 Vector<RefPtr<RegisterID>, 16, UnsafeVectorOverflow> argv;
1768 for (ElementNode* n = elements; n; n = n->next()) {
1769 if (!length)
1770 break;
1771 length--;
1772 ASSERT(!n->value()->isSpreadExpression());
1773 argv.append(newTemporary());
1774 // op_new_array requires the initial values to be a sequential range of registers
1775 ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() - 1);
1776 emitNode(argv.last().get(), n->value());
1777 }
1778 ASSERT(!length);
1779 emitOpcode(op_new_array);
1780 instructions().append(dst->index());
1781 instructions().append(argv.size() ? argv[0]->index() : 0); // argv
1782 instructions().append(argv.size()); // argc
1783 instructions().append(newArrayAllocationProfile());
1784 return dst;
1785 }
1786
1787 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
1788 {
1789 return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(function)));
1790 }
1791
1792 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index)
1793 {
1794 emitOpcode(op_new_func);
1795 instructions().append(dst->index());
1796 instructions().append(scopeRegister()->index());
1797 instructions().append(index);
1798 return dst;
1799 }
1800
1801 RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
1802 {
1803 emitOpcode(op_new_regexp);
1804 instructions().append(dst->index());
1805 instructions().append(addRegExp(regExp));
1806 return dst;
1807 }
1808
1809 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
1810 {
1811 FunctionBodyNode* function = n->body();
1812 unsigned index = m_codeBlock->addFunctionExpr(makeFunction(function));
1813
1814 emitOpcode(op_new_func_exp);
1815 instructions().append(r0->index());
1816 instructions().append(scopeRegister()->index());
1817 instructions().append(index);
1818 return r0;
1819 }
1820
1821 RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name)
1822 {
1823 UnlinkedFunctionExecutable* executable = m_vm->builtinExecutables()->createDefaultConstructor(constructorKind, name);
1824
1825 unsigned index = m_codeBlock->addFunctionExpr(executable);
1826
1827 emitOpcode(op_new_func_exp);
1828 instructions().append(dst->index());
1829 instructions().append(scopeRegister()->index());
1830 instructions().append(index);
1831 return dst;
1832 }
1833
1834 RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1835 {
1836 return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
1837 }
1838
1839 RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1840 {
1841 return emitCall(op_call_eval, dst, func, NoExpectedFunction, callArguments, divot, divotStart, divotEnd);
1842 }
1843
1844 ExpectedFunction BytecodeGenerator::expectedFunctionForIdentifier(const Identifier& identifier)
1845 {
1846 if (identifier == m_vm->propertyNames->Object || identifier == m_vm->propertyNames->ObjectPrivateName)
1847 return ExpectObjectConstructor;
1848 if (identifier == m_vm->propertyNames->Array || identifier == m_vm->propertyNames->ArrayPrivateName)
1849 return ExpectArrayConstructor;
1850 return NoExpectedFunction;
1851 }
1852
1853 ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, Label* done)
1854 {
1855 RefPtr<Label> realCall = newLabel();
1856 switch (expectedFunction) {
1857 case ExpectObjectConstructor: {
1858 // If the number of arguments is non-zero, then we can't do anything interesting.
1859 if (callArguments.argumentCountIncludingThis() >= 2)
1860 return NoExpectedFunction;
1861
1862 size_t begin = instructions().size();
1863 emitOpcode(op_jneq_ptr);
1864 instructions().append(func->index());
1865 instructions().append(Special::ObjectConstructor);
1866 instructions().append(realCall->bind(begin, instructions().size()));
1867
1868 if (dst != ignoredResult())
1869 emitNewObject(dst);
1870 break;
1871 }
1872
1873 case ExpectArrayConstructor: {
1874 // If you're doing anything other than "new Array()" or "new Array(foo)" then we
1875 // don't do inline it, for now. The only reason is that call arguments are in
1876 // the opposite order of what op_new_array expects, so we'd either need to change
1877 // how op_new_array works or we'd need an op_new_array_reverse. Neither of these
1878 // things sounds like it's worth it.
1879 if (callArguments.argumentCountIncludingThis() > 2)
1880 return NoExpectedFunction;
1881
1882 size_t begin = instructions().size();
1883 emitOpcode(op_jneq_ptr);
1884 instructions().append(func->index());
1885 instructions().append(Special::ArrayConstructor);
1886 instructions().append(realCall->bind(begin, instructions().size()));
1887
1888 if (dst != ignoredResult()) {
1889 if (callArguments.argumentCountIncludingThis() == 2) {
1890 emitOpcode(op_new_array_with_size);
1891 instructions().append(dst->index());
1892 instructions().append(callArguments.argumentRegister(0)->index());
1893 instructions().append(newArrayAllocationProfile());
1894 } else {
1895 ASSERT(callArguments.argumentCountIncludingThis() == 1);
1896 emitOpcode(op_new_array);
1897 instructions().append(dst->index());
1898 instructions().append(0);
1899 instructions().append(0);
1900 instructions().append(newArrayAllocationProfile());
1901 }
1902 }
1903 break;
1904 }
1905
1906 default:
1907 ASSERT(expectedFunction == NoExpectedFunction);
1908 return NoExpectedFunction;
1909 }
1910
1911 size_t begin = instructions().size();
1912 emitOpcode(op_jmp);
1913 instructions().append(done->bind(begin, instructions().size()));
1914 emitLabel(realCall.get());
1915
1916 return expectedFunction;
1917 }
1918
1919 RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1920 {
1921 ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
1922 ASSERT(func->refCount());
1923
1924 if (m_shouldEmitProfileHooks)
1925 emitMove(callArguments.profileHookRegister(), func);
1926
1927 // Generate code for arguments.
1928 unsigned argument = 0;
1929 if (callArguments.argumentsNode()) {
1930 ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
1931 if (n && n->m_expr->isSpreadExpression()) {
1932 RELEASE_ASSERT(!n->m_next);
1933 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
1934 RefPtr<RegisterID> argumentRegister;
1935 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
1936 RefPtr<RegisterID> thisRegister = emitMove(newTemporary(), callArguments.thisRegister());
1937 return emitCallVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
1938 }
1939 for (; n; n = n->m_next)
1940 emitNode(callArguments.argumentRegister(argument++), n);
1941 }
1942
1943 // Reserve space for call frame.
1944 Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
1945 for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
1946 callFrame.append(newTemporary());
1947
1948 if (m_shouldEmitProfileHooks) {
1949 emitOpcode(op_profile_will_call);
1950 instructions().append(callArguments.profileHookRegister()->index());
1951 }
1952
1953 emitExpressionInfo(divot, divotStart, divotEnd);
1954
1955 RefPtr<Label> done = newLabel();
1956 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
1957
1958 // Emit call.
1959 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1960 UnlinkedValueProfile profile = emitProfiledOpcode(opcodeID);
1961 ASSERT(dst);
1962 ASSERT(dst != ignoredResult());
1963 instructions().append(dst->index());
1964 instructions().append(func->index());
1965 instructions().append(callArguments.argumentCountIncludingThis());
1966 instructions().append(callArguments.stackOffset());
1967 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
1968 instructions().append(0);
1969 instructions().append(arrayProfile);
1970 instructions().append(profile);
1971
1972 if (expectedFunction != NoExpectedFunction)
1973 emitLabel(done.get());
1974
1975 if (m_shouldEmitProfileHooks) {
1976 emitOpcode(op_profile_did_call);
1977 instructions().append(callArguments.profileHookRegister()->index());
1978 }
1979
1980 return dst;
1981 }
1982
1983 RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1984 {
1985 return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
1986 }
1987
1988 RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1989 {
1990 return emitCallVarargs(op_construct_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
1991 }
1992
1993 RegisterID* BytecodeGenerator::emitCallVarargs(OpcodeID opcode, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
1994 {
1995 if (m_shouldEmitProfileHooks) {
1996 emitMove(profileHookRegister, func);
1997 emitOpcode(op_profile_will_call);
1998 instructions().append(profileHookRegister->index());
1999 }
2000
2001 emitExpressionInfo(divot, divotStart, divotEnd);
2002
2003 // Emit call.
2004 UnlinkedArrayProfile arrayProfile = newArrayProfile();
2005 UnlinkedValueProfile profile = emitProfiledOpcode(opcode);
2006 ASSERT(dst != ignoredResult());
2007 instructions().append(dst->index());
2008 instructions().append(func->index());
2009 instructions().append(thisRegister ? thisRegister->index() : 0);
2010 instructions().append(arguments->index());
2011 instructions().append(firstFreeRegister->index());
2012 instructions().append(firstVarArgOffset);
2013 instructions().append(arrayProfile);
2014 instructions().append(profile);
2015 if (m_shouldEmitProfileHooks) {
2016 emitOpcode(op_profile_did_call);
2017 instructions().append(profileHookRegister->index());
2018 }
2019 return dst;
2020 }
2021
2022 void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
2023 RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition& position)
2024 {
2025 RefPtr<RegisterID> descriptorRegister = emitNewObject(newTemporary());
2026
2027 RefPtr<RegisterID> trueRegister = emitLoad(newTemporary(), true);
2028 if (options & PropertyConfigurable)
2029 emitDirectPutById(descriptorRegister.get(), propertyNames().configurable, trueRegister.get(), PropertyNode::Unknown);
2030 if (options & PropertyWritable)
2031 emitDirectPutById(descriptorRegister.get(), propertyNames().writable, trueRegister.get(), PropertyNode::Unknown);
2032 else if (valueRegister) {
2033 RefPtr<RegisterID> falseRegister = emitLoad(newTemporary(), false);
2034 emitDirectPutById(descriptorRegister.get(), propertyNames().writable, falseRegister.get(), PropertyNode::Unknown);
2035 }
2036 if (options & PropertyEnumerable)
2037 emitDirectPutById(descriptorRegister.get(), propertyNames().enumerable, trueRegister.get(), PropertyNode::Unknown);
2038
2039 if (valueRegister)
2040 emitDirectPutById(descriptorRegister.get(), propertyNames().value, valueRegister, PropertyNode::Unknown);
2041 if (getterRegister)
2042 emitDirectPutById(descriptorRegister.get(), propertyNames().get, getterRegister, PropertyNode::Unknown);
2043 if (setterRegister)
2044 emitDirectPutById(descriptorRegister.get(), propertyNames().set, setterRegister, PropertyNode::Unknown);
2045
2046 RefPtr<RegisterID> definePropertyRegister = emitMoveLinkTimeConstant(newTemporary(), LinkTimeConstant::DefinePropertyFunction);
2047
2048 CallArguments callArguments(*this, nullptr, 3);
2049 emitLoad(callArguments.thisRegister(), jsUndefined());
2050 emitMove(callArguments.argumentRegister(0), newObj);
2051 emitMove(callArguments.argumentRegister(1), propertyNameRegister);
2052 emitMove(callArguments.argumentRegister(2), descriptorRegister.get());
2053
2054 emitCall(newTemporary(), definePropertyRegister.get(), NoExpectedFunction, callArguments, position, position, position);
2055 }
2056
2057 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
2058 {
2059 if (isConstructor()) {
2060 bool derived = constructorKind() == ConstructorKind::Derived;
2061 if (derived && src->index() == m_thisRegister.index())
2062 emitTDZCheck(src);
2063
2064 RefPtr<Label> isObjectLabel = newLabel();
2065 emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
2066
2067 if (derived) {
2068 RefPtr<Label> isUndefinedLabel = newLabel();
2069 emitJumpIfTrue(emitIsUndefined(newTemporary(), src), isUndefinedLabel.get());
2070 emitThrowTypeError("Cannot return a non-object type in the constructor of a derived class.");
2071 emitLabel(isUndefinedLabel.get());
2072 if (constructorKind() == ConstructorKind::Derived)
2073 emitTDZCheck(&m_thisRegister);
2074 }
2075
2076 emitUnaryNoDstOp(op_ret, &m_thisRegister);
2077
2078 emitLabel(isObjectLabel.get());
2079 }
2080
2081 return emitUnaryNoDstOp(op_ret, src);
2082 }
2083
2084 RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src)
2085 {
2086 emitOpcode(opcodeID);
2087 instructions().append(src->index());
2088 return src;
2089 }
2090
2091 RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
2092 {
2093 ASSERT(func->refCount());
2094
2095 if (m_shouldEmitProfileHooks)
2096 emitMove(callArguments.profileHookRegister(), func);
2097
2098 // Generate code for arguments.
2099 unsigned argument = 0;
2100 if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
2101
2102 ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
2103 if (n && n->m_expr->isSpreadExpression()) {
2104 RELEASE_ASSERT(!n->m_next);
2105 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
2106 RefPtr<RegisterID> argumentRegister;
2107 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
2108 return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
2109 }
2110
2111 for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
2112 emitNode(callArguments.argumentRegister(argument++), n);
2113 }
2114
2115 if (m_shouldEmitProfileHooks) {
2116 emitOpcode(op_profile_will_call);
2117 instructions().append(callArguments.profileHookRegister()->index());
2118 }
2119
2120 // Reserve space for call frame.
2121 Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
2122 for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
2123 callFrame.append(newTemporary());
2124
2125 emitExpressionInfo(divot, divotStart, divotEnd);
2126
2127 RefPtr<Label> done = newLabel();
2128 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
2129
2130 UnlinkedValueProfile profile = emitProfiledOpcode(op_construct);
2131 ASSERT(dst != ignoredResult());
2132 instructions().append(dst->index());
2133 instructions().append(func->index());
2134 instructions().append(callArguments.argumentCountIncludingThis());
2135 instructions().append(callArguments.stackOffset());
2136 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
2137 instructions().append(0);
2138 instructions().append(0);
2139 instructions().append(profile);
2140
2141 if (expectedFunction != NoExpectedFunction)
2142 emitLabel(done.get());
2143
2144 if (m_shouldEmitProfileHooks) {
2145 emitOpcode(op_profile_did_call);
2146 instructions().append(callArguments.profileHookRegister()->index());
2147 }
2148
2149 return dst;
2150 }
2151
2152 RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
2153 {
2154 emitOpcode(op_strcat);
2155 instructions().append(dst->index());
2156 instructions().append(src->index());
2157 instructions().append(count);
2158
2159 return dst;
2160 }
2161
2162 void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
2163 {
2164 emitOpcode(op_to_primitive);
2165 instructions().append(dst->index());
2166 instructions().append(src->index());
2167 }
2168
2169 void BytecodeGenerator::emitGetScope()
2170 {
2171 emitOpcode(op_get_scope);
2172 instructions().append(scopeRegister()->index());
2173 }
2174
2175 RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* dst, RegisterID* scope)
2176 {
2177 ControlFlowContext context;
2178 context.isFinallyBlock = false;
2179 m_scopeContextStack.append(context);
2180 m_localScopeDepth++;
2181
2182 return emitUnaryOp(op_push_with_scope, dst, scope);
2183 }
2184
2185 void BytecodeGenerator::emitPopScope(RegisterID* srcDst)
2186 {
2187 ASSERT(m_scopeContextStack.size());
2188 ASSERT(!m_scopeContextStack.last().isFinallyBlock);
2189
2190 emitOpcode(op_pop_scope);
2191 instructions().append(srcDst->index());
2192
2193 m_scopeContextStack.removeLast();
2194 m_localScopeDepth--;
2195 }
2196
2197 void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, unsigned line, unsigned charOffset, unsigned lineStart)
2198 {
2199 #if ENABLE(DEBUG_WITH_BREAKPOINT)
2200 if (debugHookID != DidReachBreakpoint)
2201 return;
2202 #else
2203 if (!m_shouldEmitDebugHooks)
2204 return;
2205 #endif
2206 JSTextPosition divot(line, charOffset, lineStart);
2207 emitExpressionInfo(divot, divot, divot);
2208 emitOpcode(op_debug);
2209 instructions().append(debugHookID);
2210 instructions().append(false);
2211 }
2212
2213 void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock)
2214 {
2215 // Reclaim free label scopes.
2216 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2217 m_labelScopes.removeLast();
2218
2219 ControlFlowContext scope;
2220 scope.isFinallyBlock = true;
2221 FinallyContext context = {
2222 finallyBlock,
2223 nullptr,
2224 nullptr,
2225 static_cast<unsigned>(m_scopeContextStack.size()),
2226 static_cast<unsigned>(m_switchContextStack.size()),
2227 static_cast<unsigned>(m_forInContextStack.size()),
2228 static_cast<unsigned>(m_tryContextStack.size()),
2229 static_cast<unsigned>(m_labelScopes.size()),
2230 m_finallyDepth,
2231 m_localScopeDepth
2232 };
2233 scope.finallyContext = context;
2234 m_scopeContextStack.append(scope);
2235 m_finallyDepth++;
2236 }
2237
2238 void BytecodeGenerator::pushIteratorCloseContext(RegisterID* iterator, ThrowableExpressionData* node)
2239 {
2240 // Reclaim free label scopes.
2241 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2242 m_labelScopes.removeLast();
2243
2244 ControlFlowContext scope;
2245 scope.isFinallyBlock = true;
2246 FinallyContext context = {
2247 nullptr,
2248 iterator,
2249 node,
2250 static_cast<unsigned>(m_scopeContextStack.size()),
2251 static_cast<unsigned>(m_switchContextStack.size()),
2252 static_cast<unsigned>(m_forInContextStack.size()),
2253 static_cast<unsigned>(m_tryContextStack.size()),
2254 static_cast<unsigned>(m_labelScopes.size()),
2255 m_finallyDepth,
2256 m_localScopeDepth
2257 };
2258 scope.finallyContext = context;
2259 m_scopeContextStack.append(scope);
2260 m_finallyDepth++;
2261 }
2262
2263 void BytecodeGenerator::popFinallyContext()
2264 {
2265 ASSERT(m_scopeContextStack.size());
2266 ASSERT(m_scopeContextStack.last().isFinallyBlock);
2267 ASSERT(m_scopeContextStack.last().finallyContext.finallyBlock);
2268 ASSERT(!m_scopeContextStack.last().finallyContext.iterator);
2269 ASSERT(!m_scopeContextStack.last().finallyContext.enumerationNode);
2270 ASSERT(m_finallyDepth > 0);
2271 m_scopeContextStack.removeLast();
2272 m_finallyDepth--;
2273 }
2274
2275 void BytecodeGenerator::popIteratorCloseContext()
2276 {
2277 ASSERT(m_scopeContextStack.size());
2278 ASSERT(m_scopeContextStack.last().isFinallyBlock);
2279 ASSERT(!m_scopeContextStack.last().finallyContext.finallyBlock);
2280 ASSERT(m_scopeContextStack.last().finallyContext.iterator);
2281 ASSERT(m_scopeContextStack.last().finallyContext.enumerationNode);
2282 ASSERT(m_finallyDepth > 0);
2283 m_scopeContextStack.removeLast();
2284 m_finallyDepth--;
2285 }
2286
2287 LabelScopePtr BytecodeGenerator::breakTarget(const Identifier& name)
2288 {
2289 // Reclaim free label scopes.
2290 //
2291 // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
2292 // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
2293 // size 0, leading to segfaulty badness. We are yet to identify a valid cause within our code to
2294 // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
2295 // loop condition is a workaround.
2296 while (m_labelScopes.size()) {
2297 if (m_labelScopes.last().refCount())
2298 break;
2299 m_labelScopes.removeLast();
2300 }
2301
2302 if (!m_labelScopes.size())
2303 return LabelScopePtr::null();
2304
2305 // We special-case the following, which is a syntax error in Firefox:
2306 // label:
2307 // break;
2308 if (name.isEmpty()) {
2309 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2310 LabelScope* scope = &m_labelScopes[i];
2311 if (scope->type() != LabelScope::NamedLabel) {
2312 ASSERT(scope->breakTarget());
2313 return LabelScopePtr(m_labelScopes, i);
2314 }
2315 }
2316 return LabelScopePtr::null();
2317 }
2318
2319 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2320 LabelScope* scope = &m_labelScopes[i];
2321 if (scope->name() && *scope->name() == name) {
2322 ASSERT(scope->breakTarget());
2323 return LabelScopePtr(m_labelScopes, i);
2324 }
2325 }
2326 return LabelScopePtr::null();
2327 }
2328
2329 LabelScopePtr BytecodeGenerator::continueTarget(const Identifier& name)
2330 {
2331 // Reclaim free label scopes.
2332 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2333 m_labelScopes.removeLast();
2334
2335 if (!m_labelScopes.size())
2336 return LabelScopePtr::null();
2337
2338 if (name.isEmpty()) {
2339 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2340 LabelScope* scope = &m_labelScopes[i];
2341 if (scope->type() == LabelScope::Loop) {
2342 ASSERT(scope->continueTarget());
2343 return LabelScopePtr(m_labelScopes, i);
2344 }
2345 }
2346 return LabelScopePtr::null();
2347 }
2348
2349 // Continue to the loop nested nearest to the label scope that matches
2350 // 'name'.
2351 LabelScopePtr result = LabelScopePtr::null();
2352 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2353 LabelScope* scope = &m_labelScopes[i];
2354 if (scope->type() == LabelScope::Loop) {
2355 ASSERT(scope->continueTarget());
2356 result = LabelScopePtr(m_labelScopes, i);
2357 }
2358 if (scope->name() && *scope->name() == name)
2359 return result; // may be null.
2360 }
2361 return LabelScopePtr::null();
2362 }
2363
2364 void BytecodeGenerator::allocateAndEmitScope()
2365 {
2366 m_scopeRegister = addVar();
2367 m_scopeRegister->ref();
2368 m_codeBlock->setScopeRegister(scopeRegister()->virtualRegister());
2369 emitGetScope();
2370 }
2371
2372 void BytecodeGenerator::emitComplexPopScopes(RegisterID* scope, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
2373 {
2374 while (topScope > bottomScope) {
2375 // First we count the number of dynamic scopes we need to remove to get
2376 // to a finally block.
2377 int nNormalScopes = 0;
2378 while (topScope > bottomScope) {
2379 if (topScope->isFinallyBlock)
2380 break;
2381 ++nNormalScopes;
2382 --topScope;
2383 }
2384
2385 if (nNormalScopes) {
2386 // We need to remove a number of dynamic scopes to get to the next
2387 // finally block
2388 while (nNormalScopes--) {
2389 emitOpcode(op_pop_scope);
2390 instructions().append(scope->index());
2391 }
2392
2393 // If topScope == bottomScope then there isn't a finally block left to emit.
2394 if (topScope == bottomScope)
2395 return;
2396 }
2397
2398 Vector<ControlFlowContext> savedScopeContextStack;
2399 Vector<SwitchInfo> savedSwitchContextStack;
2400 Vector<std::unique_ptr<ForInContext>> savedForInContextStack;
2401 Vector<TryContext> poppedTryContexts;
2402 LabelScopeStore savedLabelScopes;
2403 while (topScope > bottomScope && topScope->isFinallyBlock) {
2404 RefPtr<Label> beforeFinally = emitLabel(newLabel().get());
2405
2406 // Save the current state of the world while instating the state of the world
2407 // for the finally block.
2408 FinallyContext finallyContext = topScope->finallyContext;
2409 bool flipScopes = finallyContext.scopeContextStackSize != m_scopeContextStack.size();
2410 bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size();
2411 bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size();
2412 bool flipTries = finallyContext.tryContextStackSize != m_tryContextStack.size();
2413 bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size();
2414 int topScopeIndex = -1;
2415 int bottomScopeIndex = -1;
2416 if (flipScopes) {
2417 topScopeIndex = topScope - m_scopeContextStack.begin();
2418 bottomScopeIndex = bottomScope - m_scopeContextStack.begin();
2419 savedScopeContextStack = m_scopeContextStack;
2420 m_scopeContextStack.shrink(finallyContext.scopeContextStackSize);
2421 }
2422 if (flipSwitches) {
2423 savedSwitchContextStack = m_switchContextStack;
2424 m_switchContextStack.shrink(finallyContext.switchContextStackSize);
2425 }
2426 if (flipForIns) {
2427 savedForInContextStack.swap(m_forInContextStack);
2428 m_forInContextStack.shrink(finallyContext.forInContextStackSize);
2429 }
2430 if (flipTries) {
2431 while (m_tryContextStack.size() != finallyContext.tryContextStackSize) {
2432 ASSERT(m_tryContextStack.size() > finallyContext.tryContextStackSize);
2433 TryContext context = m_tryContextStack.last();
2434 m_tryContextStack.removeLast();
2435 TryRange range;
2436 range.start = context.start;
2437 range.end = beforeFinally;
2438 range.tryData = context.tryData;
2439 m_tryRanges.append(range);
2440 poppedTryContexts.append(context);
2441 }
2442 }
2443 if (flipLabelScopes) {
2444 savedLabelScopes = m_labelScopes;
2445 while (m_labelScopes.size() > finallyContext.labelScopesSize)
2446 m_labelScopes.removeLast();
2447 }
2448 int savedFinallyDepth = m_finallyDepth;
2449 m_finallyDepth = finallyContext.finallyDepth;
2450 int savedDynamicScopeDepth = m_localScopeDepth;
2451 m_localScopeDepth = finallyContext.dynamicScopeDepth;
2452
2453 if (finallyContext.finallyBlock) {
2454 // Emit the finally block.
2455 emitNode(finallyContext.finallyBlock);
2456 } else {
2457 // Emit the IteratorClose block.
2458 ASSERT(finallyContext.iterator);
2459 emitIteratorClose(finallyContext.iterator, finallyContext.enumerationNode);
2460 }
2461
2462 RefPtr<Label> afterFinally = emitLabel(newLabel().get());
2463
2464 // Restore the state of the world.
2465 if (flipScopes) {
2466 m_scopeContextStack = savedScopeContextStack;
2467 topScope = &m_scopeContextStack[topScopeIndex]; // assert it's within bounds
2468 bottomScope = m_scopeContextStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1.
2469 }
2470 if (flipSwitches)
2471 m_switchContextStack = savedSwitchContextStack;
2472 if (flipForIns)
2473 m_forInContextStack.swap(savedForInContextStack);
2474 if (flipTries) {
2475 ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize);
2476 for (unsigned i = poppedTryContexts.size(); i--;) {
2477 TryContext context = poppedTryContexts[i];
2478 context.start = afterFinally;
2479 m_tryContextStack.append(context);
2480 }
2481 poppedTryContexts.clear();
2482 }
2483 if (flipLabelScopes)
2484 m_labelScopes = savedLabelScopes;
2485 m_finallyDepth = savedFinallyDepth;
2486 m_localScopeDepth = savedDynamicScopeDepth;
2487
2488 --topScope;
2489 }
2490 }
2491 }
2492
2493 void BytecodeGenerator::emitPopScopes(RegisterID* scope, int targetScopeDepth)
2494 {
2495 ASSERT(scopeDepth() - targetScopeDepth >= 0);
2496
2497 size_t scopeDelta = scopeDepth() - targetScopeDepth;
2498 ASSERT(scopeDelta <= m_scopeContextStack.size());
2499 if (!scopeDelta)
2500 return;
2501
2502 if (!m_finallyDepth) {
2503 while (scopeDelta--) {
2504 emitOpcode(op_pop_scope);
2505 instructions().append(scope->index());
2506 }
2507 return;
2508 }
2509
2510 emitComplexPopScopes(scope, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
2511 }
2512
2513 TryData* BytecodeGenerator::pushTry(Label* start)
2514 {
2515 TryData tryData;
2516 tryData.target = newLabel();
2517 tryData.targetScopeDepth = UINT_MAX;
2518 tryData.handlerType = HandlerType::Illegal;
2519 m_tryData.append(tryData);
2520 TryData* result = &m_tryData.last();
2521
2522 TryContext tryContext;
2523 tryContext.start = start;
2524 tryContext.tryData = result;
2525
2526 m_tryContextStack.append(tryContext);
2527
2528 return result;
2529 }
2530
2531 void BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType handlerType)
2532 {
2533 m_usesExceptions = true;
2534
2535 ASSERT_UNUSED(tryData, m_tryContextStack.last().tryData == tryData);
2536
2537 TryRange tryRange;
2538 tryRange.start = m_tryContextStack.last().start;
2539 tryRange.end = end;
2540 tryRange.tryData = m_tryContextStack.last().tryData;
2541 m_tryRanges.append(tryRange);
2542 m_tryContextStack.removeLast();
2543
2544 emitLabel(tryRange.tryData->target.get());
2545 tryRange.tryData->targetScopeDepth = m_localScopeDepth;
2546 tryRange.tryData->handlerType = handlerType;
2547
2548 emitOpcode(op_catch);
2549 instructions().append(exceptionRegister->index());
2550 instructions().append(thrownValueRegister->index());
2551 }
2552
2553 void BytecodeGenerator::emitThrowReferenceError(const String& message)
2554 {
2555 emitOpcode(op_throw_static_error);
2556 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, message)))->index());
2557 instructions().append(true);
2558 }
2559
2560 void BytecodeGenerator::emitThrowTypeError(const String& message)
2561 {
2562 emitOpcode(op_throw_static_error);
2563 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, message)))->index());
2564 instructions().append(false);
2565 }
2566
2567 void BytecodeGenerator::emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)
2568 {
2569 emitOpcode(op_push_name_scope);
2570 instructions().append(dst->index());
2571 instructions().append(value->index());
2572 instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property, attributes))->index());
2573 instructions().append(JSNameScope::FunctionNameScope);
2574 }
2575
2576 void BytecodeGenerator::emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)
2577 {
2578 ControlFlowContext context;
2579 context.isFinallyBlock = false;
2580 m_scopeContextStack.append(context);
2581 m_localScopeDepth++;
2582
2583 emitOpcode(op_push_name_scope);
2584 instructions().append(dst->index());
2585 instructions().append(value->index());
2586 instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property, attributes))->index());
2587 instructions().append(JSNameScope::CatchScope);
2588 }
2589
2590 void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
2591 {
2592 SwitchInfo info = { static_cast<uint32_t>(instructions().size()), type };
2593 switch (type) {
2594 case SwitchInfo::SwitchImmediate:
2595 emitOpcode(op_switch_imm);
2596 break;
2597 case SwitchInfo::SwitchCharacter:
2598 emitOpcode(op_switch_char);
2599 break;
2600 case SwitchInfo::SwitchString:
2601 emitOpcode(op_switch_string);
2602 break;
2603 default:
2604 RELEASE_ASSERT_NOT_REACHED();
2605 }
2606
2607 instructions().append(0); // place holder for table index
2608 instructions().append(0); // place holder for default target
2609 instructions().append(scrutineeRegister->index());
2610 m_switchContextStack.append(info);
2611 }
2612
2613 static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
2614 {
2615 UNUSED_PARAM(max);
2616 ASSERT(node->isNumber());
2617 double value = static_cast<NumberNode*>(node)->value();
2618 int32_t key = static_cast<int32_t>(value);
2619 ASSERT(key == value);
2620 ASSERT(key >= min);
2621 ASSERT(key <= max);
2622 return key - min;
2623 }
2624
2625 static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
2626 {
2627 UNUSED_PARAM(max);
2628 ASSERT(node->isString());
2629 StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
2630 ASSERT(clause->length() == 1);
2631
2632 int32_t key = (*clause)[0];
2633 ASSERT(key >= min);
2634 ASSERT(key <= max);
2635 return key - min;
2636 }
2637
2638 static void prepareJumpTableForSwitch(
2639 UnlinkedSimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount,
2640 RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max,
2641 int32_t (*keyGetter)(ExpressionNode*, int32_t min, int32_t max))
2642 {
2643 jumpTable.min = min;
2644 jumpTable.branchOffsets.resize(max - min + 1);
2645 jumpTable.branchOffsets.fill(0);
2646 for (uint32_t i = 0; i < clauseCount; ++i) {
2647 // We're emitting this after the clause labels should have been fixed, so
2648 // the labels should not be "forward" references
2649 ASSERT(!labels[i]->isForward());
2650 jumpTable.add(keyGetter(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3));
2651 }
2652 }
2653
2654 static void prepareJumpTableForStringSwitch(UnlinkedStringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
2655 {
2656 for (uint32_t i = 0; i < clauseCount; ++i) {
2657 // We're emitting this after the clause labels should have been fixed, so
2658 // the labels should not be "forward" references
2659 ASSERT(!labels[i]->isForward());
2660
2661 ASSERT(nodes[i]->isString());
2662 StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
2663 jumpTable.offsetTable.add(clause, labels[i]->bind(switchAddress, switchAddress + 3));
2664 }
2665 }
2666
2667 void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max)
2668 {
2669 SwitchInfo switchInfo = m_switchContextStack.last();
2670 m_switchContextStack.removeLast();
2671
2672 switch (switchInfo.switchType) {
2673 case SwitchInfo::SwitchImmediate:
2674 case SwitchInfo::SwitchCharacter: {
2675 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfSwitchJumpTables();
2676 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
2677
2678 UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->addSwitchJumpTable();
2679 prepareJumpTableForSwitch(
2680 jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max,
2681 switchInfo.switchType == SwitchInfo::SwitchImmediate
2682 ? keyForImmediateSwitch
2683 : keyForCharacterSwitch);
2684 break;
2685 }
2686
2687 case SwitchInfo::SwitchString: {
2688 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
2689 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
2690
2691 UnlinkedStringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
2692 prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
2693 break;
2694 }
2695
2696 default:
2697 RELEASE_ASSERT_NOT_REACHED();
2698 break;
2699 }
2700 }
2701
2702 RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
2703 {
2704 // It would be nice to do an even better job of identifying exactly where the expression is.
2705 // And we could make the caller pass the node pointer in, if there was some way of getting
2706 // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
2707 // is still good enough to get us an accurate line number.
2708 m_expressionTooDeep = true;
2709 return newTemporary();
2710 }
2711
2712 bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
2713 {
2714 RegisterID* registerID = variable(ident).local();
2715 if (!registerID)
2716 return false;
2717 return registerID->index() == CallFrame::argumentOffset(argumentNumber);
2718 }
2719
2720 void BytecodeGenerator::emitReadOnlyExceptionIfNeeded()
2721 {
2722 if (!isStrictMode())
2723 return;
2724 emitOpcode(op_throw_static_error);
2725 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, StrictModeReadonlyPropertyWriteError)))->index());
2726 instructions().append(false);
2727 }
2728
2729 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack)
2730 {
2731 RefPtr<RegisterID> subject = newTemporary();
2732 emitNode(subject.get(), subjectNode);
2733 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), subject.get(), propertyNames().iteratorSymbol);
2734 {
2735 CallArguments args(*this, nullptr);
2736 emitMove(args.thisRegister(), subject.get());
2737 emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd());
2738 }
2739
2740 RefPtr<Label> loopDone = newLabel();
2741 // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext.
2742 pushIteratorCloseContext(iterator.get(), node);
2743 {
2744 LabelScopePtr scope = newLabelScope(LabelScope::Loop);
2745 RefPtr<RegisterID> value = newTemporary();
2746 emitLoad(value.get(), jsUndefined());
2747
2748 emitJump(scope->continueTarget());
2749
2750 RefPtr<Label> loopStart = newLabel();
2751 emitLabel(loopStart.get());
2752 emitLoopHint();
2753
2754 RefPtr<Label> tryStartLabel = newLabel();
2755 emitLabel(tryStartLabel.get());
2756 TryData* tryData = pushTry(tryStartLabel.get());
2757 callBack(*this, value.get());
2758 emitJump(scope->continueTarget());
2759
2760 // IteratorClose sequence for throw-ed control flow.
2761 {
2762 RefPtr<Label> catchHere = emitLabel(newLabel().get());
2763 RefPtr<RegisterID> exceptionRegister = newTemporary();
2764 RefPtr<RegisterID> thrownValueRegister = newTemporary();
2765 popTryAndEmitCatch(tryData, exceptionRegister.get(),
2766 thrownValueRegister.get(), catchHere.get(), HandlerType::SynthesizedFinally);
2767
2768 RefPtr<Label> catchDone = newLabel();
2769
2770 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
2771 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), catchDone.get());
2772
2773 RefPtr<Label> returnCallTryStart = newLabel();
2774 emitLabel(returnCallTryStart.get());
2775 TryData* returnCallTryData = pushTry(returnCallTryStart.get());
2776
2777 CallArguments returnArguments(*this, nullptr);
2778 emitMove(returnArguments.thisRegister(), iterator.get());
2779 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd());
2780
2781 emitLabel(catchDone.get());
2782 emitThrow(exceptionRegister.get());
2783
2784 // Absorb exception.
2785 popTryAndEmitCatch(returnCallTryData, newTemporary(),
2786 newTemporary(), catchDone.get(), HandlerType::SynthesizedFinally);
2787 emitThrow(exceptionRegister.get());
2788 }
2789
2790 emitLabel(scope->continueTarget());
2791 {
2792 emitIteratorNext(value.get(), iterator.get(), node);
2793 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get());
2794 emitGetById(value.get(), value.get(), propertyNames().value);
2795 emitJump(loopStart.get());
2796 }
2797
2798 emitLabel(scope->breakTarget());
2799 }
2800
2801 // IteratorClose sequence for break-ed control flow.
2802 popIteratorCloseContext();
2803 emitIteratorClose(iterator.get(), node);
2804 emitLabel(loopDone.get());
2805 }
2806
2807 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2808 RegisterID* BytecodeGenerator::emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode* taggedTemplate)
2809 {
2810 TemplateRegistryKey::StringVector rawStrings;
2811 TemplateRegistryKey::StringVector cookedStrings;
2812
2813 TemplateStringListNode* templateString = taggedTemplate->templateLiteral()->templateStrings();
2814 for (; templateString; templateString = templateString->next()) {
2815 rawStrings.append(templateString->value()->raw().impl());
2816 cookedStrings.append(templateString->value()->cooked().impl());
2817 }
2818
2819 RefPtr<RegisterID> getTemplateObject = nullptr;
2820 Variable var = variable(propertyNames().getTemplateObjectPrivateName);
2821 if (RegisterID* local = var.local())
2822 getTemplateObject = emitMove(newTemporary(), local);
2823 else {
2824 getTemplateObject = newTemporary();
2825 RefPtr<RegisterID> scope = newTemporary();
2826 moveToDestinationIfNeeded(scope.get(), emitResolveScope(scope.get(), var));
2827 emitGetFromScope(getTemplateObject.get(), scope.get(), var, ThrowIfNotFound);
2828 }
2829
2830 CallArguments arguments(*this, nullptr);
2831 emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(TemplateRegistryKey(rawStrings, cookedStrings))));
2832 return emitCall(dst, getTemplateObject.get(), NoExpectedFunction, arguments, taggedTemplate->divot(), taggedTemplate->divotStart(), taggedTemplate->divotEnd());
2833 }
2834 #endif
2835
2836 RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)
2837 {
2838 emitOpcode(op_get_enumerable_length);
2839 instructions().append(dst->index());
2840 instructions().append(base->index());
2841 return dst;
2842 }
2843
2844 RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
2845 {
2846 emitOpcode(op_has_generic_property);
2847 instructions().append(dst->index());
2848 instructions().append(base->index());
2849 instructions().append(propertyName->index());
2850 return dst;
2851 }
2852
2853 RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
2854 {
2855 UnlinkedArrayProfile arrayProfile = newArrayProfile();
2856 emitOpcode(op_has_indexed_property);
2857 instructions().append(dst->index());
2858 instructions().append(base->index());
2859 instructions().append(propertyName->index());
2860 instructions().append(arrayProfile);
2861 return dst;
2862 }
2863
2864 RegisterID* BytecodeGenerator::emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
2865 {
2866 emitOpcode(op_has_structure_property);
2867 instructions().append(dst->index());
2868 instructions().append(base->index());
2869 instructions().append(propertyName->index());
2870 instructions().append(enumerator->index());
2871 return dst;
2872 }
2873
2874 RegisterID* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base)
2875 {
2876 emitOpcode(op_get_property_enumerator);
2877 instructions().append(dst->index());
2878 instructions().append(base->index());
2879 return dst;
2880 }
2881
2882 RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
2883 {
2884 emitOpcode(op_enumerator_structure_pname);
2885 instructions().append(dst->index());
2886 instructions().append(enumerator->index());
2887 instructions().append(index->index());
2888 return dst;
2889 }
2890
2891 RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
2892 {
2893 emitOpcode(op_enumerator_generic_pname);
2894 instructions().append(dst->index());
2895 instructions().append(enumerator->index());
2896 instructions().append(index->index());
2897 return dst;
2898 }
2899
2900 RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)
2901 {
2902 emitOpcode(op_to_index_string);
2903 instructions().append(dst->index());
2904 instructions().append(index->index());
2905 return dst;
2906 }
2907
2908
2909 RegisterID* BytecodeGenerator::emitIsObject(RegisterID* dst, RegisterID* src)
2910 {
2911 emitOpcode(op_is_object);
2912 instructions().append(dst->index());
2913 instructions().append(src->index());
2914 return dst;
2915 }
2916
2917 RegisterID* BytecodeGenerator::emitIsUndefined(RegisterID* dst, RegisterID* src)
2918 {
2919 emitOpcode(op_is_undefined);
2920 instructions().append(dst->index());
2921 instructions().append(src->index());
2922 return dst;
2923 }
2924
2925 RegisterID* BytecodeGenerator::emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node)
2926 {
2927 {
2928 RefPtr<RegisterID> next = emitGetById(newTemporary(), iterator, propertyNames().next);
2929 CallArguments nextArguments(*this, nullptr);
2930 emitMove(nextArguments.thisRegister(), iterator);
2931 emitCall(dst, next.get(), NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd());
2932 }
2933 {
2934 RefPtr<Label> typeIsObject = newLabel();
2935 emitJumpIfTrue(emitIsObject(newTemporary(), dst), typeIsObject.get());
2936 emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
2937 emitLabel(typeIsObject.get());
2938 }
2939 return dst;
2940 }
2941
2942 void BytecodeGenerator::emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node)
2943 {
2944 RefPtr<Label> done = newLabel();
2945 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator, propertyNames().returnKeyword);
2946 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), done.get());
2947
2948 RefPtr<RegisterID> value = newTemporary();
2949 CallArguments returnArguments(*this, nullptr);
2950 emitMove(returnArguments.thisRegister(), iterator);
2951 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd());
2952 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), done.get());
2953 emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
2954 emitLabel(done.get());
2955 }
2956
2957 void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
2958 {
2959 if (!localRegister)
2960 return;
2961 m_forInContextStack.append(std::make_unique<IndexedForInContext>(localRegister, indexRegister));
2962 }
2963
2964 void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
2965 {
2966 if (!localRegister)
2967 return;
2968 m_forInContextStack.removeLast();
2969 }
2970
2971 void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
2972 {
2973 if (!localRegister)
2974 return;
2975 m_forInContextStack.append(std::make_unique<StructureForInContext>(localRegister, indexRegister, propertyRegister, enumeratorRegister));
2976 }
2977
2978 void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
2979 {
2980 if (!localRegister)
2981 return;
2982 m_forInContextStack.removeLast();
2983 }
2984
2985 void BytecodeGenerator::invalidateForInContextForLocal(RegisterID* localRegister)
2986 {
2987 // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
2988 // either of the following conditions is true:
2989 //
2990 // (1) The loop iteration variable is re-assigned within the body of the loop.
2991 // (2) The loop iteration variable is captured in the lexical scope of the function.
2992 //
2993 // These two situations occur sufficiently rarely that it's okay to use this style of
2994 // "analysis" to make iteration faster. If we didn't want to do this, we would either have
2995 // to perform some flow-sensitive analysis to see if/when the loop iteration variable was
2996 // reassigned, or we'd have to resort to runtime checks to see if the variable had been
2997 // reassigned from its original value.
2998 for (size_t i = m_forInContextStack.size(); i > 0; i--) {
2999 ForInContext* context = m_forInContextStack[i - 1].get();
3000 if (context->local() != localRegister)
3001 continue;
3002 context->invalidate();
3003 break;
3004 }
3005 }
3006
3007 } // namespace JSC