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());
80 RefPtr
<RegisterID
> temp
= newTemporary();
81 RefPtr
<RegisterID
> globalScope
= scopeRegister(); // FIXME: With lexical scoping, this won't always be the global object: https://bugs.webkit.org/show_bug.cgi?id=142944
82 for (auto functionPair
: m_functionsToInitialize
) {
83 FunctionBodyNode
* functionBody
= functionPair
.first
;
84 FunctionVariableType functionType
= functionPair
.second
;
85 emitNewFunction(temp
.get(), functionBody
);
86 if (functionType
== NormalFunctionVariable
)
87 initializeVariable(variable(functionBody
->ident()) , temp
.get());
88 else if (functionType
== GlobalFunctionVariable
)
89 emitPutToScope(globalScope
.get(), Variable(functionBody
->ident()), temp
.get(), ThrowIfNotFound
);
91 RELEASE_ASSERT_NOT_REACHED();
95 bool callingClassConstructor
= constructorKind() != ConstructorKind::None
&& !isConstructor();
96 if (!callingClassConstructor
)
97 m_scopeNode
->emitBytecode(*this);
99 m_staticPropertyAnalyzer
.kill();
101 for (unsigned i
= 0; i
< m_tryRanges
.size(); ++i
) {
102 TryRange
& range
= m_tryRanges
[i
];
103 int start
= range
.start
->bind();
104 int end
= range
.end
->bind();
106 // This will happen for empty try blocks and for some cases of finally blocks:
118 // The return will pop scopes to execute the outer finally block. But this includes
119 // popping the try context for the inner try. The try context is live in the fall-through
120 // part of the finally block not because we will emit a handler that overlaps the finally,
121 // but because we haven't yet had a chance to plant the catch target. Then when we finish
122 // emitting code for the outer finally block, we repush the try contex, this time with a
123 // new start index. But that means that the start index for the try range corresponding
124 // to the inner-finally-following-the-return (marked as "*HERE*" above) will be greater
125 // than the end index of the try block. This is harmless since end < start handlers will
126 // never get matched in our logic, but we do the runtime a favor and choose to not emit
127 // such handlers at all.
131 ASSERT(range
.tryData
->targetScopeDepth
!= UINT_MAX
);
132 ASSERT(range
.tryData
->handlerType
!= HandlerType::Illegal
);
133 UnlinkedHandlerInfo
info(static_cast<uint32_t>(start
), static_cast<uint32_t>(end
),
134 static_cast<uint32_t>(range
.tryData
->target
->bind()), range
.tryData
->targetScopeDepth
,
135 range
.tryData
->handlerType
);
136 m_codeBlock
->addExceptionHandler(info
);
139 m_codeBlock
->setInstructions(std::make_unique
<UnlinkedInstructionStream
>(m_instructions
));
141 m_codeBlock
->shrinkToFit();
143 if (m_codeBlock
->symbolTable() && !m_codeBlock
->vm()->typeProfiler())
144 m_codeBlock
->setSymbolTable(m_codeBlock
->symbolTable()->cloneScopePart(*m_codeBlock
->vm()));
146 if (m_expressionTooDeep
)
147 return ParserError(ParserError::OutOfMemory
);
148 return ParserError(ParserError::ErrorNone
);
151 BytecodeGenerator::BytecodeGenerator(VM
& vm
, ProgramNode
* programNode
, UnlinkedProgramCodeBlock
* codeBlock
, DebuggerMode debuggerMode
, ProfilerMode profilerMode
)
152 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode
== DebuggerOn
)
153 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode
== ProfilerOn
)
154 , m_scopeNode(programNode
)
155 , m_codeBlock(vm
, codeBlock
)
156 , m_thisRegister(CallFrame::thisArgumentOffset())
157 , m_codeType(GlobalCode
)
160 for (auto& constantRegister
: m_linkTimeConstantRegisters
)
161 constantRegister
= nullptr;
163 m_codeBlock
->setNumParameters(1); // Allocate space for "this"
165 emitOpcode(op_enter
);
167 allocateAndEmitScope();
169 const VarStack
& varStack
= programNode
->varStack();
170 const FunctionStack
& functionStack
= programNode
->functionStack();
172 for (size_t i
= 0; i
< functionStack
.size(); ++i
) {
173 FunctionBodyNode
* function
= functionStack
[i
];
174 m_functionsToInitialize
.append(std::make_pair(function
, GlobalFunctionVariable
));
177 for (size_t i
= 0; i
< varStack
.size(); ++i
)
178 codeBlock
->addVariableDeclaration(varStack
[i
].first
, !!(varStack
[i
].second
& DeclarationStacks::IsConstant
));
182 BytecodeGenerator::BytecodeGenerator(VM
& vm
, FunctionNode
* functionNode
, UnlinkedFunctionCodeBlock
* codeBlock
, DebuggerMode debuggerMode
, ProfilerMode profilerMode
)
183 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode
== DebuggerOn
)
184 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode
== ProfilerOn
)
185 , m_symbolTable(codeBlock
->symbolTable())
186 , m_scopeNode(functionNode
)
187 , m_codeBlock(vm
, codeBlock
)
188 , m_codeType(FunctionCode
)
190 , m_isBuiltinFunction(codeBlock
->isBuiltinFunction())
192 for (auto& constantRegister
: m_linkTimeConstantRegisters
)
193 constantRegister
= nullptr;
195 if (m_isBuiltinFunction
)
196 m_shouldEmitDebugHooks
= false;
198 m_symbolTable
->setUsesNonStrictEval(codeBlock
->usesEval() && !codeBlock
->isStrictMode());
199 Vector
<Identifier
> boundParameterProperties
;
200 FunctionParameters
& parameters
= *functionNode
->parameters();
201 for (size_t i
= 0; i
< parameters
.size(); i
++) {
202 auto pattern
= parameters
.at(i
);
203 if (pattern
->isBindingNode())
205 pattern
->collectBoundIdentifiers(boundParameterProperties
);
209 bool shouldCaptureSomeOfTheThings
= m_shouldEmitDebugHooks
|| m_codeBlock
->needsFullScopeChain();
210 bool shouldCaptureAllOfTheThings
= m_shouldEmitDebugHooks
|| codeBlock
->usesEval();
211 bool needsArguments
= functionNode
->usesArguments() || codeBlock
->usesEval();
213 auto captures
= [&] (UniquedStringImpl
* uid
) -> bool {
214 if (shouldCaptureAllOfTheThings
)
216 if (!shouldCaptureSomeOfTheThings
)
218 if (needsArguments
&& uid
== propertyNames().arguments
.impl()) {
219 // Actually, we only need to capture the arguments object when we "need full activation"
220 // because of name scopes. But historically we did it this way, so for now we just preserve
222 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=143072
225 return functionNode
->captures(uid
);
227 auto varKind
= [&] (UniquedStringImpl
* uid
) -> VarKind
{
228 return captures(uid
) ? VarKind::Scope
: VarKind::Stack
;
231 emitOpcode(op_enter
);
233 allocateAndEmitScope();
235 m_calleeRegister
.setIndex(JSStack::Callee
);
237 if (functionNameIsInScope(functionNode
->ident(), functionNode
->functionMode())
238 && functionNameScopeIsDynamic(codeBlock
->usesEval(), codeBlock
->isStrictMode())) {
239 // When we do this, we should make our local scope stack know about the function name symbol
240 // table. Currently this works because bytecode linking creates a phony name scope.
241 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141885
242 // Also, we could create the scope once per JSFunction instance that needs it. That wouldn't
243 // be any more correct, but it would be more performant.
244 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141887
245 emitPushFunctionNameScope(m_scopeRegister
, functionNode
->ident(), &m_calleeRegister
, ReadOnly
| DontDelete
);
248 if (shouldCaptureSomeOfTheThings
) {
249 m_lexicalEnvironmentRegister
= addVar();
250 m_codeBlock
->setActivationRegister(m_lexicalEnvironmentRegister
->virtualRegister());
251 emitOpcode(op_create_lexical_environment
);
252 instructions().append(m_lexicalEnvironmentRegister
->index());
253 instructions().append(scopeRegister()->index());
255 instructions().append(scopeRegister()->index());
256 instructions().append(m_lexicalEnvironmentRegister
->index());
259 // Make sure the code block knows about all of our parameters, and make sure that parameters
260 // needing destructuring are noted.
261 m_parameters
.grow(parameters
.size() + 1); // reserve space for "this"
262 m_thisRegister
.setIndex(initializeNextParameter()->index()); // this
263 for (unsigned i
= 0; i
< parameters
.size(); ++i
) {
264 auto pattern
= parameters
.at(i
);
265 RegisterID
* reg
= initializeNextParameter();
266 if (!pattern
->isBindingNode())
267 m_destructuringParameters
.append(std::make_pair(reg
, pattern
));
270 // Figure out some interesting facts about our arguments.
271 bool capturesAnyArgumentByName
= false;
272 if (functionNode
->hasCapturedVariables()) {
273 FunctionParameters
& parameters
= *functionNode
->parameters();
274 for (size_t i
= 0; i
< parameters
.size(); ++i
) {
275 auto pattern
= parameters
.at(i
);
276 if (!pattern
->isBindingNode())
278 const Identifier
& ident
= static_cast<const BindingNode
*>(pattern
)->boundProperty();
279 capturesAnyArgumentByName
|= captures(ident
.impl());
283 if (capturesAnyArgumentByName
)
284 ASSERT(m_lexicalEnvironmentRegister
);
286 // Need to know what our functions are called. Parameters have some goofy behaviors when it
287 // comes to functions of the same name.
288 for (FunctionBodyNode
* function
: functionNode
->functionStack())
289 m_functions
.add(function
->ident().impl());
291 if (needsArguments
) {
292 // Create the arguments object now. We may put the arguments object into the activation if
293 // it is captured. Either way, we create two arguments object variables: one is our
294 // private variable that is immutable, and another that is the user-visible variable. The
295 // immutable one is only used here, or during formal parameter resolutions if we opt for
298 m_argumentsRegister
= addVar();
299 m_argumentsRegister
->ref();
302 if (needsArguments
&& !codeBlock
->isStrictMode()) {
303 // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we
304 // use DirectArguments. With ScopedArguments, we lift all of our arguments into the
307 if (capturesAnyArgumentByName
) {
308 m_symbolTable
->setArgumentsLength(vm
, parameters
.size());
310 // For each parameter, we have two possibilities:
311 // Either it's a binding node with no function overlap, in which case it gets a name
312 // in the symbol table - or it just gets space reserved in the symbol table. Either
313 // way we lift the value into the scope.
314 for (unsigned i
= 0; i
< parameters
.size(); ++i
) {
315 ScopeOffset offset
= m_symbolTable
->takeNextScopeOffset();
316 m_symbolTable
->setArgumentOffset(vm
, i
, offset
);
317 if (UniquedStringImpl
* name
= visibleNameForParameter(parameters
.at(i
))) {
318 VarOffset
varOffset(offset
);
319 SymbolTableEntry
entry(varOffset
);
320 // Stores to these variables via the ScopedArguments object will not do
321 // notifyWrite(), since that would be cumbersome. Also, watching formal
322 // parameters when "arguments" is in play is unlikely to be super profitable.
323 // So, we just disable it.
324 entry
.disableWatching();
325 m_symbolTable
->set(name
, entry
);
327 emitOpcode(op_put_to_scope
);
328 instructions().append(m_lexicalEnvironmentRegister
->index());
329 instructions().append(UINT_MAX
);
330 instructions().append(virtualRegisterForArgument(1 + i
).offset());
331 instructions().append(ResolveModeAndType(ThrowIfNotFound
, LocalClosureVar
).operand());
332 instructions().append(0);
333 instructions().append(offset
.offset());
336 // This creates a scoped arguments object and copies the overflow arguments into the
337 // scope. It's the equivalent of calling ScopedArguments::createByCopying().
338 emitOpcode(op_create_scoped_arguments
);
339 instructions().append(m_argumentsRegister
->index());
340 instructions().append(m_lexicalEnvironmentRegister
->index());
342 // We're going to put all parameters into the DirectArguments object. First ensure
343 // that the symbol table knows that this is happening.
344 for (unsigned i
= 0; i
< parameters
.size(); ++i
) {
345 if (UniquedStringImpl
* name
= visibleNameForParameter(parameters
.at(i
)))
346 m_symbolTable
->set(name
, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i
))));
349 emitOpcode(op_create_direct_arguments
);
350 instructions().append(m_argumentsRegister
->index());
353 // Create the formal parameters the normal way. Any of them could be captured, or not. If
354 // captured, lift them into the scope.
355 for (unsigned i
= 0; i
< parameters
.size(); ++i
) {
356 UniquedStringImpl
* name
= visibleNameForParameter(parameters
.at(i
));
360 if (!captures(name
)) {
361 // This is the easy case - just tell the symbol table about the argument. It will
362 // be accessed directly.
363 m_symbolTable
->set(name
, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i
))));
367 ScopeOffset offset
= m_symbolTable
->takeNextScopeOffset();
368 const Identifier
& ident
=
369 static_cast<const BindingNode
*>(parameters
.at(i
))->boundProperty();
370 m_symbolTable
->set(name
, SymbolTableEntry(VarOffset(offset
)));
372 emitOpcode(op_put_to_scope
);
373 instructions().append(m_lexicalEnvironmentRegister
->index());
374 instructions().append(addConstant(ident
));
375 instructions().append(virtualRegisterForArgument(1 + i
).offset());
376 instructions().append(ResolveModeAndType(ThrowIfNotFound
, LocalClosureVar
).operand());
377 instructions().append(0);
378 instructions().append(offset
.offset());
382 if (needsArguments
&& codeBlock
->isStrictMode()) {
383 // Allocate an out-of-bands arguments object.
384 emitOpcode(op_create_out_of_band_arguments
);
385 instructions().append(m_argumentsRegister
->index());
388 // Now declare all variables.
389 for (const Identifier
& ident
: boundParameterProperties
)
390 createVariable(ident
, varKind(ident
.impl()), IsVariable
);
391 for (FunctionBodyNode
* function
: functionNode
->functionStack()) {
392 const Identifier
& ident
= function
->ident();
393 createVariable(ident
, varKind(ident
.impl()), IsVariable
);
394 m_functionsToInitialize
.append(std::make_pair(function
, NormalFunctionVariable
));
396 for (auto& entry
: functionNode
->varStack()) {
397 ConstantMode constantMode
= modeForIsConstant(entry
.second
& DeclarationStacks::IsConstant
);
398 // Variables named "arguments" are never const.
399 if (entry
.first
== propertyNames().arguments
)
400 constantMode
= IsVariable
;
401 createVariable(entry
.first
, varKind(entry
.first
.impl()), constantMode
, IgnoreExisting
);
404 // There are some variables that need to be preinitialized to something other than Undefined:
406 // - "arguments": unless it's used as a function or parameter, this should refer to the
409 // - callee: unless it's used as a var, function, or parameter, this should refer to the
410 // callee (i.e. our function).
412 // - functions: these always override everything else.
414 // The most logical way to do all of this is to initialize none of the variables until now,
415 // and then initialize them in BytecodeGenerator::generate() in such an order that the rules
416 // for how these things override each other end up holding. We would initialize the callee
417 // first, then "arguments", then all arguments, then the functions.
419 // But some arguments are already initialized by default, since if they aren't captured and we
420 // don't have "arguments" then we just point the symbol table at the stack slot of those
421 // arguments. We end up initializing the rest of the arguments that have an uncomplicated
422 // binding (i.e. don't involve destructuring) above when figuring out how to lay them out,
423 // because that's just the simplest thing. This means that when we initialize them, we have to
424 // watch out for the things that override arguments (namely, functions).
426 // We also initialize callee here as well, just because it's so weird. We know whether we want
427 // to do this because we can just check if it's in the symbol table.
428 if (functionNameIsInScope(functionNode
->ident(), functionNode
->functionMode())
429 && !functionNameScopeIsDynamic(codeBlock
->usesEval(), codeBlock
->isStrictMode())
430 && m_symbolTable
->get(functionNode
->ident().impl()).isNull()) {
431 if (captures(functionNode
->ident().impl())) {
434 ConcurrentJITLocker
locker(m_symbolTable
->m_lock
);
435 offset
= m_symbolTable
->takeNextScopeOffset(locker
);
437 locker
, functionNode
->ident().impl(),
438 SymbolTableEntry(VarOffset(offset
), ReadOnly
));
441 emitOpcode(op_put_to_scope
);
442 instructions().append(m_lexicalEnvironmentRegister
->index());
443 instructions().append(addConstant(functionNode
->ident()));
444 instructions().append(m_calleeRegister
.index());
445 instructions().append(ResolveModeAndType(ThrowIfNotFound
, LocalClosureVar
).operand());
446 instructions().append(0);
447 instructions().append(offset
.offset());
450 functionNode
->ident().impl(),
451 SymbolTableEntry(VarOffset(m_calleeRegister
.virtualRegister()), ReadOnly
));
455 // This is our final act of weirdness. "arguments" is overridden by everything except the
456 // callee. We add it to the symbol table if it's not already there and it's not an argument.
457 if (needsArguments
) {
458 // If "arguments" is overridden by a function or destructuring parameter name, then it's
459 // OK for us to call createVariable() because it won't change anything. It's also OK for
460 // us to them tell BytecodeGenerator::generate() to write to it because it will do so
461 // before it initializes functions and destructuring parameters. But if "arguments" is
462 // overridden by a "simple" function parameter, then we have to bail: createVariable()
463 // would assert and BytecodeGenerator::generate() would write the "arguments" after the
464 // argument value had already been properly initialized.
466 bool haveParameterNamedArguments
= false;
467 for (unsigned i
= 0; i
< parameters
.size(); ++i
) {
468 UniquedStringImpl
* name
= visibleNameForParameter(parameters
.at(i
));
469 if (name
== propertyNames().arguments
.impl()) {
470 haveParameterNamedArguments
= true;
475 if (!haveParameterNamedArguments
) {
477 propertyNames().arguments
, varKind(propertyNames().arguments
.impl()), IsVariable
);
478 m_needToInitializeArguments
= true;
482 if (isConstructor()) {
483 if (constructorKind() == ConstructorKind::Derived
) {
484 m_newTargetRegister
= addVar();
485 emitMove(m_newTargetRegister
, &m_thisRegister
);
486 emitMoveEmptyValue(&m_thisRegister
);
488 emitCreateThis(&m_thisRegister
);
489 } else if (constructorKind() != ConstructorKind::None
) {
490 emitThrowTypeError("Cannot call a class constructor");
491 } else if (functionNode
->usesThis() || codeBlock
->usesEval()) {
492 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
493 emitOpcode(op_to_this
);
494 instructions().append(kill(&m_thisRegister
));
495 instructions().append(0);
496 instructions().append(0);
500 BytecodeGenerator::BytecodeGenerator(VM
& vm
, EvalNode
* evalNode
, UnlinkedEvalCodeBlock
* codeBlock
, DebuggerMode debuggerMode
, ProfilerMode profilerMode
)
501 : m_shouldEmitDebugHooks(Options::forceDebuggerBytecodeGeneration() || debuggerMode
== DebuggerOn
)
502 , m_shouldEmitProfileHooks(Options::forceProfilerBytecodeGeneration() || profilerMode
== ProfilerOn
)
503 , m_symbolTable(codeBlock
->symbolTable())
504 , m_scopeNode(evalNode
)
505 , m_codeBlock(vm
, codeBlock
)
506 , m_thisRegister(CallFrame::thisArgumentOffset())
507 , m_codeType(EvalCode
)
510 for (auto& constantRegister
: m_linkTimeConstantRegisters
)
511 constantRegister
= nullptr;
513 m_symbolTable
->setUsesNonStrictEval(codeBlock
->usesEval() && !codeBlock
->isStrictMode());
514 m_codeBlock
->setNumParameters(1);
516 emitOpcode(op_enter
);
518 allocateAndEmitScope();
520 const DeclarationStacks::FunctionStack
& functionStack
= evalNode
->functionStack();
521 for (size_t i
= 0; i
< functionStack
.size(); ++i
)
522 m_codeBlock
->addFunctionDecl(makeFunction(functionStack
[i
]));
524 const DeclarationStacks::VarStack
& varStack
= evalNode
->varStack();
525 unsigned numVariables
= varStack
.size();
526 Vector
<Identifier
, 0, UnsafeVectorOverflow
> variables
;
527 variables
.reserveCapacity(numVariables
);
528 for (size_t i
= 0; i
< numVariables
; ++i
) {
529 ASSERT(varStack
[i
].first
.impl()->isAtomic() || varStack
[i
].first
.impl()->isSymbol());
530 variables
.append(varStack
[i
].first
);
532 codeBlock
->adoptVariables(variables
);
535 BytecodeGenerator::~BytecodeGenerator()
539 RegisterID
* BytecodeGenerator::initializeNextParameter()
541 VirtualRegister reg
= virtualRegisterForArgument(m_codeBlock
->numParameters());
542 RegisterID
& parameter
= registerFor(reg
);
543 parameter
.setIndex(reg
.offset());
544 m_codeBlock
->addParameter();
548 UniquedStringImpl
* BytecodeGenerator::visibleNameForParameter(DestructuringPatternNode
* pattern
)
550 if (pattern
->isBindingNode()) {
551 const Identifier
& ident
= static_cast<const BindingNode
*>(pattern
)->boundProperty();
552 if (!m_functions
.contains(ident
.impl()))
558 RegisterID
* BytecodeGenerator::newRegister()
560 m_calleeRegisters
.append(virtualRegisterForLocal(m_calleeRegisters
.size()));
561 int numCalleeRegisters
= max
<int>(m_codeBlock
->m_numCalleeRegisters
, m_calleeRegisters
.size());
562 numCalleeRegisters
= WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numCalleeRegisters
);
563 m_codeBlock
->m_numCalleeRegisters
= numCalleeRegisters
;
564 return &m_calleeRegisters
.last();
567 RegisterID
* BytecodeGenerator::newTemporary()
569 // Reclaim free register IDs.
570 while (m_calleeRegisters
.size() && !m_calleeRegisters
.last().refCount())
571 m_calleeRegisters
.removeLast();
573 RegisterID
* result
= newRegister();
574 result
->setTemporary();
578 LabelScopePtr
BytecodeGenerator::newLabelScope(LabelScope::Type type
, const Identifier
* name
)
580 // Reclaim free label scopes.
581 while (m_labelScopes
.size() && !m_labelScopes
.last().refCount())
582 m_labelScopes
.removeLast();
584 // Allocate new label scope.
585 LabelScope
scope(type
, name
, scopeDepth(), newLabel(), type
== LabelScope::Loop
? newLabel() : PassRefPtr
<Label
>()); // Only loops have continue targets.
586 m_labelScopes
.append(scope
);
587 return LabelScopePtr(m_labelScopes
, m_labelScopes
.size() - 1);
590 PassRefPtr
<Label
> BytecodeGenerator::newLabel()
592 // Reclaim free label IDs.
593 while (m_labels
.size() && !m_labels
.last().refCount())
594 m_labels
.removeLast();
596 // Allocate new label ID.
597 m_labels
.append(*this);
598 return &m_labels
.last();
601 PassRefPtr
<Label
> BytecodeGenerator::emitLabel(Label
* l0
)
603 unsigned newLabelIndex
= instructions().size();
604 l0
->setLocation(newLabelIndex
);
606 if (m_codeBlock
->numberOfJumpTargets()) {
607 unsigned lastLabelIndex
= m_codeBlock
->lastJumpTarget();
608 ASSERT(lastLabelIndex
<= newLabelIndex
);
609 if (newLabelIndex
== lastLabelIndex
) {
610 // Peephole optimizations have already been disabled by emitting the last label
615 m_codeBlock
->addJumpTarget(newLabelIndex
);
617 // This disables peephole optimizations when an instruction is a jump target
618 m_lastOpcodeID
= op_end
;
622 void BytecodeGenerator::emitOpcode(OpcodeID opcodeID
)
625 size_t opcodePosition
= instructions().size();
626 ASSERT(opcodePosition
- m_lastOpcodePosition
== opcodeLength(m_lastOpcodeID
) || m_lastOpcodeID
== op_end
);
627 m_lastOpcodePosition
= opcodePosition
;
629 instructions().append(opcodeID
);
630 m_lastOpcodeID
= opcodeID
;
633 UnlinkedArrayProfile
BytecodeGenerator::newArrayProfile()
635 return m_codeBlock
->addArrayProfile();
638 UnlinkedArrayAllocationProfile
BytecodeGenerator::newArrayAllocationProfile()
640 return m_codeBlock
->addArrayAllocationProfile();
643 UnlinkedObjectAllocationProfile
BytecodeGenerator::newObjectAllocationProfile()
645 return m_codeBlock
->addObjectAllocationProfile();
648 UnlinkedValueProfile
BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID
)
650 UnlinkedValueProfile result
= m_codeBlock
->addValueProfile();
651 emitOpcode(opcodeID
);
655 void BytecodeGenerator::emitLoopHint()
657 emitOpcode(op_loop_hint
);
660 void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex
, int& src1Index
, int& src2Index
)
662 ASSERT(instructions().size() >= 4);
663 size_t size
= instructions().size();
664 dstIndex
= instructions().at(size
- 3).u
.operand
;
665 src1Index
= instructions().at(size
- 2).u
.operand
;
666 src2Index
= instructions().at(size
- 1).u
.operand
;
669 void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex
, int& srcIndex
)
671 ASSERT(instructions().size() >= 3);
672 size_t size
= instructions().size();
673 dstIndex
= instructions().at(size
- 2).u
.operand
;
674 srcIndex
= instructions().at(size
- 1).u
.operand
;
677 void ALWAYS_INLINE
BytecodeGenerator::rewindBinaryOp()
679 ASSERT(instructions().size() >= 4);
680 instructions().shrink(instructions().size() - 4);
681 m_lastOpcodeID
= op_end
;
684 void ALWAYS_INLINE
BytecodeGenerator::rewindUnaryOp()
686 ASSERT(instructions().size() >= 3);
687 instructions().shrink(instructions().size() - 3);
688 m_lastOpcodeID
= op_end
;
691 PassRefPtr
<Label
> BytecodeGenerator::emitJump(Label
* target
)
693 size_t begin
= instructions().size();
695 instructions().append(target
->bind(begin
, instructions().size()));
699 PassRefPtr
<Label
> BytecodeGenerator::emitJumpIfTrue(RegisterID
* cond
, Label
* target
)
701 if (m_lastOpcodeID
== op_less
) {
706 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
708 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
711 size_t begin
= instructions().size();
712 emitOpcode(op_jless
);
713 instructions().append(src1Index
);
714 instructions().append(src2Index
);
715 instructions().append(target
->bind(begin
, instructions().size()));
718 } else if (m_lastOpcodeID
== op_lesseq
) {
723 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
725 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
728 size_t begin
= instructions().size();
729 emitOpcode(op_jlesseq
);
730 instructions().append(src1Index
);
731 instructions().append(src2Index
);
732 instructions().append(target
->bind(begin
, instructions().size()));
735 } else if (m_lastOpcodeID
== op_greater
) {
740 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
742 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
745 size_t begin
= instructions().size();
746 emitOpcode(op_jgreater
);
747 instructions().append(src1Index
);
748 instructions().append(src2Index
);
749 instructions().append(target
->bind(begin
, instructions().size()));
752 } else if (m_lastOpcodeID
== op_greatereq
) {
757 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
759 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
762 size_t begin
= instructions().size();
763 emitOpcode(op_jgreatereq
);
764 instructions().append(src1Index
);
765 instructions().append(src2Index
);
766 instructions().append(target
->bind(begin
, instructions().size()));
769 } else if (m_lastOpcodeID
== op_eq_null
&& target
->isForward()) {
773 retrieveLastUnaryOp(dstIndex
, srcIndex
);
775 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
778 size_t begin
= instructions().size();
779 emitOpcode(op_jeq_null
);
780 instructions().append(srcIndex
);
781 instructions().append(target
->bind(begin
, instructions().size()));
784 } else if (m_lastOpcodeID
== op_neq_null
&& target
->isForward()) {
788 retrieveLastUnaryOp(dstIndex
, srcIndex
);
790 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
793 size_t begin
= instructions().size();
794 emitOpcode(op_jneq_null
);
795 instructions().append(srcIndex
);
796 instructions().append(target
->bind(begin
, instructions().size()));
801 size_t begin
= instructions().size();
803 emitOpcode(op_jtrue
);
804 instructions().append(cond
->index());
805 instructions().append(target
->bind(begin
, instructions().size()));
809 PassRefPtr
<Label
> BytecodeGenerator::emitJumpIfFalse(RegisterID
* cond
, Label
* target
)
811 if (m_lastOpcodeID
== op_less
&& target
->isForward()) {
816 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
818 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
821 size_t begin
= instructions().size();
822 emitOpcode(op_jnless
);
823 instructions().append(src1Index
);
824 instructions().append(src2Index
);
825 instructions().append(target
->bind(begin
, instructions().size()));
828 } else if (m_lastOpcodeID
== op_lesseq
&& target
->isForward()) {
833 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
835 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
838 size_t begin
= instructions().size();
839 emitOpcode(op_jnlesseq
);
840 instructions().append(src1Index
);
841 instructions().append(src2Index
);
842 instructions().append(target
->bind(begin
, instructions().size()));
845 } else if (m_lastOpcodeID
== op_greater
&& target
->isForward()) {
850 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
852 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
855 size_t begin
= instructions().size();
856 emitOpcode(op_jngreater
);
857 instructions().append(src1Index
);
858 instructions().append(src2Index
);
859 instructions().append(target
->bind(begin
, instructions().size()));
862 } else if (m_lastOpcodeID
== op_greatereq
&& target
->isForward()) {
867 retrieveLastBinaryOp(dstIndex
, src1Index
, src2Index
);
869 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
872 size_t begin
= instructions().size();
873 emitOpcode(op_jngreatereq
);
874 instructions().append(src1Index
);
875 instructions().append(src2Index
);
876 instructions().append(target
->bind(begin
, instructions().size()));
879 } else if (m_lastOpcodeID
== op_not
) {
883 retrieveLastUnaryOp(dstIndex
, srcIndex
);
885 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
888 size_t begin
= instructions().size();
889 emitOpcode(op_jtrue
);
890 instructions().append(srcIndex
);
891 instructions().append(target
->bind(begin
, instructions().size()));
894 } else if (m_lastOpcodeID
== op_eq_null
&& target
->isForward()) {
898 retrieveLastUnaryOp(dstIndex
, srcIndex
);
900 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
903 size_t begin
= instructions().size();
904 emitOpcode(op_jneq_null
);
905 instructions().append(srcIndex
);
906 instructions().append(target
->bind(begin
, instructions().size()));
909 } else if (m_lastOpcodeID
== op_neq_null
&& target
->isForward()) {
913 retrieveLastUnaryOp(dstIndex
, srcIndex
);
915 if (cond
->index() == dstIndex
&& cond
->isTemporary() && !cond
->refCount()) {
918 size_t begin
= instructions().size();
919 emitOpcode(op_jeq_null
);
920 instructions().append(srcIndex
);
921 instructions().append(target
->bind(begin
, instructions().size()));
926 size_t begin
= instructions().size();
927 emitOpcode(op_jfalse
);
928 instructions().append(cond
->index());
929 instructions().append(target
->bind(begin
, instructions().size()));
933 PassRefPtr
<Label
> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID
* cond
, Label
* target
)
935 size_t begin
= instructions().size();
937 emitOpcode(op_jneq_ptr
);
938 instructions().append(cond
->index());
939 instructions().append(Special::CallFunction
);
940 instructions().append(target
->bind(begin
, instructions().size()));
944 PassRefPtr
<Label
> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID
* cond
, Label
* target
)
946 size_t begin
= instructions().size();
948 emitOpcode(op_jneq_ptr
);
949 instructions().append(cond
->index());
950 instructions().append(Special::ApplyFunction
);
951 instructions().append(target
->bind(begin
, instructions().size()));
955 bool BytecodeGenerator::hasConstant(const Identifier
& ident
) const
957 UniquedStringImpl
* rep
= ident
.impl();
958 return m_identifierMap
.contains(rep
);
961 unsigned BytecodeGenerator::addConstant(const Identifier
& ident
)
963 UniquedStringImpl
* rep
= ident
.impl();
964 IdentifierMap::AddResult result
= m_identifierMap
.add(rep
, m_codeBlock
->numberOfIdentifiers());
965 if (result
.isNewEntry
)
966 m_codeBlock
->addIdentifier(ident
);
968 return result
.iterator
->value
;
971 // We can't hash JSValue(), so we use a dedicated data member to cache it.
972 RegisterID
* BytecodeGenerator::addConstantEmptyValue()
974 if (!m_emptyValueRegister
) {
975 int index
= m_nextConstantOffset
;
976 m_constantPoolRegisters
.append(FirstConstantRegisterIndex
+ m_nextConstantOffset
);
977 ++m_nextConstantOffset
;
978 m_codeBlock
->addConstant(JSValue());
979 m_emptyValueRegister
= &m_constantPoolRegisters
[index
];
982 return m_emptyValueRegister
;
985 RegisterID
* BytecodeGenerator::addConstantValue(JSValue v
, SourceCodeRepresentation sourceCodeRepresentation
)
988 return addConstantEmptyValue();
990 int index
= m_nextConstantOffset
;
992 EncodedJSValueWithRepresentation valueMapKey
{ JSValue::encode(v
), sourceCodeRepresentation
};
993 JSValueMap::AddResult result
= m_jsValueMap
.add(valueMapKey
, m_nextConstantOffset
);
994 if (result
.isNewEntry
) {
995 m_constantPoolRegisters
.append(FirstConstantRegisterIndex
+ m_nextConstantOffset
);
996 ++m_nextConstantOffset
;
997 m_codeBlock
->addConstant(v
, sourceCodeRepresentation
);
999 index
= result
.iterator
->value
;
1000 return &m_constantPoolRegisters
[index
];
1003 RegisterID
* BytecodeGenerator::emitMoveLinkTimeConstant(RegisterID
* dst
, LinkTimeConstant type
)
1005 unsigned constantIndex
= static_cast<unsigned>(type
);
1006 if (!m_linkTimeConstantRegisters
[constantIndex
]) {
1007 int index
= m_nextConstantOffset
;
1008 m_constantPoolRegisters
.append(FirstConstantRegisterIndex
+ m_nextConstantOffset
);
1009 ++m_nextConstantOffset
;
1010 m_codeBlock
->addConstant(type
);
1011 m_linkTimeConstantRegisters
[constantIndex
] = &m_constantPoolRegisters
[index
];
1015 instructions().append(dst
->index());
1016 instructions().append(m_linkTimeConstantRegisters
[constantIndex
]->index());
1021 unsigned BytecodeGenerator::addRegExp(RegExp
* r
)
1023 return m_codeBlock
->addRegExp(r
);
1026 RegisterID
* BytecodeGenerator::emitMoveEmptyValue(RegisterID
* dst
)
1028 RefPtr
<RegisterID
> emptyValue
= addConstantEmptyValue();
1031 instructions().append(dst
->index());
1032 instructions().append(emptyValue
->index());
1036 RegisterID
* BytecodeGenerator::emitMove(RegisterID
* dst
, RegisterID
* src
)
1038 ASSERT(src
!= m_emptyValueRegister
);
1040 m_staticPropertyAnalyzer
.mov(dst
->index(), src
->index());
1042 instructions().append(dst
->index());
1043 instructions().append(src
->index());
1045 if (!dst
->isTemporary() && vm()->typeProfiler())
1046 emitProfileType(dst
, ProfileTypeBytecodeHasGlobalID
, nullptr);
1051 RegisterID
* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID
, RegisterID
* dst
, RegisterID
* src
)
1053 emitOpcode(opcodeID
);
1054 instructions().append(dst
->index());
1055 instructions().append(src
->index());
1059 RegisterID
* BytecodeGenerator::emitInc(RegisterID
* srcDst
)
1062 instructions().append(srcDst
->index());
1066 RegisterID
* BytecodeGenerator::emitDec(RegisterID
* srcDst
)
1069 instructions().append(srcDst
->index());
1073 RegisterID
* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID
, RegisterID
* dst
, RegisterID
* src1
, RegisterID
* src2
, OperandTypes types
)
1075 emitOpcode(opcodeID
);
1076 instructions().append(dst
->index());
1077 instructions().append(src1
->index());
1078 instructions().append(src2
->index());
1080 if (opcodeID
== op_bitor
|| opcodeID
== op_bitand
|| opcodeID
== op_bitxor
||
1081 opcodeID
== op_add
|| opcodeID
== op_mul
|| opcodeID
== op_sub
|| opcodeID
== op_div
)
1082 instructions().append(types
.toInt());
1087 RegisterID
* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID
, RegisterID
* dst
, RegisterID
* src1
, RegisterID
* src2
)
1089 if (m_lastOpcodeID
== op_typeof
) {
1093 retrieveLastUnaryOp(dstIndex
, srcIndex
);
1095 if (src1
->index() == dstIndex
1096 && src1
->isTemporary()
1097 && m_codeBlock
->isConstantRegisterIndex(src2
->index())
1098 && m_codeBlock
->constantRegister(src2
->index()).get().isString()) {
1099 const String
& value
= asString(m_codeBlock
->constantRegister(src2
->index()).get())->tryGetValue();
1100 if (value
== "undefined") {
1102 emitOpcode(op_is_undefined
);
1103 instructions().append(dst
->index());
1104 instructions().append(srcIndex
);
1107 if (value
== "boolean") {
1109 emitOpcode(op_is_boolean
);
1110 instructions().append(dst
->index());
1111 instructions().append(srcIndex
);
1114 if (value
== "number") {
1116 emitOpcode(op_is_number
);
1117 instructions().append(dst
->index());
1118 instructions().append(srcIndex
);
1121 if (value
== "string") {
1123 emitOpcode(op_is_string
);
1124 instructions().append(dst
->index());
1125 instructions().append(srcIndex
);
1128 if (value
== "object") {
1130 emitOpcode(op_is_object_or_null
);
1131 instructions().append(dst
->index());
1132 instructions().append(srcIndex
);
1135 if (value
== "function") {
1137 emitOpcode(op_is_function
);
1138 instructions().append(dst
->index());
1139 instructions().append(srcIndex
);
1145 emitOpcode(opcodeID
);
1146 instructions().append(dst
->index());
1147 instructions().append(src1
->index());
1148 instructions().append(src2
->index());
1152 void BytecodeGenerator::emitTypeProfilerExpressionInfo(const JSTextPosition
& startDivot
, const JSTextPosition
& endDivot
)
1154 unsigned start
= startDivot
.offset
; // Ranges are inclusive of their endpoints, AND 0 indexed.
1155 unsigned end
= endDivot
.offset
- 1; // End Ranges already go one past the inclusive range, so subtract 1.
1156 unsigned instructionOffset
= instructions().size() - 1;
1157 m_codeBlock
->addTypeProfilerExpressionInfo(instructionOffset
, start
, end
);
1160 void BytecodeGenerator::emitProfileType(RegisterID
* registerToProfile
, ProfileTypeBytecodeFlag flag
, const Identifier
* identifier
)
1162 if (flag
== ProfileTypeBytecodeGetFromScope
|| flag
== ProfileTypeBytecodePutToScope
)
1163 RELEASE_ASSERT(identifier
);
1165 // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
1166 emitOpcode(op_profile_type
);
1167 instructions().append(registerToProfile
->index());
1168 instructions().append(0);
1169 instructions().append(flag
);
1170 instructions().append(identifier
? addConstant(*identifier
) : 0);
1171 instructions().append(resolveType());
1174 void BytecodeGenerator::emitProfileControlFlow(int textOffset
)
1176 if (vm()->controlFlowProfiler()) {
1177 RELEASE_ASSERT(textOffset
>= 0);
1178 size_t bytecodeOffset
= instructions().size();
1179 m_codeBlock
->addOpProfileControlFlowBytecodeOffset(bytecodeOffset
);
1181 emitOpcode(op_profile_control_flow
);
1182 instructions().append(textOffset
);
1186 RegisterID
* BytecodeGenerator::emitLoad(RegisterID
* dst
, bool b
)
1188 return emitLoad(dst
, jsBoolean(b
));
1191 RegisterID
* BytecodeGenerator::emitLoad(RegisterID
* dst
, const Identifier
& identifier
)
1193 JSString
*& stringInMap
= m_stringMap
.add(identifier
.impl(), nullptr).iterator
->value
;
1195 stringInMap
= jsOwnedString(vm(), identifier
.string());
1196 return emitLoad(dst
, JSValue(stringInMap
));
1199 RegisterID
* BytecodeGenerator::emitLoad(RegisterID
* dst
, JSValue v
, SourceCodeRepresentation sourceCodeRepresentation
)
1201 RegisterID
* constantID
= addConstantValue(v
, sourceCodeRepresentation
);
1203 return emitMove(dst
, constantID
);
1207 RegisterID
* BytecodeGenerator::emitLoadGlobalObject(RegisterID
* dst
)
1209 if (!m_globalObjectRegister
) {
1210 int index
= m_nextConstantOffset
;
1211 m_constantPoolRegisters
.append(FirstConstantRegisterIndex
+ m_nextConstantOffset
);
1212 ++m_nextConstantOffset
;
1213 m_codeBlock
->addConstant(JSValue());
1214 m_globalObjectRegister
= &m_constantPoolRegisters
[index
];
1215 m_codeBlock
->setGlobalObjectRegister(VirtualRegister(index
));
1218 emitMove(dst
, m_globalObjectRegister
);
1219 return m_globalObjectRegister
;
1222 Variable
BytecodeGenerator::variable(const Identifier
& property
)
1224 if (property
== propertyNames().thisIdentifier
) {
1226 property
, VarOffset(thisRegister()->virtualRegister()), thisRegister(),
1227 ReadOnly
, Variable::SpecialVariable
);
1230 if (!shouldOptimizeLocals())
1231 return Variable(property
);
1233 SymbolTableEntry entry
= symbolTable().get(property
.impl());
1235 return Variable(property
);
1237 if (entry
.varOffset().isScope() && m_localScopeDepth
) {
1238 // FIXME: We should be able to statically resolve through our local scopes.
1239 // https://bugs.webkit.org/show_bug.cgi?id=141885
1240 return Variable(property
);
1243 return variableForLocalEntry(property
, entry
);
1246 Variable
BytecodeGenerator::variablePerSymbolTable(const Identifier
& property
)
1248 SymbolTableEntry entry
= symbolTable().get(property
.impl());
1250 return Variable(property
);
1252 return variableForLocalEntry(property
, entry
);
1255 Variable
BytecodeGenerator::variableForLocalEntry(
1256 const Identifier
& property
, const SymbolTableEntry
& entry
)
1258 VarOffset offset
= entry
.varOffset();
1261 if (offset
.isStack())
1262 local
= ®isterFor(offset
.stackOffset());
1266 return Variable(property
, offset
, local
, entry
.getAttributes(), Variable::NormalVariable
);
1269 void BytecodeGenerator::createVariable(
1270 const Identifier
& property
, VarKind varKind
, ConstantMode constantMode
,
1271 ExistingVariableMode existingVariableMode
)
1273 ASSERT(property
!= propertyNames().thisIdentifier
);
1275 ConcurrentJITLocker
locker(symbolTable().m_lock
);
1276 SymbolTableEntry entry
= symbolTable().get(locker
, property
.impl());
1278 if (!entry
.isNull()) {
1279 if (existingVariableMode
== IgnoreExisting
)
1282 // Do some checks to ensure that the variable we're being asked to create is sufficiently
1283 // compatible with the one we have already created.
1285 VarOffset offset
= entry
.varOffset();
1287 // We can't change our minds about whether it's captured.
1288 if (offset
.kind() != varKind
|| constantMode
!= entry
.constantMode()) {
1290 "Trying to add variable called ", property
, " as ", varKind
, "/", constantMode
,
1291 " but it was already added as ", offset
, "/", entry
.constantMode(), ".\n");
1292 RELEASE_ASSERT_NOT_REACHED();
1298 VarOffset varOffset
;
1299 if (varKind
== VarKind::Scope
)
1300 varOffset
= VarOffset(symbolTable().takeNextScopeOffset(locker
));
1302 ASSERT(varKind
== VarKind::Stack
);
1303 varOffset
= VarOffset(virtualRegisterForLocal(m_calleeRegisters
.size()));
1305 SymbolTableEntry
newEntry(varOffset
, constantMode
== IsConstant
? ReadOnly
: 0);
1306 symbolTable().add(locker
, property
.impl(), newEntry
);
1308 if (varKind
== VarKind::Stack
) {
1309 RegisterID
* local
= addVar();
1310 RELEASE_ASSERT(local
->index() == varOffset
.stackOffset().offset());
1314 void BytecodeGenerator::emitCheckHasInstance(RegisterID
* dst
, RegisterID
* value
, RegisterID
* base
, Label
* target
)
1316 size_t begin
= instructions().size();
1317 emitOpcode(op_check_has_instance
);
1318 instructions().append(dst
->index());
1319 instructions().append(value
->index());
1320 instructions().append(base
->index());
1321 instructions().append(target
->bind(begin
, instructions().size()));
1324 // Indicates the least upper bound of resolve type based on local scope. The bytecode linker
1325 // will start with this ResolveType and compute the least upper bound including intercepting scopes.
1326 ResolveType
BytecodeGenerator::resolveType()
1328 if (m_localScopeDepth
)
1330 if (m_symbolTable
&& m_symbolTable
->usesNonStrictEval())
1331 return GlobalPropertyWithVarInjectionChecks
;
1332 return GlobalProperty
;
1335 RegisterID
* BytecodeGenerator::emitResolveScope(RegisterID
* dst
, const Variable
& variable
)
1337 switch (variable
.offset().kind()) {
1338 case VarKind::Stack
:
1341 case VarKind::DirectArgument
:
1342 return argumentsRegister();
1344 case VarKind::Scope
:
1345 // This always refers to the activation that *we* allocated, and not the current scope that code
1346 // lives in. Note that this will change once we have proper support for block scoping. Once that
1347 // changes, it will be correct for this code to return scopeRegister(). The only reason why we
1348 // don't do that already is that m_lexicalEnvironment is required by ConstDeclNode. ConstDeclNode
1349 // requires weird things because it is a shameful pile of nonsense, but block scoping would make
1350 // that code sensible and obviate the need for us to do bad things.
1351 return m_lexicalEnvironmentRegister
;
1353 case VarKind::Invalid
:
1354 // Indicates non-local resolution.
1356 ASSERT(!m_symbolTable
|| !m_symbolTable
->contains(variable
.ident().impl()) || resolveType() == Dynamic
);
1358 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
1360 // resolve_scope dst, id, ResolveType, depth
1361 emitOpcode(op_resolve_scope
);
1362 dst
= tempDestination(dst
);
1363 instructions().append(kill(dst
));
1364 instructions().append(scopeRegister()->index());
1365 instructions().append(addConstant(variable
.ident()));
1366 instructions().append(resolveType());
1367 instructions().append(0);
1368 instructions().append(0);
1372 RELEASE_ASSERT_NOT_REACHED();
1376 RegisterID
* BytecodeGenerator::emitGetFromScope(RegisterID
* dst
, RegisterID
* scope
, const Variable
& variable
, ResolveMode resolveMode
)
1378 switch (variable
.offset().kind()) {
1379 case VarKind::Stack
:
1380 return emitMove(dst
, variable
.local());
1382 case VarKind::DirectArgument
: {
1383 UnlinkedValueProfile profile
= emitProfiledOpcode(op_get_from_arguments
);
1384 instructions().append(kill(dst
));
1385 instructions().append(scope
->index());
1386 instructions().append(variable
.offset().capturedArgumentsOffset().offset());
1387 instructions().append(profile
);
1391 case VarKind::Scope
:
1392 case VarKind::Invalid
: {
1393 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
1395 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
1396 UnlinkedValueProfile profile
= emitProfiledOpcode(op_get_from_scope
);
1397 instructions().append(kill(dst
));
1398 instructions().append(scope
->index());
1399 instructions().append(addConstant(variable
.ident()));
1400 instructions().append(ResolveModeAndType(resolveMode
, variable
.offset().isScope() ? LocalClosureVar
: resolveType()).operand());
1401 instructions().append(0);
1402 instructions().append(variable
.offset().isScope() ? variable
.offset().scopeOffset().offset() : 0);
1403 instructions().append(profile
);
1407 RELEASE_ASSERT_NOT_REACHED();
1410 RegisterID
* BytecodeGenerator::emitPutToScope(RegisterID
* scope
, const Variable
& variable
, RegisterID
* value
, ResolveMode resolveMode
)
1412 switch (variable
.offset().kind()) {
1413 case VarKind::Stack
:
1414 emitMove(variable
.local(), value
);
1417 case VarKind::DirectArgument
:
1418 emitOpcode(op_put_to_arguments
);
1419 instructions().append(scope
->index());
1420 instructions().append(variable
.offset().capturedArgumentsOffset().offset());
1421 instructions().append(value
->index());
1424 case VarKind::Scope
:
1425 case VarKind::Invalid
: {
1426 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
1428 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
1429 emitOpcode(op_put_to_scope
);
1430 instructions().append(scope
->index());
1431 instructions().append(addConstant(variable
.ident()));
1432 instructions().append(value
->index());
1434 if (variable
.offset().isScope()) {
1435 offset
= variable
.offset().scopeOffset();
1436 instructions().append(ResolveModeAndType(resolveMode
, LocalClosureVar
).operand());
1438 ASSERT(resolveType() != LocalClosureVar
);
1439 instructions().append(ResolveModeAndType(resolveMode
, resolveType()).operand());
1441 instructions().append(0);
1442 instructions().append(!!offset
? offset
.offset() : 0);
1446 RELEASE_ASSERT_NOT_REACHED();
1449 RegisterID
* BytecodeGenerator::initializeVariable(const Variable
& variable
, RegisterID
* value
)
1452 switch (variable
.offset().kind()) {
1453 case VarKind::Stack
:
1457 case VarKind::DirectArgument
:
1458 scope
= argumentsRegister();
1461 case VarKind::Scope
:
1462 scope
= scopeRegister();
1467 RELEASE_ASSERT_NOT_REACHED();
1471 return emitPutToScope(scope
, variable
, value
, ThrowIfNotFound
);
1474 RegisterID
* BytecodeGenerator::emitInstanceOf(RegisterID
* dst
, RegisterID
* value
, RegisterID
* basePrototype
)
1476 emitOpcode(op_instanceof
);
1477 instructions().append(dst
->index());
1478 instructions().append(value
->index());
1479 instructions().append(basePrototype
->index());
1483 RegisterID
* BytecodeGenerator::emitInitGlobalConst(const Identifier
& identifier
, RegisterID
* value
)
1485 ASSERT(m_codeType
== GlobalCode
);
1486 emitOpcode(op_init_global_const_nop
);
1487 instructions().append(0);
1488 instructions().append(value
->index());
1489 instructions().append(0);
1490 instructions().append(addConstant(identifier
));
1494 RegisterID
* BytecodeGenerator::emitGetById(RegisterID
* dst
, RegisterID
* base
, const Identifier
& property
)
1496 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
1498 UnlinkedValueProfile profile
= emitProfiledOpcode(op_get_by_id
);
1499 instructions().append(kill(dst
));
1500 instructions().append(base
->index());
1501 instructions().append(addConstant(property
));
1502 instructions().append(0);
1503 instructions().append(0);
1504 instructions().append(0);
1505 instructions().append(0);
1506 instructions().append(profile
);
1510 RegisterID
* BytecodeGenerator::emitPutById(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
)
1512 unsigned propertyIndex
= addConstant(property
);
1514 m_staticPropertyAnalyzer
.putById(base
->index(), propertyIndex
);
1516 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
1518 emitOpcode(op_put_by_id
);
1519 instructions().append(base
->index());
1520 instructions().append(propertyIndex
);
1521 instructions().append(value
->index());
1522 instructions().append(0);
1523 instructions().append(0);
1524 instructions().append(0);
1525 instructions().append(0);
1526 instructions().append(0);
1531 RegisterID
* BytecodeGenerator::emitDirectPutById(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
, PropertyNode::PutType putType
)
1533 ASSERT(!parseIndex(property
));
1534 unsigned propertyIndex
= addConstant(property
);
1536 m_staticPropertyAnalyzer
.putById(base
->index(), propertyIndex
);
1538 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
1540 emitOpcode(op_put_by_id
);
1541 instructions().append(base
->index());
1542 instructions().append(propertyIndex
);
1543 instructions().append(value
->index());
1544 instructions().append(0);
1545 instructions().append(0);
1546 instructions().append(0);
1547 instructions().append(0);
1548 instructions().append(putType
== PropertyNode::KnownDirect
|| property
!= m_vm
->propertyNames
->underscoreProto
);
1552 void BytecodeGenerator::emitPutGetterById(RegisterID
* base
, const Identifier
& property
, RegisterID
* getter
)
1554 unsigned propertyIndex
= addConstant(property
);
1555 m_staticPropertyAnalyzer
.putById(base
->index(), propertyIndex
);
1557 emitOpcode(op_put_getter_by_id
);
1558 instructions().append(base
->index());
1559 instructions().append(propertyIndex
);
1560 instructions().append(getter
->index());
1563 void BytecodeGenerator::emitPutSetterById(RegisterID
* base
, const Identifier
& property
, RegisterID
* setter
)
1565 unsigned propertyIndex
= addConstant(property
);
1566 m_staticPropertyAnalyzer
.putById(base
->index(), propertyIndex
);
1568 emitOpcode(op_put_setter_by_id
);
1569 instructions().append(base
->index());
1570 instructions().append(propertyIndex
);
1571 instructions().append(setter
->index());
1574 void BytecodeGenerator::emitPutGetterSetter(RegisterID
* base
, const Identifier
& property
, RegisterID
* getter
, RegisterID
* setter
)
1576 unsigned propertyIndex
= addConstant(property
);
1578 m_staticPropertyAnalyzer
.putById(base
->index(), propertyIndex
);
1580 emitOpcode(op_put_getter_setter
);
1581 instructions().append(base
->index());
1582 instructions().append(propertyIndex
);
1583 instructions().append(getter
->index());
1584 instructions().append(setter
->index());
1587 RegisterID
* BytecodeGenerator::emitDeleteById(RegisterID
* dst
, RegisterID
* base
, const Identifier
& property
)
1589 emitOpcode(op_del_by_id
);
1590 instructions().append(dst
->index());
1591 instructions().append(base
->index());
1592 instructions().append(addConstant(property
));
1596 RegisterID
* BytecodeGenerator::emitGetByVal(RegisterID
* dst
, RegisterID
* base
, RegisterID
* property
)
1598 for (size_t i
= m_forInContextStack
.size(); i
> 0; i
--) {
1599 ForInContext
* context
= m_forInContextStack
[i
- 1].get();
1600 if (context
->local() != property
)
1603 if (!context
->isValid())
1606 if (context
->type() == ForInContext::IndexedForInContextType
) {
1607 property
= static_cast<IndexedForInContext
*>(context
)->index();
1611 ASSERT(context
->type() == ForInContext::StructureForInContextType
);
1612 StructureForInContext
* structureContext
= static_cast<StructureForInContext
*>(context
);
1613 UnlinkedValueProfile profile
= emitProfiledOpcode(op_get_direct_pname
);
1614 instructions().append(kill(dst
));
1615 instructions().append(base
->index());
1616 instructions().append(property
->index());
1617 instructions().append(structureContext
->index()->index());
1618 instructions().append(structureContext
->enumerator()->index());
1619 instructions().append(profile
);
1623 UnlinkedArrayProfile arrayProfile
= newArrayProfile();
1624 UnlinkedValueProfile profile
= emitProfiledOpcode(op_get_by_val
);
1625 instructions().append(kill(dst
));
1626 instructions().append(base
->index());
1627 instructions().append(property
->index());
1628 instructions().append(arrayProfile
);
1629 instructions().append(profile
);
1633 RegisterID
* BytecodeGenerator::emitPutByVal(RegisterID
* base
, RegisterID
* property
, RegisterID
* value
)
1635 UnlinkedArrayProfile arrayProfile
= newArrayProfile();
1636 emitOpcode(op_put_by_val
);
1637 instructions().append(base
->index());
1638 instructions().append(property
->index());
1639 instructions().append(value
->index());
1640 instructions().append(arrayProfile
);
1645 RegisterID
* BytecodeGenerator::emitDirectPutByVal(RegisterID
* base
, RegisterID
* property
, RegisterID
* value
)
1647 UnlinkedArrayProfile arrayProfile
= newArrayProfile();
1648 emitOpcode(op_put_by_val_direct
);
1649 instructions().append(base
->index());
1650 instructions().append(property
->index());
1651 instructions().append(value
->index());
1652 instructions().append(arrayProfile
);
1656 RegisterID
* BytecodeGenerator::emitDeleteByVal(RegisterID
* dst
, RegisterID
* base
, RegisterID
* property
)
1658 emitOpcode(op_del_by_val
);
1659 instructions().append(dst
->index());
1660 instructions().append(base
->index());
1661 instructions().append(property
->index());
1665 RegisterID
* BytecodeGenerator::emitPutByIndex(RegisterID
* base
, unsigned index
, RegisterID
* value
)
1667 emitOpcode(op_put_by_index
);
1668 instructions().append(base
->index());
1669 instructions().append(index
);
1670 instructions().append(value
->index());
1674 RegisterID
* BytecodeGenerator::emitCreateThis(RegisterID
* dst
)
1676 size_t begin
= instructions().size();
1677 m_staticPropertyAnalyzer
.createThis(m_thisRegister
.index(), begin
+ 3);
1679 m_codeBlock
->addPropertyAccessInstruction(instructions().size());
1680 emitOpcode(op_create_this
);
1681 instructions().append(m_thisRegister
.index());
1682 instructions().append(m_thisRegister
.index());
1683 instructions().append(0);
1684 instructions().append(0);
1688 void BytecodeGenerator::emitTDZCheck(RegisterID
* target
)
1690 emitOpcode(op_check_tdz
);
1691 instructions().append(target
->index());
1694 RegisterID
* BytecodeGenerator::emitNewObject(RegisterID
* dst
)
1696 size_t begin
= instructions().size();
1697 m_staticPropertyAnalyzer
.newObject(dst
->index(), begin
+ 2);
1699 emitOpcode(op_new_object
);
1700 instructions().append(dst
->index());
1701 instructions().append(0);
1702 instructions().append(newObjectAllocationProfile());
1706 unsigned BytecodeGenerator::addConstantBuffer(unsigned length
)
1708 return m_codeBlock
->addConstantBuffer(length
);
1711 JSString
* BytecodeGenerator::addStringConstant(const Identifier
& identifier
)
1713 JSString
*& stringInMap
= m_stringMap
.add(identifier
.impl(), nullptr).iterator
->value
;
1715 stringInMap
= jsString(vm(), identifier
.string());
1716 addConstantValue(stringInMap
);
1721 JSTemplateRegistryKey
* BytecodeGenerator::addTemplateRegistryKeyConstant(const TemplateRegistryKey
& templateRegistryKey
)
1723 JSTemplateRegistryKey
*& templateRegistryKeyInMap
= m_templateRegistryKeyMap
.add(templateRegistryKey
, nullptr).iterator
->value
;
1724 if (!templateRegistryKeyInMap
) {
1725 templateRegistryKeyInMap
= JSTemplateRegistryKey::create(*vm(), templateRegistryKey
);
1726 addConstantValue(templateRegistryKeyInMap
);
1728 return templateRegistryKeyInMap
;
1731 RegisterID
* BytecodeGenerator::emitNewArray(RegisterID
* dst
, ElementNode
* elements
, unsigned length
)
1733 #if !ASSERT_DISABLED
1734 unsigned checkLength
= 0;
1736 bool hadVariableExpression
= false;
1738 for (ElementNode
* n
= elements
; n
; n
= n
->next()) {
1739 if (!n
->value()->isConstant()) {
1740 hadVariableExpression
= true;
1745 #if !ASSERT_DISABLED
1749 if (!hadVariableExpression
) {
1750 ASSERT(length
== checkLength
);
1751 unsigned constantBufferIndex
= addConstantBuffer(length
);
1752 JSValue
* constantBuffer
= m_codeBlock
->constantBuffer(constantBufferIndex
).data();
1754 for (ElementNode
* n
= elements
; index
< length
; n
= n
->next()) {
1755 ASSERT(n
->value()->isConstant());
1756 constantBuffer
[index
++] = static_cast<ConstantNode
*>(n
->value())->jsValue(*this);
1758 emitOpcode(op_new_array_buffer
);
1759 instructions().append(dst
->index());
1760 instructions().append(constantBufferIndex
);
1761 instructions().append(length
);
1762 instructions().append(newArrayAllocationProfile());
1767 Vector
<RefPtr
<RegisterID
>, 16, UnsafeVectorOverflow
> argv
;
1768 for (ElementNode
* n
= elements
; n
; n
= n
->next()) {
1772 ASSERT(!n
->value()->isSpreadExpression());
1773 argv
.append(newTemporary());
1774 // op_new_array requires the initial values to be a sequential range of registers
1775 ASSERT(argv
.size() == 1 || argv
[argv
.size() - 1]->index() == argv
[argv
.size() - 2]->index() - 1);
1776 emitNode(argv
.last().get(), n
->value());
1779 emitOpcode(op_new_array
);
1780 instructions().append(dst
->index());
1781 instructions().append(argv
.size() ? argv
[0]->index() : 0); // argv
1782 instructions().append(argv
.size()); // argc
1783 instructions().append(newArrayAllocationProfile());
1787 RegisterID
* BytecodeGenerator::emitNewFunction(RegisterID
* dst
, FunctionBodyNode
* function
)
1789 return emitNewFunctionInternal(dst
, m_codeBlock
->addFunctionDecl(makeFunction(function
)));
1792 RegisterID
* BytecodeGenerator::emitNewFunctionInternal(RegisterID
* dst
, unsigned index
)
1794 emitOpcode(op_new_func
);
1795 instructions().append(dst
->index());
1796 instructions().append(scopeRegister()->index());
1797 instructions().append(index
);
1801 RegisterID
* BytecodeGenerator::emitNewRegExp(RegisterID
* dst
, RegExp
* regExp
)
1803 emitOpcode(op_new_regexp
);
1804 instructions().append(dst
->index());
1805 instructions().append(addRegExp(regExp
));
1809 RegisterID
* BytecodeGenerator::emitNewFunctionExpression(RegisterID
* r0
, FuncExprNode
* n
)
1811 FunctionBodyNode
* function
= n
->body();
1812 unsigned index
= m_codeBlock
->addFunctionExpr(makeFunction(function
));
1814 emitOpcode(op_new_func_exp
);
1815 instructions().append(r0
->index());
1816 instructions().append(scopeRegister()->index());
1817 instructions().append(index
);
1821 RegisterID
* BytecodeGenerator::emitNewDefaultConstructor(RegisterID
* dst
, ConstructorKind constructorKind
, const Identifier
& name
)
1823 UnlinkedFunctionExecutable
* executable
= m_vm
->builtinExecutables()->createDefaultConstructor(constructorKind
, name
);
1825 unsigned index
= m_codeBlock
->addFunctionExpr(executable
);
1827 emitOpcode(op_new_func_exp
);
1828 instructions().append(dst
->index());
1829 instructions().append(scopeRegister()->index());
1830 instructions().append(index
);
1834 RegisterID
* BytecodeGenerator::emitCall(RegisterID
* dst
, RegisterID
* func
, ExpectedFunction expectedFunction
, CallArguments
& callArguments
, const JSTextPosition
& divot
, const JSTextPosition
& divotStart
, const JSTextPosition
& divotEnd
)
1836 return emitCall(op_call
, dst
, func
, expectedFunction
, callArguments
, divot
, divotStart
, divotEnd
);
1839 RegisterID
* BytecodeGenerator::emitCallEval(RegisterID
* dst
, RegisterID
* func
, CallArguments
& callArguments
, const JSTextPosition
& divot
, const JSTextPosition
& divotStart
, const JSTextPosition
& divotEnd
)
1841 return emitCall(op_call_eval
, dst
, func
, NoExpectedFunction
, callArguments
, divot
, divotStart
, divotEnd
);
1844 ExpectedFunction
BytecodeGenerator::expectedFunctionForIdentifier(const Identifier
& identifier
)
1846 if (identifier
== m_vm
->propertyNames
->Object
|| identifier
== m_vm
->propertyNames
->ObjectPrivateName
)
1847 return ExpectObjectConstructor
;
1848 if (identifier
== m_vm
->propertyNames
->Array
|| identifier
== m_vm
->propertyNames
->ArrayPrivateName
)
1849 return ExpectArrayConstructor
;
1850 return NoExpectedFunction
;
1853 ExpectedFunction
BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID
* dst
, RegisterID
* func
, ExpectedFunction expectedFunction
, CallArguments
& callArguments
, Label
* done
)
1855 RefPtr
<Label
> realCall
= newLabel();
1856 switch (expectedFunction
) {
1857 case ExpectObjectConstructor
: {
1858 // If the number of arguments is non-zero, then we can't do anything interesting.
1859 if (callArguments
.argumentCountIncludingThis() >= 2)
1860 return NoExpectedFunction
;
1862 size_t begin
= instructions().size();
1863 emitOpcode(op_jneq_ptr
);
1864 instructions().append(func
->index());
1865 instructions().append(Special::ObjectConstructor
);
1866 instructions().append(realCall
->bind(begin
, instructions().size()));
1868 if (dst
!= ignoredResult())
1873 case ExpectArrayConstructor
: {
1874 // If you're doing anything other than "new Array()" or "new Array(foo)" then we
1875 // don't do inline it, for now. The only reason is that call arguments are in
1876 // the opposite order of what op_new_array expects, so we'd either need to change
1877 // how op_new_array works or we'd need an op_new_array_reverse. Neither of these
1878 // things sounds like it's worth it.
1879 if (callArguments
.argumentCountIncludingThis() > 2)
1880 return NoExpectedFunction
;
1882 size_t begin
= instructions().size();
1883 emitOpcode(op_jneq_ptr
);
1884 instructions().append(func
->index());
1885 instructions().append(Special::ArrayConstructor
);
1886 instructions().append(realCall
->bind(begin
, instructions().size()));
1888 if (dst
!= ignoredResult()) {
1889 if (callArguments
.argumentCountIncludingThis() == 2) {
1890 emitOpcode(op_new_array_with_size
);
1891 instructions().append(dst
->index());
1892 instructions().append(callArguments
.argumentRegister(0)->index());
1893 instructions().append(newArrayAllocationProfile());
1895 ASSERT(callArguments
.argumentCountIncludingThis() == 1);
1896 emitOpcode(op_new_array
);
1897 instructions().append(dst
->index());
1898 instructions().append(0);
1899 instructions().append(0);
1900 instructions().append(newArrayAllocationProfile());
1907 ASSERT(expectedFunction
== NoExpectedFunction
);
1908 return NoExpectedFunction
;
1911 size_t begin
= instructions().size();
1913 instructions().append(done
->bind(begin
, instructions().size()));
1914 emitLabel(realCall
.get());
1916 return expectedFunction
;
1919 RegisterID
* BytecodeGenerator::emitCall(OpcodeID opcodeID
, RegisterID
* dst
, RegisterID
* func
, ExpectedFunction expectedFunction
, CallArguments
& callArguments
, const JSTextPosition
& divot
, const JSTextPosition
& divotStart
, const JSTextPosition
& divotEnd
)
1921 ASSERT(opcodeID
== op_call
|| opcodeID
== op_call_eval
);
1922 ASSERT(func
->refCount());
1924 if (m_shouldEmitProfileHooks
)
1925 emitMove(callArguments
.profileHookRegister(), func
);
1927 // Generate code for arguments.
1928 unsigned argument
= 0;
1929 if (callArguments
.argumentsNode()) {
1930 ArgumentListNode
* n
= callArguments
.argumentsNode()->m_listNode
;
1931 if (n
&& n
->m_expr
->isSpreadExpression()) {
1932 RELEASE_ASSERT(!n
->m_next
);
1933 auto expression
= static_cast<SpreadExpressionNode
*>(n
->m_expr
)->expression();
1934 RefPtr
<RegisterID
> argumentRegister
;
1935 argumentRegister
= expression
->emitBytecode(*this, callArguments
.argumentRegister(0));
1936 RefPtr
<RegisterID
> thisRegister
= emitMove(newTemporary(), callArguments
.thisRegister());
1937 return emitCallVarargs(dst
, func
, callArguments
.thisRegister(), argumentRegister
.get(), newTemporary(), 0, callArguments
.profileHookRegister(), divot
, divotStart
, divotEnd
);
1939 for (; n
; n
= n
->m_next
)
1940 emitNode(callArguments
.argumentRegister(argument
++), n
);
1943 // Reserve space for call frame.
1944 Vector
<RefPtr
<RegisterID
>, JSStack::CallFrameHeaderSize
, UnsafeVectorOverflow
> callFrame
;
1945 for (int i
= 0; i
< JSStack::CallFrameHeaderSize
; ++i
)
1946 callFrame
.append(newTemporary());
1948 if (m_shouldEmitProfileHooks
) {
1949 emitOpcode(op_profile_will_call
);
1950 instructions().append(callArguments
.profileHookRegister()->index());
1953 emitExpressionInfo(divot
, divotStart
, divotEnd
);
1955 RefPtr
<Label
> done
= newLabel();
1956 expectedFunction
= emitExpectedFunctionSnippet(dst
, func
, expectedFunction
, callArguments
, done
.get());
1959 UnlinkedArrayProfile arrayProfile
= newArrayProfile();
1960 UnlinkedValueProfile profile
= emitProfiledOpcode(opcodeID
);
1962 ASSERT(dst
!= ignoredResult());
1963 instructions().append(dst
->index());
1964 instructions().append(func
->index());
1965 instructions().append(callArguments
.argumentCountIncludingThis());
1966 instructions().append(callArguments
.stackOffset());
1967 instructions().append(m_codeBlock
->addLLIntCallLinkInfo());
1968 instructions().append(0);
1969 instructions().append(arrayProfile
);
1970 instructions().append(profile
);
1972 if (expectedFunction
!= NoExpectedFunction
)
1973 emitLabel(done
.get());
1975 if (m_shouldEmitProfileHooks
) {
1976 emitOpcode(op_profile_did_call
);
1977 instructions().append(callArguments
.profileHookRegister()->index());
1983 RegisterID
* BytecodeGenerator::emitCallVarargs(RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, RegisterID
* arguments
, RegisterID
* firstFreeRegister
, int32_t firstVarArgOffset
, RegisterID
* profileHookRegister
, const JSTextPosition
& divot
, const JSTextPosition
& divotStart
, const JSTextPosition
& divotEnd
)
1985 return emitCallVarargs(op_call_varargs
, dst
, func
, thisRegister
, arguments
, firstFreeRegister
, firstVarArgOffset
, profileHookRegister
, divot
, divotStart
, divotEnd
);
1988 RegisterID
* BytecodeGenerator::emitConstructVarargs(RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, RegisterID
* arguments
, RegisterID
* firstFreeRegister
, int32_t firstVarArgOffset
, RegisterID
* profileHookRegister
, const JSTextPosition
& divot
, const JSTextPosition
& divotStart
, const JSTextPosition
& divotEnd
)
1990 return emitCallVarargs(op_construct_varargs
, dst
, func
, thisRegister
, arguments
, firstFreeRegister
, firstVarArgOffset
, profileHookRegister
, divot
, divotStart
, divotEnd
);
1993 RegisterID
* BytecodeGenerator::emitCallVarargs(OpcodeID opcode
, RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, RegisterID
* arguments
, RegisterID
* firstFreeRegister
, int32_t firstVarArgOffset
, RegisterID
* profileHookRegister
, const JSTextPosition
& divot
, const JSTextPosition
& divotStart
, const JSTextPosition
& divotEnd
)
1995 if (m_shouldEmitProfileHooks
) {
1996 emitMove(profileHookRegister
, func
);
1997 emitOpcode(op_profile_will_call
);
1998 instructions().append(profileHookRegister
->index());
2001 emitExpressionInfo(divot
, divotStart
, divotEnd
);
2004 UnlinkedArrayProfile arrayProfile
= newArrayProfile();
2005 UnlinkedValueProfile profile
= emitProfiledOpcode(opcode
);
2006 ASSERT(dst
!= ignoredResult());
2007 instructions().append(dst
->index());
2008 instructions().append(func
->index());
2009 instructions().append(thisRegister
? thisRegister
->index() : 0);
2010 instructions().append(arguments
->index());
2011 instructions().append(firstFreeRegister
->index());
2012 instructions().append(firstVarArgOffset
);
2013 instructions().append(arrayProfile
);
2014 instructions().append(profile
);
2015 if (m_shouldEmitProfileHooks
) {
2016 emitOpcode(op_profile_did_call
);
2017 instructions().append(profileHookRegister
->index());
2022 void BytecodeGenerator::emitCallDefineProperty(RegisterID
* newObj
, RegisterID
* propertyNameRegister
,
2023 RegisterID
* valueRegister
, RegisterID
* getterRegister
, RegisterID
* setterRegister
, unsigned options
, const JSTextPosition
& position
)
2025 RefPtr
<RegisterID
> descriptorRegister
= emitNewObject(newTemporary());
2027 RefPtr
<RegisterID
> trueRegister
= emitLoad(newTemporary(), true);
2028 if (options
& PropertyConfigurable
)
2029 emitDirectPutById(descriptorRegister
.get(), propertyNames().configurable
, trueRegister
.get(), PropertyNode::Unknown
);
2030 if (options
& PropertyWritable
)
2031 emitDirectPutById(descriptorRegister
.get(), propertyNames().writable
, trueRegister
.get(), PropertyNode::Unknown
);
2032 else if (valueRegister
) {
2033 RefPtr
<RegisterID
> falseRegister
= emitLoad(newTemporary(), false);
2034 emitDirectPutById(descriptorRegister
.get(), propertyNames().writable
, falseRegister
.get(), PropertyNode::Unknown
);
2036 if (options
& PropertyEnumerable
)
2037 emitDirectPutById(descriptorRegister
.get(), propertyNames().enumerable
, trueRegister
.get(), PropertyNode::Unknown
);
2040 emitDirectPutById(descriptorRegister
.get(), propertyNames().value
, valueRegister
, PropertyNode::Unknown
);
2042 emitDirectPutById(descriptorRegister
.get(), propertyNames().get
, getterRegister
, PropertyNode::Unknown
);
2044 emitDirectPutById(descriptorRegister
.get(), propertyNames().set
, setterRegister
, PropertyNode::Unknown
);
2046 RefPtr
<RegisterID
> definePropertyRegister
= emitMoveLinkTimeConstant(newTemporary(), LinkTimeConstant::DefinePropertyFunction
);
2048 CallArguments
callArguments(*this, nullptr, 3);
2049 emitLoad(callArguments
.thisRegister(), jsUndefined());
2050 emitMove(callArguments
.argumentRegister(0), newObj
);
2051 emitMove(callArguments
.argumentRegister(1), propertyNameRegister
);
2052 emitMove(callArguments
.argumentRegister(2), descriptorRegister
.get());
2054 emitCall(newTemporary(), definePropertyRegister
.get(), NoExpectedFunction
, callArguments
, position
, position
, position
);
2057 RegisterID
* BytecodeGenerator::emitReturn(RegisterID
* src
)
2059 if (isConstructor()) {
2060 bool derived
= constructorKind() == ConstructorKind::Derived
;
2061 if (derived
&& src
->index() == m_thisRegister
.index())
2064 RefPtr
<Label
> isObjectLabel
= newLabel();
2065 emitJumpIfTrue(emitIsObject(newTemporary(), src
), isObjectLabel
.get());
2068 RefPtr
<Label
> isUndefinedLabel
= newLabel();
2069 emitJumpIfTrue(emitIsUndefined(newTemporary(), src
), isUndefinedLabel
.get());
2070 emitThrowTypeError("Cannot return a non-object type in the constructor of a derived class.");
2071 emitLabel(isUndefinedLabel
.get());
2072 if (constructorKind() == ConstructorKind::Derived
)
2073 emitTDZCheck(&m_thisRegister
);
2076 emitUnaryNoDstOp(op_ret
, &m_thisRegister
);
2078 emitLabel(isObjectLabel
.get());
2081 return emitUnaryNoDstOp(op_ret
, src
);
2084 RegisterID
* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID
, RegisterID
* src
)
2086 emitOpcode(opcodeID
);
2087 instructions().append(src
->index());
2091 RegisterID
* BytecodeGenerator::emitConstruct(RegisterID
* dst
, RegisterID
* func
, ExpectedFunction expectedFunction
, CallArguments
& callArguments
, const JSTextPosition
& divot
, const JSTextPosition
& divotStart
, const JSTextPosition
& divotEnd
)
2093 ASSERT(func
->refCount());
2095 if (m_shouldEmitProfileHooks
)
2096 emitMove(callArguments
.profileHookRegister(), func
);
2098 // Generate code for arguments.
2099 unsigned argument
= 0;
2100 if (ArgumentsNode
* argumentsNode
= callArguments
.argumentsNode()) {
2102 ArgumentListNode
* n
= callArguments
.argumentsNode()->m_listNode
;
2103 if (n
&& n
->m_expr
->isSpreadExpression()) {
2104 RELEASE_ASSERT(!n
->m_next
);
2105 auto expression
= static_cast<SpreadExpressionNode
*>(n
->m_expr
)->expression();
2106 RefPtr
<RegisterID
> argumentRegister
;
2107 argumentRegister
= expression
->emitBytecode(*this, callArguments
.argumentRegister(0));
2108 return emitConstructVarargs(dst
, func
, callArguments
.thisRegister(), argumentRegister
.get(), newTemporary(), 0, callArguments
.profileHookRegister(), divot
, divotStart
, divotEnd
);
2111 for (ArgumentListNode
* n
= argumentsNode
->m_listNode
; n
; n
= n
->m_next
)
2112 emitNode(callArguments
.argumentRegister(argument
++), n
);
2115 if (m_shouldEmitProfileHooks
) {
2116 emitOpcode(op_profile_will_call
);
2117 instructions().append(callArguments
.profileHookRegister()->index());
2120 // Reserve space for call frame.
2121 Vector
<RefPtr
<RegisterID
>, JSStack::CallFrameHeaderSize
, UnsafeVectorOverflow
> callFrame
;
2122 for (int i
= 0; i
< JSStack::CallFrameHeaderSize
; ++i
)
2123 callFrame
.append(newTemporary());
2125 emitExpressionInfo(divot
, divotStart
, divotEnd
);
2127 RefPtr
<Label
> done
= newLabel();
2128 expectedFunction
= emitExpectedFunctionSnippet(dst
, func
, expectedFunction
, callArguments
, done
.get());
2130 UnlinkedValueProfile profile
= emitProfiledOpcode(op_construct
);
2131 ASSERT(dst
!= ignoredResult());
2132 instructions().append(dst
->index());
2133 instructions().append(func
->index());
2134 instructions().append(callArguments
.argumentCountIncludingThis());
2135 instructions().append(callArguments
.stackOffset());
2136 instructions().append(m_codeBlock
->addLLIntCallLinkInfo());
2137 instructions().append(0);
2138 instructions().append(0);
2139 instructions().append(profile
);
2141 if (expectedFunction
!= NoExpectedFunction
)
2142 emitLabel(done
.get());
2144 if (m_shouldEmitProfileHooks
) {
2145 emitOpcode(op_profile_did_call
);
2146 instructions().append(callArguments
.profileHookRegister()->index());
2152 RegisterID
* BytecodeGenerator::emitStrcat(RegisterID
* dst
, RegisterID
* src
, int count
)
2154 emitOpcode(op_strcat
);
2155 instructions().append(dst
->index());
2156 instructions().append(src
->index());
2157 instructions().append(count
);
2162 void BytecodeGenerator::emitToPrimitive(RegisterID
* dst
, RegisterID
* src
)
2164 emitOpcode(op_to_primitive
);
2165 instructions().append(dst
->index());
2166 instructions().append(src
->index());
2169 void BytecodeGenerator::emitGetScope()
2171 emitOpcode(op_get_scope
);
2172 instructions().append(scopeRegister()->index());
2175 RegisterID
* BytecodeGenerator::emitPushWithScope(RegisterID
* dst
, RegisterID
* scope
)
2177 ControlFlowContext context
;
2178 context
.isFinallyBlock
= false;
2179 m_scopeContextStack
.append(context
);
2180 m_localScopeDepth
++;
2182 return emitUnaryOp(op_push_with_scope
, dst
, scope
);
2185 void BytecodeGenerator::emitPopScope(RegisterID
* srcDst
)
2187 ASSERT(m_scopeContextStack
.size());
2188 ASSERT(!m_scopeContextStack
.last().isFinallyBlock
);
2190 emitOpcode(op_pop_scope
);
2191 instructions().append(srcDst
->index());
2193 m_scopeContextStack
.removeLast();
2194 m_localScopeDepth
--;
2197 void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID
, unsigned line
, unsigned charOffset
, unsigned lineStart
)
2199 #if ENABLE(DEBUG_WITH_BREAKPOINT)
2200 if (debugHookID
!= DidReachBreakpoint
)
2203 if (!m_shouldEmitDebugHooks
)
2206 JSTextPosition
divot(line
, charOffset
, lineStart
);
2207 emitExpressionInfo(divot
, divot
, divot
);
2208 emitOpcode(op_debug
);
2209 instructions().append(debugHookID
);
2210 instructions().append(false);
2213 void BytecodeGenerator::pushFinallyContext(StatementNode
* finallyBlock
)
2215 // Reclaim free label scopes.
2216 while (m_labelScopes
.size() && !m_labelScopes
.last().refCount())
2217 m_labelScopes
.removeLast();
2219 ControlFlowContext scope
;
2220 scope
.isFinallyBlock
= true;
2221 FinallyContext context
= {
2225 static_cast<unsigned>(m_scopeContextStack
.size()),
2226 static_cast<unsigned>(m_switchContextStack
.size()),
2227 static_cast<unsigned>(m_forInContextStack
.size()),
2228 static_cast<unsigned>(m_tryContextStack
.size()),
2229 static_cast<unsigned>(m_labelScopes
.size()),
2233 scope
.finallyContext
= context
;
2234 m_scopeContextStack
.append(scope
);
2238 void BytecodeGenerator::pushIteratorCloseContext(RegisterID
* iterator
, ThrowableExpressionData
* node
)
2240 // Reclaim free label scopes.
2241 while (m_labelScopes
.size() && !m_labelScopes
.last().refCount())
2242 m_labelScopes
.removeLast();
2244 ControlFlowContext scope
;
2245 scope
.isFinallyBlock
= true;
2246 FinallyContext context
= {
2250 static_cast<unsigned>(m_scopeContextStack
.size()),
2251 static_cast<unsigned>(m_switchContextStack
.size()),
2252 static_cast<unsigned>(m_forInContextStack
.size()),
2253 static_cast<unsigned>(m_tryContextStack
.size()),
2254 static_cast<unsigned>(m_labelScopes
.size()),
2258 scope
.finallyContext
= context
;
2259 m_scopeContextStack
.append(scope
);
2263 void BytecodeGenerator::popFinallyContext()
2265 ASSERT(m_scopeContextStack
.size());
2266 ASSERT(m_scopeContextStack
.last().isFinallyBlock
);
2267 ASSERT(m_scopeContextStack
.last().finallyContext
.finallyBlock
);
2268 ASSERT(!m_scopeContextStack
.last().finallyContext
.iterator
);
2269 ASSERT(!m_scopeContextStack
.last().finallyContext
.enumerationNode
);
2270 ASSERT(m_finallyDepth
> 0);
2271 m_scopeContextStack
.removeLast();
2275 void BytecodeGenerator::popIteratorCloseContext()
2277 ASSERT(m_scopeContextStack
.size());
2278 ASSERT(m_scopeContextStack
.last().isFinallyBlock
);
2279 ASSERT(!m_scopeContextStack
.last().finallyContext
.finallyBlock
);
2280 ASSERT(m_scopeContextStack
.last().finallyContext
.iterator
);
2281 ASSERT(m_scopeContextStack
.last().finallyContext
.enumerationNode
);
2282 ASSERT(m_finallyDepth
> 0);
2283 m_scopeContextStack
.removeLast();
2287 LabelScopePtr
BytecodeGenerator::breakTarget(const Identifier
& name
)
2289 // Reclaim free label scopes.
2291 // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
2292 // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
2293 // size 0, leading to segfaulty badness. We are yet to identify a valid cause within our code to
2294 // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
2295 // loop condition is a workaround.
2296 while (m_labelScopes
.size()) {
2297 if (m_labelScopes
.last().refCount())
2299 m_labelScopes
.removeLast();
2302 if (!m_labelScopes
.size())
2303 return LabelScopePtr::null();
2305 // We special-case the following, which is a syntax error in Firefox:
2308 if (name
.isEmpty()) {
2309 for (int i
= m_labelScopes
.size() - 1; i
>= 0; --i
) {
2310 LabelScope
* scope
= &m_labelScopes
[i
];
2311 if (scope
->type() != LabelScope::NamedLabel
) {
2312 ASSERT(scope
->breakTarget());
2313 return LabelScopePtr(m_labelScopes
, i
);
2316 return LabelScopePtr::null();
2319 for (int i
= m_labelScopes
.size() - 1; i
>= 0; --i
) {
2320 LabelScope
* scope
= &m_labelScopes
[i
];
2321 if (scope
->name() && *scope
->name() == name
) {
2322 ASSERT(scope
->breakTarget());
2323 return LabelScopePtr(m_labelScopes
, i
);
2326 return LabelScopePtr::null();
2329 LabelScopePtr
BytecodeGenerator::continueTarget(const Identifier
& name
)
2331 // Reclaim free label scopes.
2332 while (m_labelScopes
.size() && !m_labelScopes
.last().refCount())
2333 m_labelScopes
.removeLast();
2335 if (!m_labelScopes
.size())
2336 return LabelScopePtr::null();
2338 if (name
.isEmpty()) {
2339 for (int i
= m_labelScopes
.size() - 1; i
>= 0; --i
) {
2340 LabelScope
* scope
= &m_labelScopes
[i
];
2341 if (scope
->type() == LabelScope::Loop
) {
2342 ASSERT(scope
->continueTarget());
2343 return LabelScopePtr(m_labelScopes
, i
);
2346 return LabelScopePtr::null();
2349 // Continue to the loop nested nearest to the label scope that matches
2351 LabelScopePtr result
= LabelScopePtr::null();
2352 for (int i
= m_labelScopes
.size() - 1; i
>= 0; --i
) {
2353 LabelScope
* scope
= &m_labelScopes
[i
];
2354 if (scope
->type() == LabelScope::Loop
) {
2355 ASSERT(scope
->continueTarget());
2356 result
= LabelScopePtr(m_labelScopes
, i
);
2358 if (scope
->name() && *scope
->name() == name
)
2359 return result
; // may be null.
2361 return LabelScopePtr::null();
2364 void BytecodeGenerator::allocateAndEmitScope()
2366 m_scopeRegister
= addVar();
2367 m_scopeRegister
->ref();
2368 m_codeBlock
->setScopeRegister(scopeRegister()->virtualRegister());
2372 void BytecodeGenerator::emitComplexPopScopes(RegisterID
* scope
, ControlFlowContext
* topScope
, ControlFlowContext
* bottomScope
)
2374 while (topScope
> bottomScope
) {
2375 // First we count the number of dynamic scopes we need to remove to get
2376 // to a finally block.
2377 int nNormalScopes
= 0;
2378 while (topScope
> bottomScope
) {
2379 if (topScope
->isFinallyBlock
)
2385 if (nNormalScopes
) {
2386 // We need to remove a number of dynamic scopes to get to the next
2388 while (nNormalScopes
--) {
2389 emitOpcode(op_pop_scope
);
2390 instructions().append(scope
->index());
2393 // If topScope == bottomScope then there isn't a finally block left to emit.
2394 if (topScope
== bottomScope
)
2398 Vector
<ControlFlowContext
> savedScopeContextStack
;
2399 Vector
<SwitchInfo
> savedSwitchContextStack
;
2400 Vector
<std::unique_ptr
<ForInContext
>> savedForInContextStack
;
2401 Vector
<TryContext
> poppedTryContexts
;
2402 LabelScopeStore savedLabelScopes
;
2403 while (topScope
> bottomScope
&& topScope
->isFinallyBlock
) {
2404 RefPtr
<Label
> beforeFinally
= emitLabel(newLabel().get());
2406 // Save the current state of the world while instating the state of the world
2407 // for the finally block.
2408 FinallyContext finallyContext
= topScope
->finallyContext
;
2409 bool flipScopes
= finallyContext
.scopeContextStackSize
!= m_scopeContextStack
.size();
2410 bool flipSwitches
= finallyContext
.switchContextStackSize
!= m_switchContextStack
.size();
2411 bool flipForIns
= finallyContext
.forInContextStackSize
!= m_forInContextStack
.size();
2412 bool flipTries
= finallyContext
.tryContextStackSize
!= m_tryContextStack
.size();
2413 bool flipLabelScopes
= finallyContext
.labelScopesSize
!= m_labelScopes
.size();
2414 int topScopeIndex
= -1;
2415 int bottomScopeIndex
= -1;
2417 topScopeIndex
= topScope
- m_scopeContextStack
.begin();
2418 bottomScopeIndex
= bottomScope
- m_scopeContextStack
.begin();
2419 savedScopeContextStack
= m_scopeContextStack
;
2420 m_scopeContextStack
.shrink(finallyContext
.scopeContextStackSize
);
2423 savedSwitchContextStack
= m_switchContextStack
;
2424 m_switchContextStack
.shrink(finallyContext
.switchContextStackSize
);
2427 savedForInContextStack
.swap(m_forInContextStack
);
2428 m_forInContextStack
.shrink(finallyContext
.forInContextStackSize
);
2431 while (m_tryContextStack
.size() != finallyContext
.tryContextStackSize
) {
2432 ASSERT(m_tryContextStack
.size() > finallyContext
.tryContextStackSize
);
2433 TryContext context
= m_tryContextStack
.last();
2434 m_tryContextStack
.removeLast();
2436 range
.start
= context
.start
;
2437 range
.end
= beforeFinally
;
2438 range
.tryData
= context
.tryData
;
2439 m_tryRanges
.append(range
);
2440 poppedTryContexts
.append(context
);
2443 if (flipLabelScopes
) {
2444 savedLabelScopes
= m_labelScopes
;
2445 while (m_labelScopes
.size() > finallyContext
.labelScopesSize
)
2446 m_labelScopes
.removeLast();
2448 int savedFinallyDepth
= m_finallyDepth
;
2449 m_finallyDepth
= finallyContext
.finallyDepth
;
2450 int savedDynamicScopeDepth
= m_localScopeDepth
;
2451 m_localScopeDepth
= finallyContext
.dynamicScopeDepth
;
2453 if (finallyContext
.finallyBlock
) {
2454 // Emit the finally block.
2455 emitNode(finallyContext
.finallyBlock
);
2457 // Emit the IteratorClose block.
2458 ASSERT(finallyContext
.iterator
);
2459 emitIteratorClose(finallyContext
.iterator
, finallyContext
.enumerationNode
);
2462 RefPtr
<Label
> afterFinally
= emitLabel(newLabel().get());
2464 // Restore the state of the world.
2466 m_scopeContextStack
= savedScopeContextStack
;
2467 topScope
= &m_scopeContextStack
[topScopeIndex
]; // assert it's within bounds
2468 bottomScope
= m_scopeContextStack
.begin() + bottomScopeIndex
; // don't assert, since it the index might be -1.
2471 m_switchContextStack
= savedSwitchContextStack
;
2473 m_forInContextStack
.swap(savedForInContextStack
);
2475 ASSERT(m_tryContextStack
.size() == finallyContext
.tryContextStackSize
);
2476 for (unsigned i
= poppedTryContexts
.size(); i
--;) {
2477 TryContext context
= poppedTryContexts
[i
];
2478 context
.start
= afterFinally
;
2479 m_tryContextStack
.append(context
);
2481 poppedTryContexts
.clear();
2483 if (flipLabelScopes
)
2484 m_labelScopes
= savedLabelScopes
;
2485 m_finallyDepth
= savedFinallyDepth
;
2486 m_localScopeDepth
= savedDynamicScopeDepth
;
2493 void BytecodeGenerator::emitPopScopes(RegisterID
* scope
, int targetScopeDepth
)
2495 ASSERT(scopeDepth() - targetScopeDepth
>= 0);
2497 size_t scopeDelta
= scopeDepth() - targetScopeDepth
;
2498 ASSERT(scopeDelta
<= m_scopeContextStack
.size());
2502 if (!m_finallyDepth
) {
2503 while (scopeDelta
--) {
2504 emitOpcode(op_pop_scope
);
2505 instructions().append(scope
->index());
2510 emitComplexPopScopes(scope
, &m_scopeContextStack
.last(), &m_scopeContextStack
.last() - scopeDelta
);
2513 TryData
* BytecodeGenerator::pushTry(Label
* start
)
2516 tryData
.target
= newLabel();
2517 tryData
.targetScopeDepth
= UINT_MAX
;
2518 tryData
.handlerType
= HandlerType::Illegal
;
2519 m_tryData
.append(tryData
);
2520 TryData
* result
= &m_tryData
.last();
2522 TryContext tryContext
;
2523 tryContext
.start
= start
;
2524 tryContext
.tryData
= result
;
2526 m_tryContextStack
.append(tryContext
);
2531 void BytecodeGenerator::popTryAndEmitCatch(TryData
* tryData
, RegisterID
* exceptionRegister
, RegisterID
* thrownValueRegister
, Label
* end
, HandlerType handlerType
)
2533 m_usesExceptions
= true;
2535 ASSERT_UNUSED(tryData
, m_tryContextStack
.last().tryData
== tryData
);
2538 tryRange
.start
= m_tryContextStack
.last().start
;
2540 tryRange
.tryData
= m_tryContextStack
.last().tryData
;
2541 m_tryRanges
.append(tryRange
);
2542 m_tryContextStack
.removeLast();
2544 emitLabel(tryRange
.tryData
->target
.get());
2545 tryRange
.tryData
->targetScopeDepth
= m_localScopeDepth
;
2546 tryRange
.tryData
->handlerType
= handlerType
;
2548 emitOpcode(op_catch
);
2549 instructions().append(exceptionRegister
->index());
2550 instructions().append(thrownValueRegister
->index());
2553 void BytecodeGenerator::emitThrowReferenceError(const String
& message
)
2555 emitOpcode(op_throw_static_error
);
2556 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm
, message
)))->index());
2557 instructions().append(true);
2560 void BytecodeGenerator::emitThrowTypeError(const String
& message
)
2562 emitOpcode(op_throw_static_error
);
2563 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm
, message
)))->index());
2564 instructions().append(false);
2567 void BytecodeGenerator::emitPushFunctionNameScope(RegisterID
* dst
, const Identifier
& property
, RegisterID
* value
, unsigned attributes
)
2569 emitOpcode(op_push_name_scope
);
2570 instructions().append(dst
->index());
2571 instructions().append(value
->index());
2572 instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property
, attributes
))->index());
2573 instructions().append(JSNameScope::FunctionNameScope
);
2576 void BytecodeGenerator::emitPushCatchScope(RegisterID
* dst
, const Identifier
& property
, RegisterID
* value
, unsigned attributes
)
2578 ControlFlowContext context
;
2579 context
.isFinallyBlock
= false;
2580 m_scopeContextStack
.append(context
);
2581 m_localScopeDepth
++;
2583 emitOpcode(op_push_name_scope
);
2584 instructions().append(dst
->index());
2585 instructions().append(value
->index());
2586 instructions().append(addConstantValue(SymbolTable::createNameScopeTable(*vm(), property
, attributes
))->index());
2587 instructions().append(JSNameScope::CatchScope
);
2590 void BytecodeGenerator::beginSwitch(RegisterID
* scrutineeRegister
, SwitchInfo::SwitchType type
)
2592 SwitchInfo info
= { static_cast<uint32_t>(instructions().size()), type
};
2594 case SwitchInfo::SwitchImmediate
:
2595 emitOpcode(op_switch_imm
);
2597 case SwitchInfo::SwitchCharacter
:
2598 emitOpcode(op_switch_char
);
2600 case SwitchInfo::SwitchString
:
2601 emitOpcode(op_switch_string
);
2604 RELEASE_ASSERT_NOT_REACHED();
2607 instructions().append(0); // place holder for table index
2608 instructions().append(0); // place holder for default target
2609 instructions().append(scrutineeRegister
->index());
2610 m_switchContextStack
.append(info
);
2613 static int32_t keyForImmediateSwitch(ExpressionNode
* node
, int32_t min
, int32_t max
)
2616 ASSERT(node
->isNumber());
2617 double value
= static_cast<NumberNode
*>(node
)->value();
2618 int32_t key
= static_cast<int32_t>(value
);
2619 ASSERT(key
== value
);
2625 static int32_t keyForCharacterSwitch(ExpressionNode
* node
, int32_t min
, int32_t max
)
2628 ASSERT(node
->isString());
2629 StringImpl
* clause
= static_cast<StringNode
*>(node
)->value().impl();
2630 ASSERT(clause
->length() == 1);
2632 int32_t key
= (*clause
)[0];
2638 static void prepareJumpTableForSwitch(
2639 UnlinkedSimpleJumpTable
& jumpTable
, int32_t switchAddress
, uint32_t clauseCount
,
2640 RefPtr
<Label
>* labels
, ExpressionNode
** nodes
, int32_t min
, int32_t max
,
2641 int32_t (*keyGetter
)(ExpressionNode
*, int32_t min
, int32_t max
))
2643 jumpTable
.min
= min
;
2644 jumpTable
.branchOffsets
.resize(max
- min
+ 1);
2645 jumpTable
.branchOffsets
.fill(0);
2646 for (uint32_t i
= 0; i
< clauseCount
; ++i
) {
2647 // We're emitting this after the clause labels should have been fixed, so
2648 // the labels should not be "forward" references
2649 ASSERT(!labels
[i
]->isForward());
2650 jumpTable
.add(keyGetter(nodes
[i
], min
, max
), labels
[i
]->bind(switchAddress
, switchAddress
+ 3));
2654 static void prepareJumpTableForStringSwitch(UnlinkedStringJumpTable
& jumpTable
, int32_t switchAddress
, uint32_t clauseCount
, RefPtr
<Label
>* labels
, ExpressionNode
** nodes
)
2656 for (uint32_t i
= 0; i
< clauseCount
; ++i
) {
2657 // We're emitting this after the clause labels should have been fixed, so
2658 // the labels should not be "forward" references
2659 ASSERT(!labels
[i
]->isForward());
2661 ASSERT(nodes
[i
]->isString());
2662 StringImpl
* clause
= static_cast<StringNode
*>(nodes
[i
])->value().impl();
2663 jumpTable
.offsetTable
.add(clause
, labels
[i
]->bind(switchAddress
, switchAddress
+ 3));
2667 void BytecodeGenerator::endSwitch(uint32_t clauseCount
, RefPtr
<Label
>* labels
, ExpressionNode
** nodes
, Label
* defaultLabel
, int32_t min
, int32_t max
)
2669 SwitchInfo switchInfo
= m_switchContextStack
.last();
2670 m_switchContextStack
.removeLast();
2672 switch (switchInfo
.switchType
) {
2673 case SwitchInfo::SwitchImmediate
:
2674 case SwitchInfo::SwitchCharacter
: {
2675 instructions()[switchInfo
.bytecodeOffset
+ 1] = m_codeBlock
->numberOfSwitchJumpTables();
2676 instructions()[switchInfo
.bytecodeOffset
+ 2] = defaultLabel
->bind(switchInfo
.bytecodeOffset
, switchInfo
.bytecodeOffset
+ 3);
2678 UnlinkedSimpleJumpTable
& jumpTable
= m_codeBlock
->addSwitchJumpTable();
2679 prepareJumpTableForSwitch(
2680 jumpTable
, switchInfo
.bytecodeOffset
, clauseCount
, labels
, nodes
, min
, max
,
2681 switchInfo
.switchType
== SwitchInfo::SwitchImmediate
2682 ? keyForImmediateSwitch
2683 : keyForCharacterSwitch
);
2687 case SwitchInfo::SwitchString
: {
2688 instructions()[switchInfo
.bytecodeOffset
+ 1] = m_codeBlock
->numberOfStringSwitchJumpTables();
2689 instructions()[switchInfo
.bytecodeOffset
+ 2] = defaultLabel
->bind(switchInfo
.bytecodeOffset
, switchInfo
.bytecodeOffset
+ 3);
2691 UnlinkedStringJumpTable
& jumpTable
= m_codeBlock
->addStringSwitchJumpTable();
2692 prepareJumpTableForStringSwitch(jumpTable
, switchInfo
.bytecodeOffset
, clauseCount
, labels
, nodes
);
2697 RELEASE_ASSERT_NOT_REACHED();
2702 RegisterID
* BytecodeGenerator::emitThrowExpressionTooDeepException()
2704 // It would be nice to do an even better job of identifying exactly where the expression is.
2705 // And we could make the caller pass the node pointer in, if there was some way of getting
2706 // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
2707 // is still good enough to get us an accurate line number.
2708 m_expressionTooDeep
= true;
2709 return newTemporary();
2712 bool BytecodeGenerator::isArgumentNumber(const Identifier
& ident
, int argumentNumber
)
2714 RegisterID
* registerID
= variable(ident
).local();
2717 return registerID
->index() == CallFrame::argumentOffset(argumentNumber
);
2720 void BytecodeGenerator::emitReadOnlyExceptionIfNeeded()
2722 if (!isStrictMode())
2724 emitOpcode(op_throw_static_error
);
2725 instructions().append(addConstantValue(addStringConstant(Identifier::fromString(m_vm
, StrictModeReadonlyPropertyWriteError
)))->index());
2726 instructions().append(false);
2729 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData
* node
, ExpressionNode
* subjectNode
, const std::function
<void(BytecodeGenerator
&, RegisterID
*)>& callBack
)
2731 RefPtr
<RegisterID
> subject
= newTemporary();
2732 emitNode(subject
.get(), subjectNode
);
2733 RefPtr
<RegisterID
> iterator
= emitGetById(newTemporary(), subject
.get(), propertyNames().iteratorSymbol
);
2735 CallArguments
args(*this, nullptr);
2736 emitMove(args
.thisRegister(), subject
.get());
2737 emitCall(iterator
.get(), iterator
.get(), NoExpectedFunction
, args
, node
->divot(), node
->divotStart(), node
->divotEnd());
2740 RefPtr
<Label
> loopDone
= newLabel();
2741 // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext.
2742 pushIteratorCloseContext(iterator
.get(), node
);
2744 LabelScopePtr scope
= newLabelScope(LabelScope::Loop
);
2745 RefPtr
<RegisterID
> value
= newTemporary();
2746 emitLoad(value
.get(), jsUndefined());
2748 emitJump(scope
->continueTarget());
2750 RefPtr
<Label
> loopStart
= newLabel();
2751 emitLabel(loopStart
.get());
2754 RefPtr
<Label
> tryStartLabel
= newLabel();
2755 emitLabel(tryStartLabel
.get());
2756 TryData
* tryData
= pushTry(tryStartLabel
.get());
2757 callBack(*this, value
.get());
2758 emitJump(scope
->continueTarget());
2760 // IteratorClose sequence for throw-ed control flow.
2762 RefPtr
<Label
> catchHere
= emitLabel(newLabel().get());
2763 RefPtr
<RegisterID
> exceptionRegister
= newTemporary();
2764 RefPtr
<RegisterID
> thrownValueRegister
= newTemporary();
2765 popTryAndEmitCatch(tryData
, exceptionRegister
.get(),
2766 thrownValueRegister
.get(), catchHere
.get(), HandlerType::SynthesizedFinally
);
2768 RefPtr
<Label
> catchDone
= newLabel();
2770 RefPtr
<RegisterID
> returnMethod
= emitGetById(newTemporary(), iterator
.get(), propertyNames().returnKeyword
);
2771 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod
.get()), catchDone
.get());
2773 RefPtr
<Label
> returnCallTryStart
= newLabel();
2774 emitLabel(returnCallTryStart
.get());
2775 TryData
* returnCallTryData
= pushTry(returnCallTryStart
.get());
2777 CallArguments
returnArguments(*this, nullptr);
2778 emitMove(returnArguments
.thisRegister(), iterator
.get());
2779 emitCall(value
.get(), returnMethod
.get(), NoExpectedFunction
, returnArguments
, node
->divot(), node
->divotStart(), node
->divotEnd());
2781 emitLabel(catchDone
.get());
2782 emitThrow(exceptionRegister
.get());
2784 // Absorb exception.
2785 popTryAndEmitCatch(returnCallTryData
, newTemporary(),
2786 newTemporary(), catchDone
.get(), HandlerType::SynthesizedFinally
);
2787 emitThrow(exceptionRegister
.get());
2790 emitLabel(scope
->continueTarget());
2792 emitIteratorNext(value
.get(), iterator
.get(), node
);
2793 emitJumpIfTrue(emitGetById(newTemporary(), value
.get(), propertyNames().done
), loopDone
.get());
2794 emitGetById(value
.get(), value
.get(), propertyNames().value
);
2795 emitJump(loopStart
.get());
2798 emitLabel(scope
->breakTarget());
2801 // IteratorClose sequence for break-ed control flow.
2802 popIteratorCloseContext();
2803 emitIteratorClose(iterator
.get(), node
);
2804 emitLabel(loopDone
.get());
2807 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
2808 RegisterID
* BytecodeGenerator::emitGetTemplateObject(RegisterID
* dst
, TaggedTemplateNode
* taggedTemplate
)
2810 TemplateRegistryKey::StringVector rawStrings
;
2811 TemplateRegistryKey::StringVector cookedStrings
;
2813 TemplateStringListNode
* templateString
= taggedTemplate
->templateLiteral()->templateStrings();
2814 for (; templateString
; templateString
= templateString
->next()) {
2815 rawStrings
.append(templateString
->value()->raw().impl());
2816 cookedStrings
.append(templateString
->value()->cooked().impl());
2819 RefPtr
<RegisterID
> getTemplateObject
= nullptr;
2820 Variable var
= variable(propertyNames().getTemplateObjectPrivateName
);
2821 if (RegisterID
* local
= var
.local())
2822 getTemplateObject
= emitMove(newTemporary(), local
);
2824 getTemplateObject
= newTemporary();
2825 RefPtr
<RegisterID
> scope
= newTemporary();
2826 moveToDestinationIfNeeded(scope
.get(), emitResolveScope(scope
.get(), var
));
2827 emitGetFromScope(getTemplateObject
.get(), scope
.get(), var
, ThrowIfNotFound
);
2830 CallArguments
arguments(*this, nullptr);
2831 emitLoad(arguments
.thisRegister(), JSValue(addTemplateRegistryKeyConstant(TemplateRegistryKey(rawStrings
, cookedStrings
))));
2832 return emitCall(dst
, getTemplateObject
.get(), NoExpectedFunction
, arguments
, taggedTemplate
->divot(), taggedTemplate
->divotStart(), taggedTemplate
->divotEnd());
2836 RegisterID
* BytecodeGenerator::emitGetEnumerableLength(RegisterID
* dst
, RegisterID
* base
)
2838 emitOpcode(op_get_enumerable_length
);
2839 instructions().append(dst
->index());
2840 instructions().append(base
->index());
2844 RegisterID
* BytecodeGenerator::emitHasGenericProperty(RegisterID
* dst
, RegisterID
* base
, RegisterID
* propertyName
)
2846 emitOpcode(op_has_generic_property
);
2847 instructions().append(dst
->index());
2848 instructions().append(base
->index());
2849 instructions().append(propertyName
->index());
2853 RegisterID
* BytecodeGenerator::emitHasIndexedProperty(RegisterID
* dst
, RegisterID
* base
, RegisterID
* propertyName
)
2855 UnlinkedArrayProfile arrayProfile
= newArrayProfile();
2856 emitOpcode(op_has_indexed_property
);
2857 instructions().append(dst
->index());
2858 instructions().append(base
->index());
2859 instructions().append(propertyName
->index());
2860 instructions().append(arrayProfile
);
2864 RegisterID
* BytecodeGenerator::emitHasStructureProperty(RegisterID
* dst
, RegisterID
* base
, RegisterID
* propertyName
, RegisterID
* enumerator
)
2866 emitOpcode(op_has_structure_property
);
2867 instructions().append(dst
->index());
2868 instructions().append(base
->index());
2869 instructions().append(propertyName
->index());
2870 instructions().append(enumerator
->index());
2874 RegisterID
* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID
* dst
, RegisterID
* base
)
2876 emitOpcode(op_get_property_enumerator
);
2877 instructions().append(dst
->index());
2878 instructions().append(base
->index());
2882 RegisterID
* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID
* dst
, RegisterID
* enumerator
, RegisterID
* index
)
2884 emitOpcode(op_enumerator_structure_pname
);
2885 instructions().append(dst
->index());
2886 instructions().append(enumerator
->index());
2887 instructions().append(index
->index());
2891 RegisterID
* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID
* dst
, RegisterID
* enumerator
, RegisterID
* index
)
2893 emitOpcode(op_enumerator_generic_pname
);
2894 instructions().append(dst
->index());
2895 instructions().append(enumerator
->index());
2896 instructions().append(index
->index());
2900 RegisterID
* BytecodeGenerator::emitToIndexString(RegisterID
* dst
, RegisterID
* index
)
2902 emitOpcode(op_to_index_string
);
2903 instructions().append(dst
->index());
2904 instructions().append(index
->index());
2909 RegisterID
* BytecodeGenerator::emitIsObject(RegisterID
* dst
, RegisterID
* src
)
2911 emitOpcode(op_is_object
);
2912 instructions().append(dst
->index());
2913 instructions().append(src
->index());
2917 RegisterID
* BytecodeGenerator::emitIsUndefined(RegisterID
* dst
, RegisterID
* src
)
2919 emitOpcode(op_is_undefined
);
2920 instructions().append(dst
->index());
2921 instructions().append(src
->index());
2925 RegisterID
* BytecodeGenerator::emitIteratorNext(RegisterID
* dst
, RegisterID
* iterator
, const ThrowableExpressionData
* node
)
2928 RefPtr
<RegisterID
> next
= emitGetById(newTemporary(), iterator
, propertyNames().next
);
2929 CallArguments
nextArguments(*this, nullptr);
2930 emitMove(nextArguments
.thisRegister(), iterator
);
2931 emitCall(dst
, next
.get(), NoExpectedFunction
, nextArguments
, node
->divot(), node
->divotStart(), node
->divotEnd());
2934 RefPtr
<Label
> typeIsObject
= newLabel();
2935 emitJumpIfTrue(emitIsObject(newTemporary(), dst
), typeIsObject
.get());
2936 emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
2937 emitLabel(typeIsObject
.get());
2942 void BytecodeGenerator::emitIteratorClose(RegisterID
* iterator
, const ThrowableExpressionData
* node
)
2944 RefPtr
<Label
> done
= newLabel();
2945 RefPtr
<RegisterID
> returnMethod
= emitGetById(newTemporary(), iterator
, propertyNames().returnKeyword
);
2946 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod
.get()), done
.get());
2948 RefPtr
<RegisterID
> value
= newTemporary();
2949 CallArguments
returnArguments(*this, nullptr);
2950 emitMove(returnArguments
.thisRegister(), iterator
);
2951 emitCall(value
.get(), returnMethod
.get(), NoExpectedFunction
, returnArguments
, node
->divot(), node
->divotStart(), node
->divotEnd());
2952 emitJumpIfTrue(emitIsObject(newTemporary(), value
.get()), done
.get());
2953 emitThrowTypeError(ASCIILiteral("Iterator result interface is not an object."));
2954 emitLabel(done
.get());
2957 void BytecodeGenerator::pushIndexedForInScope(RegisterID
* localRegister
, RegisterID
* indexRegister
)
2961 m_forInContextStack
.append(std::make_unique
<IndexedForInContext
>(localRegister
, indexRegister
));
2964 void BytecodeGenerator::popIndexedForInScope(RegisterID
* localRegister
)
2968 m_forInContextStack
.removeLast();
2971 void BytecodeGenerator::pushStructureForInScope(RegisterID
* localRegister
, RegisterID
* indexRegister
, RegisterID
* propertyRegister
, RegisterID
* enumeratorRegister
)
2975 m_forInContextStack
.append(std::make_unique
<StructureForInContext
>(localRegister
, indexRegister
, propertyRegister
, enumeratorRegister
));
2978 void BytecodeGenerator::popStructureForInScope(RegisterID
* localRegister
)
2982 m_forInContextStack
.removeLast();
2985 void BytecodeGenerator::invalidateForInContextForLocal(RegisterID
* localRegister
)
2987 // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
2988 // either of the following conditions is true:
2990 // (1) The loop iteration variable is re-assigned within the body of the loop.
2991 // (2) The loop iteration variable is captured in the lexical scope of the function.
2993 // These two situations occur sufficiently rarely that it's okay to use this style of
2994 // "analysis" to make iteration faster. If we didn't want to do this, we would either have
2995 // to perform some flow-sensitive analysis to see if/when the loop iteration variable was
2996 // reassigned, or we'd have to resort to runtime checks to see if the variable had been
2997 // reassigned from its original value.
2998 for (size_t i
= m_forInContextStack
.size(); i
> 0; i
--) {
2999 ForInContext
* context
= m_forInContextStack
[i
- 1].get();
3000 if (context
->local() != localRegister
)
3002 context
->invalidate();