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.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "BytecodeGenerator.h"
34 #include "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"
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>
54 void Label::setLocation(unsigned location)
56 m_location = location;
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;
63 ParserError BytecodeGenerator::generate()
65 SamplingRegion samplingRegion("Bytecode Generation");
67 m_codeBlock->setThisRegister(m_thisRegister.virtualRegister());
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);
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());
79 pushLexicalScope(m_scopeNode, true);
82 RefPtr<RegisterID> temp = newTemporary();
83 RefPtr<RegisterID> globalScope;
84 for (auto functionPair : m_functionsToInitialize) {
85 FunctionBodyNode* functionBody = functionPair.first;
86 FunctionVariableType functionType = functionPair.second;
87 emitNewFunction(temp.get(), functionBody);
88 if (functionType == NormalFunctionVariable)
89 initializeVariable(variable(functionBody->ident()) , temp.get());
90 else if (functionType == GlobalFunctionVariable) {
92 if (m_symbolTableStack.isEmpty() || !m_symbolTableStack.first().m_scope) {
93 // We haven't allocated a lexical scope on top of the global object, so scopeRegister() will correspond to the global scope.
94 globalScope = scopeRegister();
96 // We know this will resolve to the global object because our parser doesn't allow
97 // "let" variables to have the same names as functions.
98 ASSERT(m_scopeNode->lexicalVariables().hasCapturedVariables());
99 RefPtr<RegisterID> globalObjectScope = emitResolveScope(nullptr, Variable(functionBody->ident()));
100 globalScope = newBlockScopeVariable();
101 emitMove(globalScope.get(), globalObjectScope.get());
104 emitPutToScope(globalScope.get(), Variable(functionBody->ident()), temp.get(), ThrowIfNotFound);
106 RELEASE_ASSERT_NOT_REACHED();
110 bool callingClassConstructor = constructorKind() != ConstructorKind::None && !isConstructor();
111 if (!callingClassConstructor)
112 m_scopeNode->emitBytecode(*this);
114 m_staticPropertyAnalyzer.kill();
116 for (unsigned i = 0; i < m_tryRanges.size(); ++i) {
117 TryRange& range = m_tryRanges[i];
118 int start = range.start->bind();
119 int end = range.end->bind();
121 // This will happen for empty try blocks and for some cases of finally blocks:
133 // The return will pop scopes to execute the outer finally block. But this includes
134 // popping the try context for the inner try. The try context is live in the fall-through
135 // part of the finally block not because we will emit a handler that overlaps the finally,
136 // but because we haven't yet had a chance to plant the catch target. Then when we finish
137 // emitting code for the outer finally block, we repush the try contex, this time with a
138 // new start index. But that means that the start index for the try range corresponding
139 // to the inner-finally-following-the-return (marked as "*HERE*" above) will be greater
140 // than the end index of the try block. This is harmless since end < start handlers will
141 // never get matched in our logic, but we do the runtime a favor and choose to not emit
142 // such handlers at all.
146 ASSERT(range.tryData->targetScopeDepth != UINT_MAX);
147 ASSERT(range.tryData->handlerType != HandlerType::Illegal);
148 UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
149 static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->targetScopeDepth,
150 range.tryData->handlerType);
151 m_codeBlock->addExceptionHandler(info);
154 m_codeBlock->setInstructions(std::make_unique<UnlinkedInstructionStream>(m_instructions));
156 m_codeBlock->shrinkToFit();
158 if (m_codeBlock->symbolTable() && !m_codeBlock->vm()->typeProfiler())
159 m_codeBlock->setSymbolTable(m_codeBlock->symbolTable()->cloneScopePart(*m_codeBlock->vm()));
161 if (m_expressionTooDeep)
162 return ParserError(ParserError::OutOfMemory);
163 return ParserError(ParserError::ErrorNone);
166 BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
167 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
168 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
169 , m_scopeNode(programNode)
170 , m_codeBlock(vm, codeBlock)
171 , m_thisRegister(CallFrame::thisArgumentOffset())
172 , m_codeType(GlobalCode)
175 ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());
177 for (auto& constantRegister : m_linkTimeConstantRegisters)
178 constantRegister = nullptr;
180 m_codeBlock->setNumParameters(1); // Allocate space for "this"
182 emitOpcode(op_enter);
184 allocateAndEmitScope();
186 const FunctionStack& functionStack = programNode->functionStack();
188 for (size_t i = 0; i < functionStack.size(); ++i) {
189 FunctionBodyNode* function = functionStack[i];
190 m_functionsToInitialize.append(std::make_pair(function, GlobalFunctionVariable));
192 if (Options::validateBytecode()) {
193 for (auto& entry : programNode->varDeclarations()) {
194 // FIXME: When supporting ES6 spec compliant const, this should only check isVar().
195 RELEASE_ASSERT(entry.value.isVar() || entry.value.isConstant());
198 codeBlock->setVariableDeclarations(programNode->varDeclarations());
201 BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
202 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
203 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
204 , m_symbolTable(codeBlock->symbolTable())
205 , m_scopeNode(functionNode)
206 , m_codeBlock(vm, codeBlock)
207 , m_codeType(FunctionCode)
209 , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
211 for (auto& constantRegister : m_linkTimeConstantRegisters)
212 constantRegister = nullptr;
214 if (m_isBuiltinFunction)
215 m_shouldEmitDebugHooks = false;
217 m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
218 Vector<Identifier> boundParameterProperties;
219 FunctionParameters& parameters = *functionNode->parameters();
220 for (size_t i = 0; i < parameters.size(); i++) {
221 auto pattern = parameters.at(i);
222 if (pattern->isBindingNode())
224 pattern->collectBoundIdentifiers(boundParameterProperties);
228 bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || m_codeBlock->needsFullScopeChain();
229 bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock->usesEval();
230 bool needsArguments = functionNode->usesArguments() || codeBlock->usesEval();
231 if (shouldCaptureAllOfTheThings)
232 functionNode->varDeclarations().markAllVariablesAsCaptured();
234 auto captures = [&] (UniquedStringImpl* uid) -> bool {
235 if (!shouldCaptureSomeOfTheThings)
237 if (needsArguments && uid == propertyNames().arguments.impl()) {
238 // Actually, we only need to capture the arguments object when we "need full activation"
239 // because of name scopes. But historically we did it this way, so for now we just preserve
241 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=143072
244 return functionNode->captures(uid);
246 auto varKind = [&] (UniquedStringImpl* uid) -> VarKind {
247 return captures(uid) ? VarKind::Scope : VarKind::Stack;
250 emitOpcode(op_enter);
252 allocateAndEmitScope();
254 m_calleeRegister.setIndex(JSStack::Callee);
256 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())
257 && functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode())) {
258 // When we do this, we should make our local scope stack know about the function name symbol
259 // table. Currently this works because bytecode linking creates a phony name scope.
260 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
261 // Also, we could create the scope once per JSFunction instance that needs it. That wouldn't
262 // be any more correct, but it would be more performant.
263 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141887
264 emitPushFunctionNameScope(m_scopeRegister, functionNode->ident(), &m_calleeRegister, ReadOnly | DontDelete);
267 int symbolTableConstantIndex = addConstantValue(m_symbolTable)->index();
268 m_codeBlock->setSymbolTableConstantIndex(symbolTableConstantIndex);
269 if (shouldCaptureSomeOfTheThings) {
270 m_lexicalEnvironmentRegister = addVar();
271 m_codeBlock->setActivationRegister(m_lexicalEnvironmentRegister->virtualRegister());
272 emitOpcode(op_create_lexical_environment);
273 instructions().append(m_lexicalEnvironmentRegister->index());
274 instructions().append(scopeRegister()->index());
275 instructions().append(symbolTableConstantIndex);
276 instructions().append(addConstantValue(jsUndefined())->index());
279 instructions().append(scopeRegister()->index());
280 instructions().append(m_lexicalEnvironmentRegister->index());
283 // Make sure the code block knows about all of our parameters, and make sure that parameters
284 // needing destructuring are noted.
285 m_parameters.grow(parameters.size() + 1); // reserve space for "this"
286 m_thisRegister.setIndex(initializeNextParameter()->index()); // this
287 for (unsigned i = 0; i < parameters.size(); ++i) {
288 auto pattern = parameters.at(i);
289 RegisterID* reg = initializeNextParameter();
290 if (!pattern->isBindingNode())
291 m_destructuringParameters.append(std::make_pair(reg, pattern));
294 // Figure out some interesting facts about our arguments.
295 bool capturesAnyArgumentByName = false;
296 if (functionNode->hasCapturedVariables()) {
297 FunctionParameters& parameters = *functionNode->parameters();
298 for (size_t i = 0; i < parameters.size(); ++i) {
299 auto pattern = parameters.at(i);
300 if (!pattern->isBindingNode())
302 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
303 capturesAnyArgumentByName |= captures(ident.impl());
307 if (capturesAnyArgumentByName)
308 ASSERT(m_lexicalEnvironmentRegister);
310 // Need to know what our functions are called. Parameters have some goofy behaviors when it
311 // comes to functions of the same name.
312 for (FunctionBodyNode* function : functionNode->functionStack())
313 m_functions.add(function->ident().impl());
315 if (needsArguments) {
316 // Create the arguments object now. We may put the arguments object into the activation if
317 // it is captured. Either way, we create two arguments object variables: one is our
318 // private variable that is immutable, and another that is the user-visible variable. The
319 // immutable one is only used here, or during formal parameter resolutions if we opt for
322 m_argumentsRegister = addVar();
323 m_argumentsRegister->ref();
326 if (needsArguments && !codeBlock->isStrictMode()) {
327 // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we
328 // use DirectArguments. With ScopedArguments, we lift all of our arguments into the
331 if (capturesAnyArgumentByName) {
332 m_symbolTable->setArgumentsLength(vm, parameters.size());
334 // For each parameter, we have two possibilities:
335 // Either it's a binding node with no function overlap, in which case it gets a name
336 // in the symbol table - or it just gets space reserved in the symbol table. Either
337 // way we lift the value into the scope.
338 for (unsigned i = 0; i < parameters.size(); ++i) {
339 ScopeOffset offset = m_symbolTable->takeNextScopeOffset();
340 m_symbolTable->setArgumentOffset(vm, i, offset);
341 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i))) {
342 VarOffset varOffset(offset);
343 SymbolTableEntry entry(varOffset);
344 // Stores to these variables via the ScopedArguments object will not do
345 // notifyWrite(), since that would be cumbersome. Also, watching formal
346 // parameters when "arguments" is in play is unlikely to be super profitable.
347 // So, we just disable it.
348 entry.disableWatching();
349 m_symbolTable->set(name, entry);
351 emitOpcode(op_put_to_scope);
352 instructions().append(m_lexicalEnvironmentRegister->index());
353 instructions().append(UINT_MAX);
354 instructions().append(virtualRegisterForArgument(1 + i).offset());
355 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand());
356 instructions().append(symbolTableConstantIndex);
357 instructions().append(offset.offset());
360 // This creates a scoped arguments object and copies the overflow arguments into the
361 // scope. It's the equivalent of calling ScopedArguments::createByCopying().
362 emitOpcode(op_create_scoped_arguments);
363 instructions().append(m_argumentsRegister->index());
364 instructions().append(m_lexicalEnvironmentRegister->index());
366 // We're going to put all parameters into the DirectArguments object. First ensure
367 // that the symbol table knows that this is happening.
368 for (unsigned i = 0; i < parameters.size(); ++i) {
369 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i)))
370 m_symbolTable->set(name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i))));
373 emitOpcode(op_create_direct_arguments);
374 instructions().append(m_argumentsRegister->index());
377 // Create the formal parameters the normal way. Any of them could be captured, or not. If
378 // captured, lift them into the scope.
379 for (unsigned i = 0; i < parameters.size(); ++i) {
380 UniquedStringImpl* name = visibleNameForParameter(parameters.at(i));
384 if (!captures(name)) {
385 // This is the easy case - just tell the symbol table about the argument. It will
386 // be accessed directly.
387 m_symbolTable->set(name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i))));
391 ScopeOffset offset = m_symbolTable->takeNextScopeOffset();
392 const Identifier& ident =
393 static_cast<const BindingNode*>(parameters.at(i))->boundProperty();
394 m_symbolTable->set(name, SymbolTableEntry(VarOffset(offset)));
396 emitOpcode(op_put_to_scope);
397 instructions().append(m_lexicalEnvironmentRegister->index());
398 instructions().append(addConstant(ident));
399 instructions().append(virtualRegisterForArgument(1 + i).offset());
400 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand());
401 instructions().append(symbolTableConstantIndex);
402 instructions().append(offset.offset());
406 if (needsArguments && codeBlock->isStrictMode()) {
407 // Allocate an out-of-bands arguments object.
408 emitOpcode(op_create_out_of_band_arguments);
409 instructions().append(m_argumentsRegister->index());
412 // Now declare all variables.
413 for (const Identifier& ident : boundParameterProperties)
414 createVariable(ident, varKind(ident.impl()), IsVariable);
415 for (FunctionBodyNode* function : functionNode->functionStack()) {
416 const Identifier& ident = function->ident();
417 createVariable(ident, varKind(ident.impl()), IsVariable);
418 m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
420 for (auto& entry : functionNode->varDeclarations()) {
421 if (!entry.value.isVar())
423 ConstantMode constantMode = modeForIsConstant(entry.value.isConstant());
424 // Variables named "arguments" are never const.
425 if (Identifier::fromUid(m_vm, entry.key.get()) == propertyNames().arguments)
426 constantMode = IsVariable;
427 createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), constantMode, IgnoreExisting);
430 // There are some variables that need to be preinitialized to something other than Undefined:
432 // - "arguments": unless it's used as a function or parameter, this should refer to the
435 // - callee: unless it's used as a var, function, or parameter, this should refer to the
436 // callee (i.e. our function).
438 // - functions: these always override everything else.
440 // The most logical way to do all of this is to initialize none of the variables until now,
441 // and then initialize them in BytecodeGenerator::generate() in such an order that the rules
442 // for how these things override each other end up holding. We would initialize the callee
443 // first, then "arguments", then all arguments, then the functions.
445 // But some arguments are already initialized by default, since if they aren't captured and we
446 // don't have "arguments" then we just point the symbol table at the stack slot of those
447 // arguments. We end up initializing the rest of the arguments that have an uncomplicated
448 // binding (i.e. don't involve destructuring) above when figuring out how to lay them out,
449 // because that's just the simplest thing. This means that when we initialize them, we have to
450 // watch out for the things that override arguments (namely, functions).
452 // We also initialize callee here as well, just because it's so weird. We know whether we want
453 // to do this because we can just check if it's in the symbol table.
454 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())
455 && !functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode())
456 && m_symbolTable->get(functionNode->ident().impl()).isNull()) {
457 if (captures(functionNode->ident().impl())) {
460 ConcurrentJITLocker locker(m_symbolTable->m_lock);
461 offset = m_symbolTable->takeNextScopeOffset(locker);
463 locker, functionNode->ident().impl(),
464 SymbolTableEntry(VarOffset(offset), ReadOnly));
467 emitOpcode(op_put_to_scope);
468 instructions().append(m_lexicalEnvironmentRegister->index());
469 instructions().append(addConstant(functionNode->ident()));
470 instructions().append(m_calleeRegister.index());
471 instructions().append(ResolveModeAndType(ThrowIfNotFound, LocalClosureVar).operand());
472 instructions().append(symbolTableConstantIndex);
473 instructions().append(offset.offset());
476 functionNode->ident().impl(),
477 SymbolTableEntry(VarOffset(m_calleeRegister.virtualRegister()), ReadOnly));
481 // This is our final act of weirdness. "arguments" is overridden by everything except the
482 // callee. We add it to the symbol table if it's not already there and it's not an argument.
483 if (needsArguments) {
484 // If "arguments" is overridden by a function or destructuring parameter name, then it's
485 // OK for us to call createVariable() because it won't change anything. It's also OK for
486 // us to them tell BytecodeGenerator::generate() to write to it because it will do so
487 // before it initializes functions and destructuring parameters. But if "arguments" is
488 // overridden by a "simple" function parameter, then we have to bail: createVariable()
489 // would assert and BytecodeGenerator::generate() would write the "arguments" after the
490 // argument value had already been properly initialized.
492 bool haveParameterNamedArguments = false;
493 for (unsigned i = 0; i < parameters.size(); ++i) {
494 UniquedStringImpl* name = visibleNameForParameter(parameters.at(i));
495 if (name == propertyNames().arguments.impl()) {
496 haveParameterNamedArguments = true;
501 if (!haveParameterNamedArguments) {
503 propertyNames().arguments, varKind(propertyNames().arguments.impl()), IsVariable);
504 m_needToInitializeArguments = true;
508 if (isConstructor()) {
509 if (constructorKind() == ConstructorKind::Derived) {
510 m_newTargetRegister = addVar();
511 emitMove(m_newTargetRegister, &m_thisRegister);
512 emitMoveEmptyValue(&m_thisRegister);
514 emitCreateThis(&m_thisRegister);
515 } else if (constructorKind() != ConstructorKind::None) {
516 emitThrowTypeError("Cannot call a class constructor");
517 } else if (functionNode->usesThis() || codeBlock->usesEval()) {
518 m_codeBlock->addPropertyAccessInstruction(instructions().size());
519 emitOpcode(op_to_this);
520 instructions().append(kill(&m_thisRegister));
521 instructions().append(0);
522 instructions().append(0);
525 m_symbolTableStack.append(SymbolTableStackEntry{ Strong<SymbolTable>(*m_vm, m_symbolTable), m_lexicalEnvironmentRegister, false, symbolTableConstantIndex });
526 m_TDZStack.append(std::make_pair(*parentScopeTDZVariables, false));
529 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
530 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode == DebuggerOn)
531 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode == ProfilerOn)
532 , m_symbolTable(codeBlock->symbolTable())
533 , m_scopeNode(evalNode)
534 , m_codeBlock(vm, codeBlock)
535 , m_thisRegister(CallFrame::thisArgumentOffset())
536 , m_codeType(EvalCode)
539 for (auto& constantRegister : m_linkTimeConstantRegisters)
540 constantRegister = nullptr;
542 m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
543 m_codeBlock->setNumParameters(1);
544 int symbolTableConstantIndex = addConstantValue(m_symbolTable)->index();
545 m_codeBlock->setSymbolTableConstantIndex(symbolTableConstantIndex);
547 emitOpcode(op_enter);
549 allocateAndEmitScope();
551 const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
552 for (size_t i = 0; i < functionStack.size(); ++i)
553 m_codeBlock->addFunctionDecl(makeFunction(functionStack[i]));
555 const VariableEnvironment& varDeclarations = evalNode->varDeclarations();
556 unsigned numVariables = varDeclarations.size();
557 Vector<Identifier, 0, UnsafeVectorOverflow> variables;
558 variables.reserveCapacity(numVariables);
559 for (auto& entry : varDeclarations) {
560 ASSERT(entry.value.isVar() || entry.value.isConstant()); // FIXME: When supporting ES6 spec compliant const, this should only check isVar().
561 ASSERT(entry.key->isAtomic() || entry.key->isSymbol());
562 variables.append(Identifier::fromUid(m_vm, entry.key.get()));
564 codeBlock->adoptVariables(variables);
566 m_TDZStack.append(std::make_pair(*parentScopeTDZVariables, false));
569 BytecodeGenerator::~BytecodeGenerator()
573 RegisterID* BytecodeGenerator::initializeNextParameter()
575 VirtualRegister reg = virtualRegisterForArgument(m_codeBlock->numParameters());
576 RegisterID& parameter = registerFor(reg);
577 parameter.setIndex(reg.offset());
578 m_codeBlock->addParameter();
582 UniquedStringImpl* BytecodeGenerator::visibleNameForParameter(DestructuringPatternNode* pattern)
584 if (pattern->isBindingNode()) {
585 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
586 if (!m_functions.contains(ident.impl()))
592 RegisterID* BytecodeGenerator::newRegister()
594 m_calleeRegisters.append(virtualRegisterForLocal(m_calleeRegisters.size()));
595 int numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size());
596 numCalleeRegisters = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numCalleeRegisters);
597 m_codeBlock->m_numCalleeRegisters = numCalleeRegisters;
598 return &m_calleeRegisters.last();
601 void BytecodeGenerator::reclaimFreeRegisters()
603 while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
604 m_calleeRegisters.removeLast();
607 RegisterID* BytecodeGenerator::newBlockScopeVariable()
609 reclaimFreeRegisters();
611 return newRegister();
614 RegisterID* BytecodeGenerator::newTemporary()
616 reclaimFreeRegisters();
618 RegisterID* result = newRegister();
619 result->setTemporary();
623 LabelScopePtr BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
625 // Reclaim free label scopes.
626 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
627 m_labelScopes.removeLast();
629 // Allocate new label scope.
630 LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
631 m_labelScopes.append(scope);
632 return LabelScopePtr(m_labelScopes, m_labelScopes.size() - 1);
635 PassRefPtr<Label> BytecodeGenerator::newLabel()
637 // Reclaim free label IDs.
638 while (m_labels.size() && !m_labels.last().refCount())
639 m_labels.removeLast();
641 // Allocate new label ID.
642 m_labels.append(*this);
643 return &m_labels.last();
646 PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
648 unsigned newLabelIndex = instructions().size();
649 l0->setLocation(newLabelIndex);
651 if (m_codeBlock->numberOfJumpTargets()) {
652 unsigned lastLabelIndex = m_codeBlock->lastJumpTarget();
653 ASSERT(lastLabelIndex <= newLabelIndex);
654 if (newLabelIndex == lastLabelIndex) {
655 // Peephole optimizations have already been disabled by emitting the last label
660 m_codeBlock->addJumpTarget(newLabelIndex);
662 // This disables peephole optimizations when an instruction is a jump target
663 m_lastOpcodeID = op_end;
667 void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
670 size_t opcodePosition = instructions().size();
671 ASSERT(opcodePosition - m_lastOpcodePosition == opcodeLength(m_lastOpcodeID) || m_lastOpcodeID == op_end);
672 m_lastOpcodePosition = opcodePosition;
674 instructions().append(opcodeID);
675 m_lastOpcodeID = opcodeID;
678 UnlinkedArrayProfile BytecodeGenerator::newArrayProfile()
680 return m_codeBlock->addArrayProfile();
683 UnlinkedArrayAllocationProfile BytecodeGenerator::newArrayAllocationProfile()
685 return m_codeBlock->addArrayAllocationProfile();
688 UnlinkedObjectAllocationProfile BytecodeGenerator::newObjectAllocationProfile()
690 return m_codeBlock->addObjectAllocationProfile();
693 UnlinkedValueProfile BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
695 UnlinkedValueProfile result = m_codeBlock->addValueProfile();
696 emitOpcode(opcodeID);
700 void BytecodeGenerator::emitLoopHint()
702 emitOpcode(op_loop_hint);
705 void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
707 ASSERT(instructions().size() >= 4);
708 size_t size = instructions().size();
709 dstIndex = instructions().at(size - 3).u.operand;
710 src1Index = instructions().at(size - 2).u.operand;
711 src2Index = instructions().at(size - 1).u.operand;
714 void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
716 ASSERT(instructions().size() >= 3);
717 size_t size = instructions().size();
718 dstIndex = instructions().at(size - 2).u.operand;
719 srcIndex = instructions().at(size - 1).u.operand;
722 void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
724 ASSERT(instructions().size() >= 4);
725 instructions().shrink(instructions().size() - 4);
726 m_lastOpcodeID = op_end;
729 void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
731 ASSERT(instructions().size() >= 3);
732 instructions().shrink(instructions().size() - 3);
733 m_lastOpcodeID = op_end;
736 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
738 size_t begin = instructions().size();
740 instructions().append(target->bind(begin, instructions().size()));
744 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
746 if (m_lastOpcodeID == op_less) {
751 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
753 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
756 size_t begin = instructions().size();
757 emitOpcode(op_jless);
758 instructions().append(src1Index);
759 instructions().append(src2Index);
760 instructions().append(target->bind(begin, instructions().size()));
763 } else if (m_lastOpcodeID == op_lesseq) {
768 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
770 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
773 size_t begin = instructions().size();
774 emitOpcode(op_jlesseq);
775 instructions().append(src1Index);
776 instructions().append(src2Index);
777 instructions().append(target->bind(begin, instructions().size()));
780 } else if (m_lastOpcodeID == op_greater) {
785 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
787 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
790 size_t begin = instructions().size();
791 emitOpcode(op_jgreater);
792 instructions().append(src1Index);
793 instructions().append(src2Index);
794 instructions().append(target->bind(begin, instructions().size()));
797 } else if (m_lastOpcodeID == op_greatereq) {
802 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
804 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
807 size_t begin = instructions().size();
808 emitOpcode(op_jgreatereq);
809 instructions().append(src1Index);
810 instructions().append(src2Index);
811 instructions().append(target->bind(begin, instructions().size()));
814 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
818 retrieveLastUnaryOp(dstIndex, srcIndex);
820 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
823 size_t begin = instructions().size();
824 emitOpcode(op_jeq_null);
825 instructions().append(srcIndex);
826 instructions().append(target->bind(begin, instructions().size()));
829 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
833 retrieveLastUnaryOp(dstIndex, srcIndex);
835 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
838 size_t begin = instructions().size();
839 emitOpcode(op_jneq_null);
840 instructions().append(srcIndex);
841 instructions().append(target->bind(begin, instructions().size()));
846 size_t begin = instructions().size();
848 emitOpcode(op_jtrue);
849 instructions().append(cond->index());
850 instructions().append(target->bind(begin, instructions().size()));
854 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
856 if (m_lastOpcodeID == op_less && target->isForward()) {
861 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
863 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
866 size_t begin = instructions().size();
867 emitOpcode(op_jnless);
868 instructions().append(src1Index);
869 instructions().append(src2Index);
870 instructions().append(target->bind(begin, instructions().size()));
873 } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
878 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
880 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
883 size_t begin = instructions().size();
884 emitOpcode(op_jnlesseq);
885 instructions().append(src1Index);
886 instructions().append(src2Index);
887 instructions().append(target->bind(begin, instructions().size()));
890 } else if (m_lastOpcodeID == op_greater && target->isForward()) {
895 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
897 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
900 size_t begin = instructions().size();
901 emitOpcode(op_jngreater);
902 instructions().append(src1Index);
903 instructions().append(src2Index);
904 instructions().append(target->bind(begin, instructions().size()));
907 } else if (m_lastOpcodeID == op_greatereq && target->isForward()) {
912 retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
914 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
917 size_t begin = instructions().size();
918 emitOpcode(op_jngreatereq);
919 instructions().append(src1Index);
920 instructions().append(src2Index);
921 instructions().append(target->bind(begin, instructions().size()));
924 } else if (m_lastOpcodeID == op_not) {
928 retrieveLastUnaryOp(dstIndex, srcIndex);
930 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
933 size_t begin = instructions().size();
934 emitOpcode(op_jtrue);
935 instructions().append(srcIndex);
936 instructions().append(target->bind(begin, instructions().size()));
939 } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
943 retrieveLastUnaryOp(dstIndex, srcIndex);
945 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
948 size_t begin = instructions().size();
949 emitOpcode(op_jneq_null);
950 instructions().append(srcIndex);
951 instructions().append(target->bind(begin, instructions().size()));
954 } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
958 retrieveLastUnaryOp(dstIndex, srcIndex);
960 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
963 size_t begin = instructions().size();
964 emitOpcode(op_jeq_null);
965 instructions().append(srcIndex);
966 instructions().append(target->bind(begin, instructions().size()));
971 size_t begin = instructions().size();
972 emitOpcode(op_jfalse);
973 instructions().append(cond->index());
974 instructions().append(target->bind(begin, instructions().size()));
978 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
980 size_t begin = instructions().size();
982 emitOpcode(op_jneq_ptr);
983 instructions().append(cond->index());
984 instructions().append(Special::CallFunction);
985 instructions().append(target->bind(begin, instructions().size()));
989 PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
991 size_t begin = instructions().size();
993 emitOpcode(op_jneq_ptr);
994 instructions().append(cond->index());
995 instructions().append(Special::ApplyFunction);
996 instructions().append(target->bind(begin, instructions().size()));
1000 bool BytecodeGenerator::hasConstant(const Identifier& ident) const
1002 UniquedStringImpl* rep = ident.impl();
1003 return m_identifierMap.contains(rep);
1006 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
1008 UniquedStringImpl* rep = ident.impl();
1009 IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
1010 if (result.isNewEntry)
1011 m_codeBlock->addIdentifier(ident);
1013 return result.iterator->value;
1016 // We can't hash JSValue(), so we use a dedicated data member to cache it.
1017 RegisterID* BytecodeGenerator::addConstantEmptyValue()
1019 if (!m_emptyValueRegister) {
1020 int index = m_nextConstantOffset;
1021 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1022 ++m_nextConstantOffset;
1023 m_codeBlock->addConstant(JSValue());
1024 m_emptyValueRegister = &m_constantPoolRegisters[index];
1027 return m_emptyValueRegister;
1030 RegisterID* BytecodeGenerator::addConstantValue(JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
1033 return addConstantEmptyValue();
1035 int index = m_nextConstantOffset;
1037 EncodedJSValueWithRepresentation valueMapKey { JSValue::encode(v), sourceCodeRepresentation };
1038 JSValueMap::AddResult result = m_jsValueMap.add(valueMapKey, m_nextConstantOffset);
1039 if (result.isNewEntry) {
1040 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1041 ++m_nextConstantOffset;
1042 m_codeBlock->addConstant(v, sourceCodeRepresentation);
1044 index = result.iterator->value;
1045 return &m_constantPoolRegisters[index];
1048 RegisterID* BytecodeGenerator::emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant type)
1050 unsigned constantIndex = static_cast<unsigned>(type);
1051 if (!m_linkTimeConstantRegisters[constantIndex]) {
1052 int index = m_nextConstantOffset;
1053 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1054 ++m_nextConstantOffset;
1055 m_codeBlock->addConstant(type);
1056 m_linkTimeConstantRegisters[constantIndex] = &m_constantPoolRegisters[index];
1060 instructions().append(dst->index());
1061 instructions().append(m_linkTimeConstantRegisters[constantIndex]->index());
1066 unsigned BytecodeGenerator::addRegExp(RegExp* r)
1068 return m_codeBlock->addRegExp(r);
1071 RegisterID* BytecodeGenerator::emitMoveEmptyValue(RegisterID* dst)
1073 RefPtr<RegisterID> emptyValue = addConstantEmptyValue();
1076 instructions().append(dst->index());
1077 instructions().append(emptyValue->index());
1081 RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
1083 ASSERT(src != m_emptyValueRegister);
1085 m_staticPropertyAnalyzer.mov(dst->index(), src->index());
1087 instructions().append(dst->index());
1088 instructions().append(src->index());
1090 if (!dst->isTemporary() && vm()->typeProfiler())
1091 emitProfileType(dst, ProfileTypeBytecodeHasGlobalID, nullptr);
1096 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src)
1098 emitOpcode(opcodeID);
1099 instructions().append(dst->index());
1100 instructions().append(src->index());
1104 RegisterID* BytecodeGenerator::emitInc(RegisterID* srcDst)
1107 instructions().append(srcDst->index());
1111 RegisterID* BytecodeGenerator::emitDec(RegisterID* srcDst)
1114 instructions().append(srcDst->index());
1118 RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
1120 emitOpcode(opcodeID);
1121 instructions().append(dst->index());
1122 instructions().append(src1->index());
1123 instructions().append(src2->index());
1125 if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
1126 opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
1127 instructions().append(types.toInt());
1132 RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2)
1134 if (m_lastOpcodeID == op_typeof) {
1138 retrieveLastUnaryOp(dstIndex, srcIndex);
1140 if (src1->index() == dstIndex
1141 && src1->isTemporary()
1142 && m_codeBlock->isConstantRegisterIndex(src2->index())
1143 && m_codeBlock->constantRegister(src2->index()).get().isString()) {
1144 const String& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
1145 if (value == "undefined") {
1147 emitOpcode(op_is_undefined);
1148 instructions().append(dst->index());
1149 instructions().append(srcIndex);
1152 if (value == "boolean") {
1154 emitOpcode(op_is_boolean);
1155 instructions().append(dst->index());
1156 instructions().append(srcIndex);
1159 if (value == "number") {
1161 emitOpcode(op_is_number);
1162 instructions().append(dst->index());
1163 instructions().append(srcIndex);
1166 if (value == "string") {
1168 emitOpcode(op_is_string);
1169 instructions().append(dst->index());
1170 instructions().append(srcIndex);
1173 if (value == "object") {
1175 emitOpcode(op_is_object_or_null);
1176 instructions().append(dst->index());
1177 instructions().append(srcIndex);
1180 if (value == "function") {
1182 emitOpcode(op_is_function);
1183 instructions().append(dst->index());
1184 instructions().append(srcIndex);
1190 emitOpcode(opcodeID);
1191 instructions().append(dst->index());
1192 instructions().append(src1->index());
1193 instructions().append(src2->index());
1197 void BytecodeGenerator::emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
1199 unsigned start = startDivot.offset; // Ranges are inclusive of their endpoints, AND 0 indexed.
1200 unsigned end = endDivot.offset - 1; // End Ranges already go one past the inclusive range, so subtract 1.
1201 unsigned instructionOffset = instructions().size() - 1;
1202 m_codeBlock->addTypeProfilerExpressionInfo(instructionOffset, start, end);
1205 void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const Identifier* identifier)
1207 if (flag == ProfileTypeBytecodeGetFromScope || flag == ProfileTypeBytecodePutToScope)
1208 RELEASE_ASSERT(identifier);
1210 // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
1211 emitOpcode(op_profile_type);
1212 instructions().append(registerToProfile->index());
1213 instructions().append(currentScopeDepth());
1214 instructions().append(flag);
1215 instructions().append(identifier ? addConstant(*identifier) : 0);
1216 instructions().append(resolveType());
1219 void BytecodeGenerator::emitProfileControlFlow(int textOffset)
1221 if (vm()->controlFlowProfiler()) {
1222 RELEASE_ASSERT(textOffset >= 0);
1223 size_t bytecodeOffset = instructions().size();
1224 m_codeBlock->addOpProfileControlFlowBytecodeOffset(bytecodeOffset);
1226 emitOpcode(op_profile_control_flow);
1227 instructions().append(textOffset);
1231 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
1233 return emitLoad(dst, jsBoolean(b));
1236 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
1238 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
1240 stringInMap = jsOwnedString(vm(), identifier.string());
1241 return emitLoad(dst, JSValue(stringInMap));
1244 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
1246 RegisterID* constantID = addConstantValue(v, sourceCodeRepresentation);
1248 return emitMove(dst, constantID);
1252 RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst)
1254 if (!m_globalObjectRegister) {
1255 int index = m_nextConstantOffset;
1256 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1257 ++m_nextConstantOffset;
1258 m_codeBlock->addConstant(JSValue());
1259 m_globalObjectRegister = &m_constantPoolRegisters[index];
1260 m_codeBlock->setGlobalObjectRegister(VirtualRegister(index));
1263 emitMove(dst, m_globalObjectRegister);
1264 return m_globalObjectRegister;
1267 void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
1269 VariableEnvironment& environment = node->lexicalVariables();
1270 if (!environment.size())
1273 if (m_shouldEmitDebugHooks)
1274 environment.markAllVariablesAsCaptured();
1276 Strong<SymbolTable> symbolTable(*m_vm, SymbolTable::create(*m_vm));
1277 symbolTable->setDoesCorrespondToLexicalScope();
1278 bool hasCapturedVariables = false;
1280 ConcurrentJITLocker locker(symbolTable->m_lock);
1281 for (auto entry : environment) {
1282 ASSERT(entry.value.isLet() && !entry.value.isVar());
1283 SymbolTableEntry symbolTableEntry = symbolTable->get(locker, entry.key.get());
1284 ASSERT(symbolTableEntry.isNull());
1286 VarKind varKind = entry.value.isCaptured() ? VarKind::Scope : VarKind::Stack;
1287 VarOffset varOffset;
1288 if (varKind == VarKind::Scope) {
1289 varOffset = VarOffset(symbolTable->takeNextScopeOffset(locker));
1290 hasCapturedVariables = true;
1292 ASSERT(varKind == VarKind::Stack);
1293 RegisterID* local = newBlockScopeVariable();
1295 varOffset = VarOffset(local->virtualRegister());
1297 // FIXME: Make this work with 'const' variables: https://bugs.webkit.org/show_bug.cgi?id=31813
1298 SymbolTableEntry newEntry(varOffset, 0);
1299 symbolTable->add(locker, entry.key.get(), newEntry);
1303 RegisterID* newScope = nullptr;
1304 int symbolTableConstantIndex = 0;
1305 if (hasCapturedVariables) {
1306 newScope = newBlockScopeVariable();
1309 RegisterID* constantSymbolTable = addConstantValue(symbolTable->cloneScopePart(*m_vm));
1310 symbolTableConstantIndex = constantSymbolTable->index();
1311 if (constantSymbolTableResult)
1312 *constantSymbolTableResult = constantSymbolTable;
1314 emitOpcode(op_create_lexical_environment);
1315 instructions().append(newScope->index());
1316 instructions().append(scopeRegister()->index());
1317 instructions().append(constantSymbolTable->index());
1318 instructions().append(addConstantValue(jsTDZValue())->index());
1320 emitMove(scopeRegister(), newScope);
1323 m_symbolTableStack.append(SymbolTableStackEntry{ symbolTable, newScope, false, symbolTableConstantIndex });
1324 m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks));
1325 // Prefill stack variables with the TDZ empty value.
1326 // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated.
1327 for (auto entry : environment) {
1328 SymbolTableEntry symbolTableEntry = symbolTable->get(entry.key.get());
1329 ASSERT(!symbolTableEntry.isNull());
1330 VarOffset offset = symbolTableEntry.varOffset();
1331 if (offset.isScope()) {
1335 ASSERT(offset.isStack());
1336 emitMoveEmptyValue(®isterFor(offset.stackOffset()));
1340 void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node)
1342 VariableEnvironment& environment = node->lexicalVariables();
1343 if (!environment.size())
1346 if (m_shouldEmitDebugHooks)
1347 environment.markAllVariablesAsCaptured();
1349 SymbolTableStackEntry stackEntry = m_symbolTableStack.takeLast();
1350 Strong<SymbolTable> symbolTable = stackEntry.m_symbolTable;
1351 ConcurrentJITLocker locker(symbolTable->m_lock);
1352 bool hasCapturedVariables = false;
1353 for (auto entry : environment) {
1354 if (entry.value.isCaptured()) {
1355 hasCapturedVariables = true;
1358 SymbolTableEntry symbolTableEntry = symbolTable->get(locker, entry.key.get());
1359 ASSERT(!symbolTableEntry.isNull());
1360 VarOffset offset = symbolTableEntry.varOffset();
1361 ASSERT(offset.isStack());
1362 RegisterID* local = ®isterFor(offset.stackOffset());
1366 if (hasCapturedVariables) {
1367 RELEASE_ASSERT(stackEntry.m_scope);
1368 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), scopeRegister());
1369 emitMove(scopeRegister(), parentScope.get());
1370 stackEntry.m_scope->deref();
1373 m_TDZStack.removeLast();
1376 void BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode* node, RegisterID* loopSymbolTable)
1378 VariableEnvironment& environment = node->lexicalVariables();
1379 if (!environment.size())
1381 if (m_shouldEmitDebugHooks)
1382 environment.markAllVariablesAsCaptured();
1383 if (!environment.hasCapturedVariables())
1386 RELEASE_ASSERT(loopSymbolTable);
1388 // This function needs to do setup for a for loop's activation if any of
1389 // the for loop's lexically declared variables are captured (that is, variables
1390 // declared in the loop header, not the loop body). This function needs to
1391 // make a copy of the current activation and copy the values from the previous
1392 // activation into the new activation because each iteration of a for loop
1393 // gets a new activation.
1395 SymbolTableStackEntry stackEntry = m_symbolTableStack.last();
1396 Strong<SymbolTable> symbolTable = stackEntry.m_symbolTable;
1397 RegisterID* loopScope = stackEntry.m_scope;
1398 ASSERT(symbolTable->scopeSize());
1400 Vector<std::pair<RegisterID*, Identifier>> activationValuesToCopyOver;
1403 ConcurrentJITLocker locker(symbolTable->m_lock);
1404 activationValuesToCopyOver.reserveInitialCapacity(symbolTable->scopeSize());
1406 for (auto end = symbolTable->end(locker), ptr = symbolTable->begin(locker); ptr != end; ++ptr) {
1407 if (!ptr->value.varOffset().isScope())
1410 RefPtr<UniquedStringImpl> ident = ptr->key;
1411 Identifier identifier = Identifier::fromUid(m_vm, ident.get());
1413 RegisterID* transitionValue = newBlockScopeVariable();
1414 transitionValue->ref();
1415 emitGetFromScope(transitionValue, loopScope, variableForLocalEntry(identifier, ptr->value, loopSymbolTable->index()), DoNotThrowIfNotFound);
1416 activationValuesToCopyOver.uncheckedAppend(std::make_pair(transitionValue, identifier));
1420 // We need this dynamic behavior of the executing code to ensure
1421 // each loop iteration has a new activation object. (It's pretty ugly).
1422 // Also, this new activation needs to be assigned to the same register
1423 // as the previous scope because the loop body is compiled under
1424 // the assumption that the scope's register index is constant even
1425 // though the value in that register will change on each loop iteration.
1426 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), scopeRegister());
1427 emitMove(scopeRegister(), parentScope.get());
1429 emitOpcode(op_create_lexical_environment);
1430 instructions().append(loopScope->index());
1431 instructions().append(scopeRegister()->index());
1432 instructions().append(loopSymbolTable->index());
1433 instructions().append(addConstantValue(jsTDZValue())->index());
1435 emitMove(scopeRegister(), loopScope);
1438 ConcurrentJITLocker locker(symbolTable->m_lock);
1439 for (auto pair : activationValuesToCopyOver) {
1440 const Identifier& identifier = pair.second;
1441 SymbolTableEntry entry = symbolTable->get(locker, identifier.impl());
1442 RELEASE_ASSERT(!entry.isNull());
1443 RegisterID* transitionValue = pair.first;
1444 emitPutToScope(loopScope, variableForLocalEntry(identifier, entry, loopSymbolTable->index()), transitionValue, DoNotThrowIfNotFound);
1445 transitionValue->deref();
1450 Variable BytecodeGenerator::variable(const Identifier& property)
1452 if (property == propertyNames().thisIdentifier) {
1454 property, VarOffset(thisRegister()->virtualRegister()), thisRegister(),
1455 ReadOnly, Variable::SpecialVariable, 0);
1458 // We can optimize lookups if the lexical variable is found before a "with" or "catch"
1459 // scope because we're guaranteed static resolution. If we have to pass through
1460 // a "with" or "catch" scope we loose this guarantee.
1461 // We can't optimize cases like this:
1465 // doSomethingWith(x);
1468 // Because we can't gaurantee static resolution on x.
1469 // But, in this case, we are guaranteed static resolution:
1474 // doSomethingWith(x);
1477 for (unsigned i = m_symbolTableStack.size(); i--; ) {
1478 SymbolTableStackEntry& stackEntry = m_symbolTableStack[i];
1479 if (stackEntry.m_isWithOrCatch)
1480 return Variable(property);
1481 Strong<SymbolTable>& symbolTable = stackEntry.m_symbolTable;
1482 SymbolTableEntry symbolTableEntry = symbolTable->get(property.impl());
1483 if (symbolTableEntry.isNull())
1486 return variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex);
1489 return Variable(property);
1492 Variable BytecodeGenerator::variablePerSymbolTable(const Identifier& property)
1494 RELEASE_ASSERT(m_symbolTableStack.size());
1495 SymbolTableStackEntry& baseActivationEntry = m_symbolTableStack.first();
1496 SymbolTableEntry entry = baseActivationEntry.m_symbolTable->get(property.impl());
1498 return Variable(property);
1500 return variableForLocalEntry(property, entry, baseActivationEntry.m_symbolTableConstantIndex);
1503 Variable BytecodeGenerator::variableForLocalEntry(
1504 const Identifier& property, const SymbolTableEntry& entry, int symbolTableConstantIndex)
1506 VarOffset offset = entry.varOffset();
1509 if (offset.isStack())
1510 local = ®isterFor(offset.stackOffset());
1514 return Variable(property, offset, local, entry.getAttributes(), Variable::NormalVariable, symbolTableConstantIndex);
1517 void BytecodeGenerator::createVariable(
1518 const Identifier& property, VarKind varKind, ConstantMode constantMode,
1519 ExistingVariableMode existingVariableMode)
1521 ASSERT(property != propertyNames().thisIdentifier);
1522 ConcurrentJITLocker locker(symbolTable().m_lock);
1523 SymbolTableEntry entry = symbolTable().get(locker, property.impl());
1525 if (!entry.isNull()) {
1526 if (existingVariableMode == IgnoreExisting)
1529 // Do some checks to ensure that the variable we're being asked to create is sufficiently
1530 // compatible with the one we have already created.
1532 VarOffset offset = entry.varOffset();
1534 // We can't change our minds about whether it's captured.
1535 if (offset.kind() != varKind || constantMode != entry.constantMode()) {
1537 "Trying to add variable called ", property, " as ", varKind, "/", constantMode,
1538 " but it was already added as ", offset, "/", entry.constantMode(), ".\n");
1539 RELEASE_ASSERT_NOT_REACHED();
1545 VarOffset varOffset;
1546 if (varKind == VarKind::Scope)
1547 varOffset = VarOffset(symbolTable().takeNextScopeOffset(locker));
1549 ASSERT(varKind == VarKind::Stack);
1550 varOffset = VarOffset(virtualRegisterForLocal(m_calleeRegisters.size()));
1552 SymbolTableEntry newEntry(varOffset, constantMode == IsConstant ? ReadOnly : 0);
1553 symbolTable().add(locker, property.impl(), newEntry);
1555 if (varKind == VarKind::Stack) {
1556 RegisterID* local = addVar();
1557 RELEASE_ASSERT(local->index() == varOffset.stackOffset().offset());
1561 void BytecodeGenerator::emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target)
1563 size_t begin = instructions().size();
1564 emitOpcode(op_check_has_instance);
1565 instructions().append(dst->index());
1566 instructions().append(value->index());
1567 instructions().append(base->index());
1568 instructions().append(target->bind(begin, instructions().size()));
1571 // Indicates the least upper bound of resolve type based on local scope. The bytecode linker
1572 // will start with this ResolveType and compute the least upper bound including intercepting scopes.
1573 ResolveType BytecodeGenerator::resolveType()
1575 if (m_localScopeDepth)
1577 if (m_symbolTable && m_symbolTable->usesNonStrictEval())
1578 return GlobalPropertyWithVarInjectionChecks;
1579 return GlobalProperty;
1582 RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Variable& variable)
1584 switch (variable.offset().kind()) {
1585 case VarKind::Stack:
1588 case VarKind::DirectArgument:
1589 return argumentsRegister();
1591 case VarKind::Scope:
1592 // This always refers to the activation that *we* allocated, and not the current scope that code
1593 // lives in. Note that this will change once we have proper support for block scoping. Once that
1594 // changes, it will be correct for this code to return scopeRegister(). The only reason why we
1595 // don't do that already is that m_lexicalEnvironment is required by ConstDeclNode. ConstDeclNode
1596 // requires weird things because it is a shameful pile of nonsense, but block scoping would make
1597 // that code sensible and obviate the need for us to do bad things.
1598 for (unsigned i = m_symbolTableStack.size(); i--; ) {
1599 SymbolTableStackEntry& stackEntry = m_symbolTableStack[i];
1600 // We should not resolve a variable to VarKind::Scope if a "with" or "catch" scope lies in between the current
1601 // scope and the resolved scope.
1602 // We'd like to say: RELEASE_ASSERT(!stackEntry.m_isWithOrCatch);
1603 // But, our current implementation 'const' is a pile of crap and uses variablePerSymbolTable
1604 // which recklessly ignores the scope stack.
1605 // FIXME: When implementing const the proper way ensure we add this assert in.
1606 // https://bugs.webkit.org/show_bug.cgi?id=143654
1607 if (stackEntry.m_isWithOrCatch)
1610 if (stackEntry.m_symbolTable->get(variable.ident().impl()).isNull())
1613 RegisterID* scope = stackEntry.m_scope;
1614 RELEASE_ASSERT(scope);
1618 RELEASE_ASSERT_NOT_REACHED();
1621 case VarKind::Invalid:
1622 // Indicates non-local resolution.
1624 ASSERT(!m_symbolTable || !m_symbolTable->contains(variable.ident().impl()) || resolveType() == Dynamic);
1626 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1628 // resolve_scope dst, id, ResolveType, depth
1629 dst = tempDestination(dst);
1630 emitOpcode(op_resolve_scope);
1631 instructions().append(kill(dst));
1632 instructions().append(scopeRegister()->index());
1633 instructions().append(addConstant(variable.ident()));
1634 instructions().append(resolveType());
1635 instructions().append(currentScopeDepth());
1636 instructions().append(0);
1640 RELEASE_ASSERT_NOT_REACHED();
1644 RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable& variable, ResolveMode resolveMode)
1646 switch (variable.offset().kind()) {
1647 case VarKind::Stack:
1648 return emitMove(dst, variable.local());
1650 case VarKind::DirectArgument: {
1651 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_arguments);
1652 instructions().append(kill(dst));
1653 instructions().append(scope->index());
1654 instructions().append(variable.offset().capturedArgumentsOffset().offset());
1655 instructions().append(profile);
1659 case VarKind::Scope:
1660 case VarKind::Invalid: {
1661 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1663 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
1664 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope);
1665 instructions().append(kill(dst));
1666 instructions().append(scope->index());
1667 instructions().append(addConstant(variable.ident()));
1668 instructions().append(ResolveModeAndType(resolveMode, variable.offset().isScope() ? LocalClosureVar : resolveType()).operand());
1669 instructions().append(currentScopeDepth());
1670 instructions().append(variable.offset().isScope() ? variable.offset().scopeOffset().offset() : 0);
1671 instructions().append(profile);
1675 RELEASE_ASSERT_NOT_REACHED();
1678 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Variable& variable, RegisterID* value, ResolveMode resolveMode)
1680 switch (variable.offset().kind()) {
1681 case VarKind::Stack:
1682 emitMove(variable.local(), value);
1685 case VarKind::DirectArgument:
1686 emitOpcode(op_put_to_arguments);
1687 instructions().append(scope->index());
1688 instructions().append(variable.offset().capturedArgumentsOffset().offset());
1689 instructions().append(value->index());
1692 case VarKind::Scope:
1693 case VarKind::Invalid: {
1694 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1696 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
1697 emitOpcode(op_put_to_scope);
1698 instructions().append(scope->index());
1699 instructions().append(addConstant(variable.ident()));
1700 instructions().append(value->index());
1702 if (variable.offset().isScope()) {
1703 offset = variable.offset().scopeOffset();
1704 instructions().append(ResolveModeAndType(resolveMode, LocalClosureVar).operand());
1705 instructions().append(variable.symbolTableConstantIndex());
1707 ASSERT(resolveType() != LocalClosureVar);
1708 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
1709 instructions().append(currentScopeDepth());
1711 instructions().append(!!offset ? offset.offset() : 0);
1715 RELEASE_ASSERT_NOT_REACHED();
1718 RegisterID* BytecodeGenerator::initializeVariable(const Variable& variable, RegisterID* value)
1720 RELEASE_ASSERT(variable.offset().kind() != VarKind::Invalid);
1721 RegisterID* scope = emitResolveScope(nullptr, variable);
1722 return emitPutToScope(scope, variable, value, ThrowIfNotFound);
1725 RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype)
1727 emitOpcode(op_instanceof);
1728 instructions().append(dst->index());
1729 instructions().append(value->index());
1730 instructions().append(basePrototype->index());
1734 RegisterID* BytecodeGenerator::emitInitGlobalConst(const Identifier& identifier, RegisterID* value)
1736 ASSERT(m_codeType == GlobalCode);
1737 emitOpcode(op_init_global_const_nop);
1738 instructions().append(0);
1739 instructions().append(value->index());
1740 instructions().append(0);
1741 instructions().append(addConstant(identifier));
1745 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
1747 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1749 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_id);
1750 instructions().append(kill(dst));
1751 instructions().append(base->index());
1752 instructions().append(addConstant(property));
1753 instructions().append(0);
1754 instructions().append(0);
1755 instructions().append(0);
1756 instructions().append(0);
1757 instructions().append(profile);
1761 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1763 unsigned propertyIndex = addConstant(property);
1765 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1767 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1769 emitOpcode(op_put_by_id);
1770 instructions().append(base->index());
1771 instructions().append(propertyIndex);
1772 instructions().append(value->index());
1773 instructions().append(0);
1774 instructions().append(0);
1775 instructions().append(0);
1776 instructions().append(0);
1777 instructions().append(0);
1782 RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType putType)
1784 ASSERT(!parseIndex(property));
1785 unsigned propertyIndex = addConstant(property);
1787 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1789 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1791 emitOpcode(op_put_by_id);
1792 instructions().append(base->index());
1793 instructions().append(propertyIndex);
1794 instructions().append(value->index());
1795 instructions().append(0);
1796 instructions().append(0);
1797 instructions().append(0);
1798 instructions().append(0);
1799 instructions().append(putType == PropertyNode::KnownDirect || property != m_vm->propertyNames->underscoreProto);
1803 void BytecodeGenerator::emitPutGetterById(RegisterID* base, const Identifier& property, RegisterID* getter)
1805 unsigned propertyIndex = addConstant(property);
1806 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1808 emitOpcode(op_put_getter_by_id);
1809 instructions().append(base->index());
1810 instructions().append(propertyIndex);
1811 instructions().append(getter->index());
1814 void BytecodeGenerator::emitPutSetterById(RegisterID* base, const Identifier& property, RegisterID* setter)
1816 unsigned propertyIndex = addConstant(property);
1817 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1819 emitOpcode(op_put_setter_by_id);
1820 instructions().append(base->index());
1821 instructions().append(propertyIndex);
1822 instructions().append(setter->index());
1825 void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter)
1827 unsigned propertyIndex = addConstant(property);
1829 m_staticPropertyAnalyzer.putById(base->index(), propertyIndex);
1831 emitOpcode(op_put_getter_setter);
1832 instructions().append(base->index());
1833 instructions().append(propertyIndex);
1834 instructions().append(getter->index());
1835 instructions().append(setter->index());
1838 RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
1840 emitOpcode(op_del_by_id);
1841 instructions().append(dst->index());
1842 instructions().append(base->index());
1843 instructions().append(addConstant(property));
1847 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1849 for (size_t i = m_forInContextStack.size(); i > 0; i--) {
1850 ForInContext* context = m_forInContextStack[i - 1].get();
1851 if (context->local() != property)
1854 if (!context->isValid())
1857 if (context->type() == ForInContext::IndexedForInContextType) {
1858 property = static_cast<IndexedForInContext*>(context)->index();
1862 ASSERT(context->type() == ForInContext::StructureForInContextType);
1863 StructureForInContext* structureContext = static_cast<StructureForInContext*>(context);
1864 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_direct_pname);
1865 instructions().append(kill(dst));
1866 instructions().append(base->index());
1867 instructions().append(property->index());
1868 instructions().append(structureContext->index()->index());
1869 instructions().append(structureContext->enumerator()->index());
1870 instructions().append(profile);
1874 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1875 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val);
1876 instructions().append(kill(dst));
1877 instructions().append(base->index());
1878 instructions().append(property->index());
1879 instructions().append(arrayProfile);
1880 instructions().append(profile);
1884 RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1886 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1887 emitOpcode(op_put_by_val);
1888 instructions().append(base->index());
1889 instructions().append(property->index());
1890 instructions().append(value->index());
1891 instructions().append(arrayProfile);
1896 RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1898 UnlinkedArrayProfile arrayProfile = newArrayProfile();
1899 emitOpcode(op_put_by_val_direct);
1900 instructions().append(base->index());
1901 instructions().append(property->index());
1902 instructions().append(value->index());
1903 instructions().append(arrayProfile);
1907 RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1909 emitOpcode(op_del_by_val);
1910 instructions().append(dst->index());
1911 instructions().append(base->index());
1912 instructions().append(property->index());
1916 RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1918 emitOpcode(op_put_by_index);
1919 instructions().append(base->index());
1920 instructions().append(index);
1921 instructions().append(value->index());
1925 RegisterID* BytecodeGenerator::emitCreateThis(RegisterID* dst)
1927 size_t begin = instructions().size();
1928 m_staticPropertyAnalyzer.createThis(m_thisRegister.index(), begin + 3);
1930 m_codeBlock->addPropertyAccessInstruction(instructions().size());
1931 emitOpcode(op_create_this);
1932 instructions().append(m_thisRegister.index());
1933 instructions().append(m_thisRegister.index());
1934 instructions().append(0);
1935 instructions().append(0);
1939 void BytecodeGenerator::emitTDZCheck(RegisterID* target)
1941 emitOpcode(op_check_tdz);
1942 instructions().append(target->index());
1945 bool BytecodeGenerator::needsTDZCheck(const Variable& variable)
1947 for (unsigned i = m_TDZStack.size(); i--;) {
1948 VariableEnvironment& identifiers = m_TDZStack[i].first;
1949 if (identifiers.contains(variable.ident().impl()))
1956 void BytecodeGenerator::emitTDZCheckIfNecessary(const Variable& variable, RegisterID* target, RegisterID* scope)
1958 if (needsTDZCheck(variable)) {
1960 emitTDZCheck(target);
1962 RELEASE_ASSERT(!variable.isLocal() && scope);
1963 RefPtr<RegisterID> result = emitGetFromScope(newTemporary(), scope, variable, DoNotThrowIfNotFound);
1964 emitTDZCheck(result.get());
1969 void BytecodeGenerator::liftTDZCheckIfPossible(const Variable& variable)
1971 RefPtr<UniquedStringImpl> identifier(variable.ident().impl());
1972 for (unsigned i = m_TDZStack.size(); i--;) {
1973 VariableEnvironment& environment = m_TDZStack[i].first;
1974 if (environment.contains(identifier)) {
1975 bool isSyntacticallyAbleToOptimizeTDZ = m_TDZStack[i].second;
1976 if (isSyntacticallyAbleToOptimizeTDZ) {
1977 bool wasRemoved = environment.remove(identifier);
1978 RELEASE_ASSERT(wasRemoved);
1985 void BytecodeGenerator::getVariablesUnderTDZ(VariableEnvironment& result)
1987 for (auto& pair : m_TDZStack) {
1988 VariableEnvironment& environment = pair.first;
1989 for (auto entry : environment)
1990 result.add(entry.key.get());
1994 RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
1996 size_t begin = instructions().size();
1997 m_staticPropertyAnalyzer.newObject(dst->index(), begin + 2);
1999 emitOpcode(op_new_object);
2000 instructions().append(dst->index());
2001 instructions().append(0);
2002 instructions().append(newObjectAllocationProfile());
2006 unsigned BytecodeGenerator::addConstantBuffer(unsigned length)
2008 return m_codeBlock->addConstantBuffer(length);
2011 JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
2013 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
2015 stringInMap = jsString(vm(), identifier.string());
2016 addConstantValue(stringInMap);
2021 JSTemplateRegistryKey* BytecodeGenerator::addTemplateRegistryKeyConstant(const TemplateRegistryKey& templateRegistryKey)
2023 JSTemplateRegistryKey*& templateRegistryKeyInMap = m_templateRegistryKeyMap.add(templateRegistryKey, nullptr).iterator->value;
2024 if (!templateRegistryKeyInMap) {
2025 templateRegistryKeyInMap = JSTemplateRegistryKey::create(*vm(), templateRegistryKey);
2026 addConstantValue(templateRegistryKeyInMap);
2028 return templateRegistryKeyInMap;
2031 RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length)
2033 #if !ASSERT_DISABLED
2034 unsigned checkLength = 0;
2036 bool hadVariableExpression = false;
2038 for (ElementNode* n = elements; n; n = n->next()) {
2039 if (!n->value()->isConstant()) {
2040 hadVariableExpression = true;
2045 #if !ASSERT_DISABLED
2049 if (!hadVariableExpression) {
2050 ASSERT(length == checkLength);
2051 unsigned constantBufferIndex = addConstantBuffer(length);
2052 JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex).data();
2054 for (ElementNode* n = elements; index < length; n = n->next()) {
2055 ASSERT(n->value()->isConstant());
2056 constantBuffer[index++] = static_cast<ConstantNode*>(n->value())->jsValue(*this);
2058 emitOpcode(op_new_array_buffer);
2059 instructions().append(dst->index());
2060 instructions().append(constantBufferIndex);
2061 instructions().append(length);
2062 instructions().append(newArrayAllocationProfile());
2067 Vector<RefPtr<RegisterID>, 16, UnsafeVectorOverflow> argv;
2068 for (ElementNode* n = elements; n; n = n->next()) {
2072 ASSERT(!n->value()->isSpreadExpression());
2073 argv.append(newTemporary());
2074 // op_new_array requires the initial values to be a sequential range of registers
2075 ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() - 1);
2076 emitNode(argv.last().get(), n->value());
2079 emitOpcode(op_new_array);
2080 instructions().append(dst->index());
2081 instructions().append(argv.size() ? argv[0]->index() : 0); // argv
2082 instructions().append(argv.size()); // argc
2083 instructions().append(newArrayAllocationProfile());
2087 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
2089 return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(function)));
2092 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index)
2094 emitOpcode(op_new_func);
2095 instructions().append(dst->index());
2096 instructions().append(scopeRegister()->index());
2097 instructions().append(index);
2101 RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
2103 emitOpcode(op_new_regexp);
2104 instructions().append(dst->index());
2105 instructions().append(addRegExp(regExp));
2109 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
2111 FunctionBodyNode* function = n->body();
2112 unsigned index = m_codeBlock->addFunctionExpr(makeFunction(function));
2114 emitOpcode(op_new_func_exp);
2115 instructions().append(r0->index());
2116 instructions().append(scopeRegister()->index());
2117 instructions().append(index);
2121 RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name)
2123 UnlinkedFunctionExecutable* executable = m_vm->builtinExecutables()->createDefaultConstructor(constructorKind, name);
2125 unsigned index = m_codeBlock->addFunctionExpr(executable);
2127 emitOpcode(op_new_func_exp);
2128 instructions().append(dst->index());
2129 instructions().append(scopeRegister()->index());
2130 instructions().append(index);
2134 RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
2136 return emitCall(op_call, dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd);
2139 RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
2141 return emitCall(op_call_eval, dst, func, NoExpectedFunction, callArguments, divot, divotStart, divotEnd);
2144 ExpectedFunction BytecodeGenerator::expectedFunctionForIdentifier(const Identifier& identifier)
2146 if (identifier == m_vm->propertyNames->Object || identifier == m_vm->propertyNames->ObjectPrivateName)
2147 return ExpectObjectConstructor;
2148 if (identifier == m_vm->propertyNames->Array || identifier == m_vm->propertyNames->ArrayPrivateName)
2149 return ExpectArrayConstructor;
2150 return NoExpectedFunction;
2153 ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, Label* done)
2155 RefPtr<Label> realCall = newLabel();
2156 switch (expectedFunction) {
2157 case ExpectObjectConstructor: {
2158 // If the number of arguments is non-zero, then we can't do anything interesting.
2159 if (callArguments.argumentCountIncludingThis() >= 2)
2160 return NoExpectedFunction;
2162 size_t begin = instructions().size();
2163 emitOpcode(op_jneq_ptr);
2164 instructions().append(func->index());
2165 instructions().append(Special::ObjectConstructor);
2166 instructions().append(realCall->bind(begin, instructions().size()));
2168 if (dst != ignoredResult())
2173 case ExpectArrayConstructor: {
2174 // If you're doing anything other than "new Array()" or "new Array(foo)" then we
2175 // don't do inline it, for now. The only reason is that call arguments are in
2176 // the opposite order of what op_new_array expects, so we'd either need to change
2177 // how op_new_array works or we'd need an op_new_array_reverse. Neither of these
2178 // things sounds like it's worth it.
2179 if (callArguments.argumentCountIncludingThis() > 2)
2180 return NoExpectedFunction;
2182 size_t begin = instructions().size();
2183 emitOpcode(op_jneq_ptr);
2184 instructions().append(func->index());
2185 instructions().append(Special::ArrayConstructor);
2186 instructions().append(realCall->bind(begin, instructions().size()));
2188 if (dst != ignoredResult()) {
2189 if (callArguments.argumentCountIncludingThis() == 2) {
2190 emitOpcode(op_new_array_with_size);
2191 instructions().append(dst->index());
2192 instructions().append(callArguments.argumentRegister(0)->index());
2193 instructions().append(newArrayAllocationProfile());
2195 ASSERT(callArguments.argumentCountIncludingThis() == 1);
2196 emitOpcode(op_new_array);
2197 instructions().append(dst->index());
2198 instructions().append(0);
2199 instructions().append(0);
2200 instructions().append(newArrayAllocationProfile());
2207 ASSERT(expectedFunction == NoExpectedFunction);
2208 return NoExpectedFunction;
2211 size_t begin = instructions().size();
2213 instructions().append(done->bind(begin, instructions().size()));
2214 emitLabel(realCall.get());
2216 return expectedFunction;
2219 RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
2221 ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
2222 ASSERT(func->refCount());
2224 if (m_shouldEmitProfileHooks)
2225 emitMove(callArguments.profileHookRegister(), func);
2227 // Generate code for arguments.
2228 unsigned argument = 0;
2229 if (callArguments.argumentsNode()) {
2230 ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
2231 if (n && n->m_expr->isSpreadExpression()) {
2232 RELEASE_ASSERT(!n->m_next);
2233 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
2234 RefPtr<RegisterID> argumentRegister;
2235 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
2236 RefPtr<RegisterID> thisRegister = emitMove(newTemporary(), callArguments.thisRegister());
2237 return emitCallVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
2239 for (; n; n = n->m_next)
2240 emitNode(callArguments.argumentRegister(argument++), n);
2243 // Reserve space for call frame.
2244 Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
2245 for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
2246 callFrame.append(newTemporary());
2248 if (m_shouldEmitProfileHooks) {
2249 emitOpcode(op_profile_will_call);
2250 instructions().append(callArguments.profileHookRegister()->index());
2253 emitExpressionInfo(divot, divotStart, divotEnd);
2255 RefPtr<Label> done = newLabel();
2256 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
2259 UnlinkedArrayProfile arrayProfile = newArrayProfile();
2260 UnlinkedValueProfile profile = emitProfiledOpcode(opcodeID);
2262 ASSERT(dst != ignoredResult());
2263 instructions().append(dst->index());
2264 instructions().append(func->index());
2265 instructions().append(callArguments.argumentCountIncludingThis());
2266 instructions().append(callArguments.stackOffset());
2267 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
2268 instructions().append(0);
2269 instructions().append(arrayProfile);
2270 instructions().append(profile);
2272 if (expectedFunction != NoExpectedFunction)
2273 emitLabel(done.get());
2275 if (m_shouldEmitProfileHooks) {
2276 emitOpcode(op_profile_did_call);
2277 instructions().append(callArguments.profileHookRegister()->index());
2283 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)
2285 return emitCallVarargs(op_call_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
2288 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)
2290 return emitCallVarargs(op_construct_varargs, dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, profileHookRegister, divot, divotStart, divotEnd);
2293 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)
2295 if (m_shouldEmitProfileHooks) {
2296 emitMove(profileHookRegister, func);
2297 emitOpcode(op_profile_will_call);
2298 instructions().append(profileHookRegister->index());
2301 emitExpressionInfo(divot, divotStart, divotEnd);
2304 UnlinkedArrayProfile arrayProfile = newArrayProfile();
2305 UnlinkedValueProfile profile = emitProfiledOpcode(opcode);
2306 ASSERT(dst != ignoredResult());
2307 instructions().append(dst->index());
2308 instructions().append(func->index());
2309 instructions().append(thisRegister ? thisRegister->index() : 0);
2310 instructions().append(arguments->index());
2311 instructions().append(firstFreeRegister->index());
2312 instructions().append(firstVarArgOffset);
2313 instructions().append(arrayProfile);
2314 instructions().append(profile);
2315 if (m_shouldEmitProfileHooks) {
2316 emitOpcode(op_profile_did_call);
2317 instructions().append(profileHookRegister->index());
2322 void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
2323 RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition& position)
2325 RefPtr<RegisterID> descriptorRegister = emitNewObject(newTemporary());
2327 RefPtr<RegisterID> trueRegister = emitLoad(newTemporary(), true);
2328 if (options & PropertyConfigurable)
2329 emitDirectPutById(descriptorRegister.get(), propertyNames().configurable, trueRegister.get(), PropertyNode::Unknown);
2330 if (options & PropertyWritable)
2331 emitDirectPutById(descriptorRegister.get(), propertyNames().writable, trueRegister.get(), PropertyNode::Unknown);
2332 else if (valueRegister) {
2333 RefPtr<RegisterID> falseRegister = emitLoad(newTemporary(), false);
2334 emitDirectPutById(descriptorRegister.get(), propertyNames().writable, falseRegister.get(), PropertyNode::Unknown);
2336 if (options & PropertyEnumerable)
2337 emitDirectPutById(descriptorRegister.get(), propertyNames().enumerable, trueRegister.get(), PropertyNode::Unknown);
2340 emitDirectPutById(descriptorRegister.get(), propertyNames().value, valueRegister, PropertyNode::Unknown);
2342 emitDirectPutById(descriptorRegister.get(), propertyNames().get, getterRegister, PropertyNode::Unknown);
2344 emitDirectPutById(descriptorRegister.get(), propertyNames().set, setterRegister, PropertyNode::Unknown);
2346 RefPtr<RegisterID> definePropertyRegister = emitMoveLinkTimeConstant(newTemporary(), LinkTimeConstant::DefinePropertyFunction);
2348 CallArguments callArguments(*this, nullptr, 3);
2349 emitLoad(callArguments.thisRegister(), jsUndefined());
2350 emitMove(callArguments.argumentRegister(0), newObj);
2351 emitMove(callArguments.argumentRegister(1), propertyNameRegister);
2352 emitMove(callArguments.argumentRegister(2), descriptorRegister.get());
2354 emitCall(newTemporary(), definePropertyRegister.get(), NoExpectedFunction, callArguments, position, position, position);
2357 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
2359 if (isConstructor()) {
2360 bool derived = constructorKind() == ConstructorKind::Derived;
2361 if (derived && src->index() == m_thisRegister.index())
2364 RefPtr<Label> isObjectLabel = newLabel();
2365 emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
2368 RefPtr<Label> isUndefinedLabel = newLabel();
2369 emitJumpIfTrue(emitIsUndefined(newTemporary(), src), isUndefinedLabel.get());
2370 emitThrowTypeError("Cannot return a non-object type in the constructor of a derived class.");
2371 emitLabel(isUndefinedLabel.get());
2372 if (constructorKind() == ConstructorKind::Derived)
2373 emitTDZCheck(&m_thisRegister);
2376 emitUnaryNoDstOp(op_ret, &m_thisRegister);
2378 emitLabel(isObjectLabel.get());
2381 return emitUnaryNoDstOp(op_ret, src);
2384 RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src)
2386 emitOpcode(opcodeID);
2387 instructions().append(src->index());
2391 RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
2393 ASSERT(func->refCount());
2395 if (m_shouldEmitProfileHooks)
2396 emitMove(callArguments.profileHookRegister(), func);
2398 // Generate code for arguments.
2399 unsigned argument = 0;
2400 if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
2402 ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
2403 if (n && n->m_expr->isSpreadExpression()) {
2404 RELEASE_ASSERT(!n->m_next);
2405 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
2406 RefPtr<RegisterID> argumentRegister;
2407 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
2408 return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, callArguments.profileHookRegister(), divot, divotStart, divotEnd);
2411 for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
2412 emitNode(callArguments.argumentRegister(argument++), n);
2415 if (m_shouldEmitProfileHooks) {
2416 emitOpcode(op_profile_will_call);
2417 instructions().append(callArguments.profileHookRegister()->index());
2420 // Reserve space for call frame.
2421 Vector<RefPtr<RegisterID>, JSStack::CallFrameHeaderSize, UnsafeVectorOverflow> callFrame;
2422 for (int i = 0; i < JSStack::CallFrameHeaderSize; ++i)
2423 callFrame.append(newTemporary());
2425 emitExpressionInfo(divot, divotStart, divotEnd);
2427 RefPtr<Label> done = newLabel();
2428 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
2430 UnlinkedValueProfile profile = emitProfiledOpcode(op_construct);
2431 ASSERT(dst != ignoredResult());
2432 instructions().append(dst->index());
2433 instructions().append(func->index());
2434 instructions().append(callArguments.argumentCountIncludingThis());
2435 instructions().append(callArguments.stackOffset());
2436 instructions().append(m_codeBlock->addLLIntCallLinkInfo());
2437 instructions().append(0);
2438 instructions().append(0);
2439 instructions().append(profile);
2441 if (expectedFunction != NoExpectedFunction)
2442 emitLabel(done.get());
2444 if (m_shouldEmitProfileHooks) {
2445 emitOpcode(op_profile_did_call);
2446 instructions().append(callArguments.profileHookRegister()->index());
2452 RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
2454 emitOpcode(op_strcat);
2455 instructions().append(dst->index());
2456 instructions().append(src->index());
2457 instructions().append(count);
2462 void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
2464 emitOpcode(op_to_primitive);
2465 instructions().append(dst->index());
2466 instructions().append(src->index());
2469 void BytecodeGenerator::emitGetScope()
2471 emitOpcode(op_get_scope);
2472 instructions().append(scopeRegister()->index());
2475 RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* dst, RegisterID* scope)
2477 ControlFlowContext context;
2478 context.isFinallyBlock = false;
2479 m_scopeContextStack.append(context);
2480 m_localScopeDepth++;
2482 RegisterID* result = emitUnaryOp(op_push_with_scope, dst, scope);
2483 m_symbolTableStack.append(SymbolTableStackEntry{ Strong<SymbolTable>(), nullptr, true, 0 });
2487 RegisterID* BytecodeGenerator::emitGetParentScope(RegisterID* dst, RegisterID* scope)
2489 emitOpcode(op_get_parent_scope);
2490 instructions().append(dst->index());
2491 instructions().append(scope->index());
2495 void BytecodeGenerator::emitPopScope(RegisterID* srcDst)
2497 ASSERT(m_scopeContextStack.size());
2498 ASSERT(!m_scopeContextStack.last().isFinallyBlock);
2500 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), srcDst);
2501 emitMove(srcDst, parentScope.get());
2503 m_scopeContextStack.removeLast();
2504 m_localScopeDepth--;
2505 SymbolTableStackEntry stackEntry = m_symbolTableStack.takeLast();
2506 RELEASE_ASSERT(stackEntry.m_isWithOrCatch);
2509 void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, unsigned line, unsigned charOffset, unsigned lineStart)
2511 #if ENABLE(DEBUG_WITH_BREAKPOINT)
2512 if (debugHookID != DidReachBreakpoint)
2515 if (!m_shouldEmitDebugHooks)
2518 JSTextPosition divot(line, charOffset, lineStart);
2519 emitExpressionInfo(divot, divot, divot);
2520 emitOpcode(op_debug);
2521 instructions().append(debugHookID);
2522 instructions().append(false);
2525 void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock)
2527 // Reclaim free label scopes.
2528 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2529 m_labelScopes.removeLast();
2531 ControlFlowContext scope;
2532 scope.isFinallyBlock = true;
2533 FinallyContext context = {
2537 static_cast<unsigned>(m_scopeContextStack.size()),
2538 static_cast<unsigned>(m_switchContextStack.size()),
2539 static_cast<unsigned>(m_forInContextStack.size()),
2540 static_cast<unsigned>(m_tryContextStack.size()),
2541 static_cast<unsigned>(m_labelScopes.size()),
2542 static_cast<unsigned>(m_symbolTableStack.size()),
2546 scope.finallyContext = context;
2547 m_scopeContextStack.append(scope);
2551 void BytecodeGenerator::pushIteratorCloseContext(RegisterID* iterator, ThrowableExpressionData* node)
2553 // Reclaim free label scopes.
2554 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2555 m_labelScopes.removeLast();
2557 ControlFlowContext scope;
2558 scope.isFinallyBlock = true;
2559 FinallyContext context = {
2563 static_cast<unsigned>(m_scopeContextStack.size()),
2564 static_cast<unsigned>(m_switchContextStack.size()),
2565 static_cast<unsigned>(m_forInContextStack.size()),
2566 static_cast<unsigned>(m_tryContextStack.size()),
2567 static_cast<unsigned>(m_labelScopes.size()),
2568 static_cast<unsigned>(m_symbolTableStack.size()),
2572 scope.finallyContext = context;
2573 m_scopeContextStack.append(scope);
2577 void BytecodeGenerator::popFinallyContext()
2579 ASSERT(m_scopeContextStack.size());
2580 ASSERT(m_scopeContextStack.last().isFinallyBlock);
2581 ASSERT(m_scopeContextStack.last().finallyContext.finallyBlock);
2582 ASSERT(!m_scopeContextStack.last().finallyContext.iterator);
2583 ASSERT(!m_scopeContextStack.last().finallyContext.enumerationNode);
2584 ASSERT(m_finallyDepth > 0);
2585 m_scopeContextStack.removeLast();
2589 void BytecodeGenerator::popIteratorCloseContext()
2591 ASSERT(m_scopeContextStack.size());
2592 ASSERT(m_scopeContextStack.last().isFinallyBlock);
2593 ASSERT(!m_scopeContextStack.last().finallyContext.finallyBlock);
2594 ASSERT(m_scopeContextStack.last().finallyContext.iterator);
2595 ASSERT(m_scopeContextStack.last().finallyContext.enumerationNode);
2596 ASSERT(m_finallyDepth > 0);
2597 m_scopeContextStack.removeLast();
2601 LabelScopePtr BytecodeGenerator::breakTarget(const Identifier& name)
2603 // Reclaim free label scopes.
2605 // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
2606 // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
2607 // size 0, leading to segfaulty badness. We are yet to identify a valid cause within our code to
2608 // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
2609 // loop condition is a workaround.
2610 while (m_labelScopes.size()) {
2611 if (m_labelScopes.last().refCount())
2613 m_labelScopes.removeLast();
2616 if (!m_labelScopes.size())
2617 return LabelScopePtr::null();
2619 // We special-case the following, which is a syntax error in Firefox:
2622 if (name.isEmpty()) {
2623 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2624 LabelScope* scope = &m_labelScopes[i];
2625 if (scope->type() != LabelScope::NamedLabel) {
2626 ASSERT(scope->breakTarget());
2627 return LabelScopePtr(m_labelScopes, i);
2630 return LabelScopePtr::null();
2633 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2634 LabelScope* scope = &m_labelScopes[i];
2635 if (scope->name() && *scope->name() == name) {
2636 ASSERT(scope->breakTarget());
2637 return LabelScopePtr(m_labelScopes, i);
2640 return LabelScopePtr::null();
2643 LabelScopePtr BytecodeGenerator::continueTarget(const Identifier& name)
2645 // Reclaim free label scopes.
2646 while (m_labelScopes.size() && !m_labelScopes.last().refCount())
2647 m_labelScopes.removeLast();
2649 if (!m_labelScopes.size())
2650 return LabelScopePtr::null();
2652 if (name.isEmpty()) {
2653 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2654 LabelScope* scope = &m_labelScopes[i];
2655 if (scope->type() == LabelScope::Loop) {
2656 ASSERT(scope->continueTarget());
2657 return LabelScopePtr(m_labelScopes, i);
2660 return LabelScopePtr::null();
2663 // Continue to the loop nested nearest to the label scope that matches
2665 LabelScopePtr result = LabelScopePtr::null();
2666 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
2667 LabelScope* scope = &m_labelScopes[i];
2668 if (scope->type() == LabelScope::Loop) {
2669 ASSERT(scope->continueTarget());
2670 result = LabelScopePtr(m_labelScopes, i);
2672 if (scope->name() && *scope->name() == name)
2673 return result; // may be null.
2675 return LabelScopePtr::null();
2678 void BytecodeGenerator::allocateAndEmitScope()
2680 m_scopeRegister = addVar();
2681 m_scopeRegister->ref();
2682 m_codeBlock->setScopeRegister(scopeRegister()->virtualRegister());
2686 void BytecodeGenerator::emitComplexPopScopes(RegisterID* scope, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
2688 while (topScope > bottomScope) {
2689 // First we count the number of dynamic scopes we need to remove to get
2690 // to a finally block.
2691 int nNormalScopes = 0;
2692 while (topScope > bottomScope) {
2693 if (topScope->isFinallyBlock)
2699 if (nNormalScopes) {
2700 // We need to remove a number of dynamic scopes to get to the next
2702 RefPtr<RegisterID> parentScope = newTemporary();
2703 while (nNormalScopes--) {
2704 parentScope = emitGetParentScope(parentScope.get(), scope);
2705 emitMove(scope, parentScope.get());
2708 // If topScope == bottomScope then there isn't a finally block left to emit.
2709 if (topScope == bottomScope)
2713 Vector<ControlFlowContext> savedScopeContextStack;
2714 Vector<SwitchInfo> savedSwitchContextStack;
2715 Vector<std::unique_ptr<ForInContext>> savedForInContextStack;
2716 Vector<TryContext> poppedTryContexts;
2717 Vector<SymbolTableStackEntry> savedSymbolTableStack;
2718 LabelScopeStore savedLabelScopes;
2719 while (topScope > bottomScope && topScope->isFinallyBlock) {
2720 RefPtr<Label> beforeFinally = emitLabel(newLabel().get());
2722 // Save the current state of the world while instating the state of the world
2723 // for the finally block.
2724 FinallyContext finallyContext = topScope->finallyContext;
2725 bool flipScopes = finallyContext.scopeContextStackSize != m_scopeContextStack.size();
2726 bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size();
2727 bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size();
2728 bool flipTries = finallyContext.tryContextStackSize != m_tryContextStack.size();
2729 bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size();
2730 bool flipSymbolTableStack = finallyContext.symbolTableStackSize != m_symbolTableStack.size();
2731 int topScopeIndex = -1;
2732 int bottomScopeIndex = -1;
2734 topScopeIndex = topScope - m_scopeContextStack.begin();
2735 bottomScopeIndex = bottomScope - m_scopeContextStack.begin();
2736 savedScopeContextStack = m_scopeContextStack;
2737 m_scopeContextStack.shrink(finallyContext.scopeContextStackSize);
2740 savedSwitchContextStack = m_switchContextStack;
2741 m_switchContextStack.shrink(finallyContext.switchContextStackSize);
2744 savedForInContextStack.swap(m_forInContextStack);
2745 m_forInContextStack.shrink(finallyContext.forInContextStackSize);
2748 while (m_tryContextStack.size() != finallyContext.tryContextStackSize) {
2749 ASSERT(m_tryContextStack.size() > finallyContext.tryContextStackSize);
2750 TryContext context = m_tryContextStack.last();
2751 m_tryContextStack.removeLast();
2753 range.start = context.start;
2754 range.end = beforeFinally;
2755 range.tryData = context.tryData;
2756 m_tryRanges.append(range);
2757 poppedTryContexts.append(context);
2760 if (flipLabelScopes) {
2761 savedLabelScopes = m_labelScopes;
2762 while (m_labelScopes.size() > finallyContext.labelScopesSize)
2763 m_labelScopes.removeLast();
2765 if (flipSymbolTableStack) {
2766 savedSymbolTableStack = m_symbolTableStack;
2767 m_symbolTableStack.shrink(finallyContext.symbolTableStackSize);
2769 int savedFinallyDepth = m_finallyDepth;
2770 m_finallyDepth = finallyContext.finallyDepth;
2771 int savedDynamicScopeDepth = m_localScopeDepth;
2772 m_localScopeDepth = finallyContext.dynamicScopeDepth;
2774 if (finallyContext.finallyBlock) {
2775 // Emit the finally block.
2776 emitNode(finallyContext.finallyBlock);
2778 // Emit the IteratorClose block.
2779 ASSERT(finallyContext.iterator);
2780 emitIteratorClose(finallyContext.iterator, finallyContext.enumerationNode);
2783 RefPtr<Label> afterFinally = emitLabel(newLabel().get());
2785 // Restore the state of the world.
2787 m_scopeContextStack = savedScopeContextStack;
2788 topScope = &m_scopeContextStack[topScopeIndex]; // assert it's within bounds
2789 bottomScope = m_scopeContextStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1.
2792 m_switchContextStack = savedSwitchContextStack;
2794 m_forInContextStack.swap(savedForInContextStack);
2796 ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize);
2797 for (unsigned i = poppedTryContexts.size(); i--;) {
2798 TryContext context = poppedTryContexts[i];
2799 context.start = afterFinally;
2800 m_tryContextStack.append(context);
2802 poppedTryContexts.clear();
2804 if (flipLabelScopes)
2805 m_labelScopes = savedLabelScopes;
2806 if (flipSymbolTableStack)
2807 m_symbolTableStack = savedSymbolTableStack;
2808 m_finallyDepth = savedFinallyDepth;
2809 m_localScopeDepth = savedDynamicScopeDepth;
2816 void BytecodeGenerator::emitPopScopes(RegisterID* scope, int targetScopeDepth)
2818 ASSERT(scopeDepth() - targetScopeDepth >= 0);
2820 size_t scopeDelta = scopeDepth() - targetScopeDepth;
2821 ASSERT(scopeDelta <= m_scopeContextStack.size());
2825 if (!m_finallyDepth) {
2826 RefPtr<RegisterID> parentScope = newTemporary();
2827 while (scopeDelta--) {
2828 parentScope = emitGetParentScope(parentScope.get(), scope);
2829 emitMove(scope, parentScope.get());
2834 emitComplexPopScopes(scope, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
2837 TryData* BytecodeGenerator::pushTry(Label* start)
2840 tryData.target = newLabel();
2841 tryData.targetScopeDepth = UINT_MAX;
2842 tryData.handlerType = HandlerType::Illegal;
2843 m_tryData.append(tryData);
2844 TryData* result = &m_tryData.last();
2846 TryContext tryContext;
2847 tryContext.start = start;
2848 tryContext.tryData = result;
2850 m_tryContextStack.append(tryContext);
2855 void BytecodeGenerator::popTryAndEmitCatch(TryData* tryData, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType handlerType)
2857 m_usesExceptions = true;
2859 ASSERT_UNUSED(tryData, m_tryContextStack.last().tryData == tryData);
2862 tryRange.start = m_tryContextStack.last().start;
2864 tryRange.tryData = m_tryContextStack.last().tryData;
2865 m_tryRanges.append(tryRange);
2866 m_tryContextStack.removeLast();
2868 emitLabel(tryRange.tryData->target.get());
2869 tryRange.tryData->targetScopeDepth = calculateTargetScopeDepthForExceptionHandler();
2870 tryRange.tryData->handlerType = handlerType;
2872 emitOpcode(op_catch);
2873 instructions().append(exceptionRegister->index());
2874 instructions().append(thrownValueRegister->index());
2877 int BytecodeGenerator::calculateTargetScopeDepthForExceptionHandler() const
2879 int depth = m_localScopeDepth;
2881 for (unsigned i = m_symbolTableStack.size(); i--; ) {
2882 RegisterID* scope = m_symbolTableStack[i].m_scope;
2887 // Currently, we're maintaing compatibility with how things are done and letting the exception handling
2888 // code take into consideration the base activation of the function. There is no reason we shouldn't
2889 // be able to calculate the exact depth here and let the exception handler not worry if there is a base
2890 // activation or not.
2891 if (m_lexicalEnvironmentRegister)
2898 int BytecodeGenerator::currentScopeDepth() const
2900 // This is the current number of JSScope descendents that would be allocated
2901 // in this function/program if this code were running.
2903 for (unsigned i = m_symbolTableStack.size(); i--; ) {
2904 if (m_symbolTableStack[i].m_scope || m_symbolTableStack[i].m_isWithOrCatch)
2910 void BytecodeGenerator::emitThrowReferenceError(const String& message)
2912 emitOpcode(op_throw_static_error);
2913 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, message)))->index());
2914 instructions().append(true);
2917 void BytecodeGenerator::emitThrowTypeError(const String& message)
2919 emitOpcode(op_throw_static_error);
2920 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, message)))->index());
2921 instructions().append(false);
2924 void BytecodeGenerator::emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)
2926 emitOpcode(op_push_name_scope);
2927 instructions().append(dst->index());
2928 instructions().append(value->index());
2929 instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property, attributes))->index());
2930 instructions().append(JSNameScope::FunctionNameScope);
2933 void BytecodeGenerator::emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)
2935 ControlFlowContext context;
2936 context.isFinallyBlock = false;
2937 m_scopeContextStack.append(context);
2938 m_localScopeDepth++;
2940 emitOpcode(op_push_name_scope);
2941 instructions().append(dst->index());
2942 instructions().append(value->index());
2943 instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property, attributes))->index());
2944 instructions().append(JSNameScope::CatchScope);
2946 m_symbolTableStack.append(SymbolTableStackEntry{ Strong<SymbolTable>(), nullptr, true, 0 });
2949 void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
2951 SwitchInfo info = { static_cast<uint32_t>(instructions().size()), type };
2953 case SwitchInfo::SwitchImmediate:
2954 emitOpcode(op_switch_imm);
2956 case SwitchInfo::SwitchCharacter:
2957 emitOpcode(op_switch_char);
2959 case SwitchInfo::SwitchString:
2960 emitOpcode(op_switch_string);
2963 RELEASE_ASSERT_NOT_REACHED();
2966 instructions().append(0); // place holder for table index
2967 instructions().append(0); // place holder for default target
2968 instructions().append(scrutineeRegister->index());
2969 m_switchContextStack.append(info);
2972 static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
2975 ASSERT(node->isNumber());
2976 double value = static_cast<NumberNode*>(node)->value();
2977 int32_t key = static_cast<int32_t>(value);
2978 ASSERT(key == value);
2984 static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
2987 ASSERT(node->isString());
2988 StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
2989 ASSERT(clause->length() == 1);
2991 int32_t key = (*clause)[0];
2997 static void prepareJumpTableForSwitch(
2998 UnlinkedSimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount,
2999 RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max,
3000 int32_t (*keyGetter)(ExpressionNode*, int32_t min, int32_t max))
3002 jumpTable.min = min;
3003 jumpTable.branchOffsets.resize(max - min + 1);
3004 jumpTable.branchOffsets.fill(0);
3005 for (uint32_t i = 0; i < clauseCount; ++i) {
3006 // We're emitting this after the clause labels should have been fixed, so
3007 // the labels should not be "forward" references
3008 ASSERT(!labels[i]->isForward());
3009 jumpTable.add(keyGetter(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3));
3013 static void prepareJumpTableForStringSwitch(UnlinkedStringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
3015 for (uint32_t i = 0; i < clauseCount; ++i) {
3016 // We're emitting this after the clause labels should have been fixed, so
3017 // the labels should not be "forward" references
3018 ASSERT(!labels[i]->isForward());
3020 ASSERT(nodes[i]->isString());
3021 StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
3022 jumpTable.offsetTable.add(clause, labels[i]->bind(switchAddress, switchAddress + 3));
3026 void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max)
3028 SwitchInfo switchInfo = m_switchContextStack.last();
3029 m_switchContextStack.removeLast();
3031 switch (switchInfo.switchType) {
3032 case SwitchInfo::SwitchImmediate:
3033 case SwitchInfo::SwitchCharacter: {
3034 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfSwitchJumpTables();
3035 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
3037 UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->addSwitchJumpTable();
3038 prepareJumpTableForSwitch(
3039 jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max,
3040 switchInfo.switchType == SwitchInfo::SwitchImmediate
3041 ? keyForImmediateSwitch
3042 : keyForCharacterSwitch);
3046 case SwitchInfo::SwitchString: {
3047 instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
3048 instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
3050 UnlinkedStringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
3051 prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
3056 RELEASE_ASSERT_NOT_REACHED();
3061 RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
3063 // It would be nice to do an even better job of identifying exactly where the expression is.
3064 // And we could make the caller pass the node pointer in, if there was some way of getting
3065 // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
3066 // is still good enough to get us an accurate line number.
3067 m_expressionTooDeep = true;
3068 return newTemporary();
3071 bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
3073 RegisterID* registerID = variable(ident).local();
3076 return registerID->index() == CallFrame::argumentOffset(argumentNumber);
3079 void BytecodeGenerator::emitReadOnlyExceptionIfNeeded()
3081 if (!isStrictMode())
3083 emitOpcode(op_throw_static_error);
3084 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm, StrictModeReadonlyPropertyWriteError)))->index());
3085 instructions().append(false);
3088 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, VariableEnvironmentNode* forLoopNode, RegisterID* forLoopSymbolTable)
3090 RefPtr<RegisterID> subject = newTemporary();
3091 emitNode(subject.get(), subjectNode);
3092 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), subject.get(), propertyNames().iteratorSymbol);
3094 CallArguments args(*this, nullptr);
3095 emitMove(args.thisRegister(), subject.get());
3096 emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd());
3099 RefPtr<Label> loopDone = newLabel();
3100 // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext.
3101 pushIteratorCloseContext(iterator.get(), node);
3103 LabelScopePtr scope = newLabelScope(LabelScope::Loop);
3104 RefPtr<RegisterID> value = newTemporary();
3105 emitLoad(value.get(), jsUndefined());
3107 emitJump(scope->continueTarget());
3109 RefPtr<Label> loopStart = newLabel();
3110 emitLabel(loopStart.get());
3113 RefPtr<Label> tryStartLabel = newLabel();
3114 emitLabel(tryStartLabel.get());
3115 TryData* tryData = pushTry(tryStartLabel.get());
3116 callBack(*this, value.get());
3117 emitJump(scope->continueTarget());
3119 // IteratorClose sequence for throw-ed control flow.
3121 RefPtr<Label> catchHere = emitLabel(newLabel().get());
3122 RefPtr<RegisterID> exceptionRegister = newTemporary();
3123 RefPtr<RegisterID> thrownValueRegister = newTemporary();
3124 popTryAndEmitCatch(tryData, exceptionRegister.get(),
3125 thrownValueRegister.get(), catchHere.get(), HandlerType::SynthesizedFinally);
3127 RefPtr<Label> catchDone = newLabel();
3129 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
3130 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), catchDone.get());
3132 RefPtr<Label> returnCallTryStart = newLabel();
3133 emitLabel(returnCallTryStart.get());
3134 TryData* returnCallTryData = pushTry(returnCallTryStart.get());
3136 CallArguments returnArguments(*this, nullptr);
3137 emitMove(returnArguments.thisRegister(), iterator.get());
3138 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd());
3140 emitLabel(catchDone.get());
3141 emitThrow(exceptionRegister.get());
3143 // Absorb exception.
3144 popTryAndEmitCatch(returnCallTryData, newTemporary(),
3145 newTemporary(), catchDone.get(), HandlerType::SynthesizedFinally);
3146 emitThrow(exceptionRegister.get());
3149 emitLabel(scope->continueTarget());
3151 prepareLexicalScopeForNextForLoopIteration(forLoopNode, forLoopSymbolTable);
3154 emitIteratorNext(value.get(), iterator.get(), node);
3155 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get());
3156 emitGetById(value.get(), value.get(), propertyNames().value);
3157 emitJump(loopStart.get());
3160 emitLabel(scope->breakTarget());
3163 // IteratorClose sequence for break-ed control flow.
3164 popIteratorCloseContext();
3165 emitIteratorClose(iterator.get(), node);
3166 emitLabel(loopDone.get());
3169 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
3170 RegisterID* BytecodeGenerator::emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode* taggedTemplate)
3172 TemplateRegistryKey::StringVector rawStrings;
3173 TemplateRegistryKey::StringVector cookedStrings;
3175 TemplateStringListNode* templateString = taggedTemplate->templateLiteral()->templateStrings();
3176 for (; templateString; templateString = templateString->next()) {
3177 rawStrings.append(templateString->value()->raw().impl());
3178 cookedStrings.append(templateString->value()->cooked().impl());
3181 RefPtr<RegisterID> getTemplateObject = nullptr;
3182 Variable var = variable(propertyNames().getTemplateObjectPrivateName);
3183 if (RegisterID* local = var.local())
3184 getTemplateObject = emitMove(newTemporary(), local);
3186 getTemplateObject = newTemporary();
3187 RefPtr<RegisterID> scope = newTemporary();
3188 moveToDestinationIfNeeded(scope.get(), emitResolveScope(scope.get(), var));
3189 emitGetFromScope(getTemplateObject.get(), scope.get(), var, ThrowIfNotFound);
3192 CallArguments arguments(*this, nullptr);
3193 emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(TemplateRegistryKey(rawStrings, cookedStrings))));
3194 return emitCall(dst, getTemplateObject.get(), NoExpectedFunction, arguments, taggedTemplate->divot(), taggedTemplate->divotStart(), taggedTemplate->divotEnd());
3198 RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)