1/*
2 * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <[email protected]>
4 * Copyright (C) 2012 Igalia, S.L.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "BytecodeGenerator.h"
33
34#include "ArithProfile.h"
35#include "BuiltinExecutables.h"
36#include "BuiltinNames.h"
37#include "BytecodeGeneratorBaseInlines.h"
38#include "BytecodeGeneratorification.h"
39#include "BytecodeLivenessAnalysis.h"
40#include "BytecodeUseDef.h"
41#include "CatchScope.h"
42#include "DefinePropertyAttributes.h"
43#include "Interpreter.h"
44#include "JSAsyncGenerator.h"
45#include "JSBigInt.h"
46#include "JSCInlines.h"
47#include "JSFixedArray.h"
48#include "JSFunction.h"
49#include "JSGeneratorFunction.h"
50#include "JSImmutableButterfly.h"
51#include "JSLexicalEnvironment.h"
52#include "JSTemplateObjectDescriptor.h"
53#include "LinkTimeConstant.h"
54#include "LowLevelInterpreter.h"
55#include "Options.h"
56#include "PreciseJumpTargetsInlines.h"
57#include "StackAlignment.h"
58#include "StrongInlines.h"
59#include "SuperSamplerBytecodeScope.h"
60#include "UnlinkedCodeBlock.h"
61#include "UnlinkedEvalCodeBlock.h"
62#include "UnlinkedFunctionCodeBlock.h"
63#include "UnlinkedMetadataTableInlines.h"
64#include "UnlinkedModuleProgramCodeBlock.h"
65#include "UnlinkedProgramCodeBlock.h"
66#include <wtf/BitVector.h>
67#include <wtf/CommaPrinter.h>
68#include <wtf/Optional.h>
69#include <wtf/SmallPtrSet.h>
70#include <wtf/StdLibExtras.h>
71#include <wtf/text/WTFString.h>
72
73namespace JSC {
74
75template<typename CallOp, typename = std::true_type>
76struct VarArgsOp;
77
78template<typename CallOp>
79struct VarArgsOp<CallOp, std::enable_if_t<std::is_same<CallOp, OpTailCall>::value, std::true_type>> {
80 using type = OpTailCallVarargs;
81};
82
83
84template<typename CallOp>
85struct VarArgsOp<CallOp, std::enable_if_t<!std::is_same<CallOp, OpTailCall>::value, std::true_type>> {
86 using type = OpCallVarargs;
87};
88
89template<>
90void GenericLabel<JSGeneratorTraits>::setLocation(BytecodeGenerator& generator, unsigned location)
91{
92 m_location = location;
93
94 for (auto offset : m_unresolvedJumps) {
95 auto instruction = generator.m_writer.ref(offset);
96 int target = m_location - offset;
97
98#define CASE(__op) \
99 case __op::opcodeID: \
100 instruction->cast<__op>()->setTargetLabel(BoundLabel(target), [&]() { \
101 generator.m_codeBlock->addOutOfLineJumpTarget(instruction.offset(), target); \
102 return BoundLabel(); \
103 }); \
104 break;
105
106 switch (instruction->opcodeID()) {
107 CASE(OpJmp)
108 CASE(OpJtrue)
109 CASE(OpJfalse)
110 CASE(OpJeqNull)
111 CASE(OpJneqNull)
112 CASE(OpJundefinedOrNull)
113 CASE(OpJnundefinedOrNull)
114 CASE(OpJeq)
115 CASE(OpJstricteq)
116 CASE(OpJneq)
117 CASE(OpJneqPtr)
118 CASE(OpJnstricteq)
119 CASE(OpJless)
120 CASE(OpJlesseq)
121 CASE(OpJgreater)
122 CASE(OpJgreatereq)
123 CASE(OpJnless)
124 CASE(OpJnlesseq)
125 CASE(OpJngreater)
126 CASE(OpJngreatereq)
127 CASE(OpJbelow)
128 CASE(OpJbeloweq)
129 default:
130 ASSERT_NOT_REACHED();
131 }
132#undef CASE
133 }
134}
135
136void Variable::dump(PrintStream& out) const
137{
138 out.print(
139 "{ident = ", m_ident,
140 ", offset = ", m_offset,
141 ", local = ", RawPointer(m_local),
142 ", attributes = ", m_attributes,
143 ", kind = ", m_kind,
144 ", symbolTableConstantIndex = ", m_symbolTableConstantIndex,
145 ", isLexicallyScoped = ", m_isLexicallyScoped, "}");
146}
147
148FinallyContext::FinallyContext(BytecodeGenerator& generator, Label& finallyLabel)
149 : m_outerContext(generator.m_currentFinallyContext)
150 , m_finallyLabel(&finallyLabel)
151{
152 ASSERT(m_jumps.isEmpty());
153 m_completionRecord.typeRegister = generator.newTemporary();
154 m_completionRecord.valueRegister = generator.newTemporary();
155 generator.emitLoad(completionTypeRegister(), CompletionType::Normal);
156 generator.moveEmptyValue(completionValueRegister());
157}
158
159ParserError BytecodeGenerator::generate()
160{
161 m_codeBlock->setThisRegister(m_thisRegister.virtualRegister());
162
163 emitLogShadowChickenPrologueIfNecessary();
164
165 // If we have declared a variable named "arguments" and we are using arguments then we should
166 // perform that assignment now.
167 if (m_needToInitializeArguments)
168 initializeVariable(variable(propertyNames().arguments), m_argumentsRegister);
169
170 if (m_restParameter)
171 m_restParameter->emit(*this);
172
173 {
174 RefPtr<RegisterID> temp = newTemporary();
175 RefPtr<RegisterID> tolLevelScope;
176 for (auto functionPair : m_functionsToInitialize) {
177 FunctionMetadataNode* metadata = functionPair.first;
178 FunctionVariableType functionType = functionPair.second;
179 emitNewFunction(temp.get(), metadata);
180 if (functionType == NormalFunctionVariable)
181 initializeVariable(variable(metadata->ident()), temp.get());
182 else if (functionType == TopLevelFunctionVariable) {
183 if (!tolLevelScope) {
184 // We know this will resolve to the top level scope or global object because our parser/global initialization code
185 // doesn't allow let/const/class variables to have the same names as functions.
186 // This is a top level function, and it's an error to ever create a top level function
187 // name that would resolve to a lexical variable. E.g:
188 // ```
189 // function f() {
190 // {
191 // let x;
192 // {
193 // //// error thrown here
194 // eval("function x(){}");
195 // }
196 // }
197 // }
198 // ```
199 // Therefore, we're guaranteed to have this resolve to a top level variable.
200 RefPtr<RegisterID> tolLevelObjectScope = emitResolveScope(nullptr, Variable(metadata->ident()));
201 tolLevelScope = newBlockScopeVariable();
202 move(tolLevelScope.get(), tolLevelObjectScope.get());
203 }
204 emitPutToScope(tolLevelScope.get(), Variable(metadata->ident()), temp.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
205 } else
206 RELEASE_ASSERT_NOT_REACHED();
207 }
208 }
209
210 bool callingClassConstructor = false;
211 switch (constructorKind()) {
212 case ConstructorKind::None:
213 case ConstructorKind::Naked:
214 break;
215 case ConstructorKind::Base:
216 case ConstructorKind::Extends:
217 callingClassConstructor = !isConstructor();
218 break;
219 }
220 if (!callingClassConstructor)
221 m_scopeNode->emitBytecode(*this);
222 else {
223 // At this point we would have emitted an unconditional throw followed by some nonsense that's
224 // just an artifact of how this generator is structured. That code never runs, but it confuses
225 // bytecode analyses because it constitutes an unterminated basic block. So, we terminate the
226 // basic block the strongest way possible.
227 emitUnreachable();
228 }
229
230 for (auto& handler : m_exceptionHandlersToEmit) {
231 Ref<Label> realCatchTarget = newLabel();
232 TryData* tryData = handler.tryData;
233
234 OpCatch::emit(this, handler.exceptionRegister, handler.thrownValueRegister);
235 realCatchTarget->setLocation(*this, m_lastInstruction.offset());
236 if (handler.completionTypeRegister.isValid()) {
237 RegisterID completionTypeRegister { handler.completionTypeRegister };
238 CompletionType completionType =
239 tryData->handlerType == HandlerType::Finally || tryData->handlerType == HandlerType::SynthesizedFinally
240 ? CompletionType::Throw
241 : CompletionType::Normal;
242 emitLoad(&completionTypeRegister, completionType);
243 }
244 m_codeBlock->addJumpTarget(m_lastInstruction.offset());
245
246
247 emitJump(tryData->target.get());
248 tryData->target = WTFMove(realCatchTarget);
249 }
250
251 m_staticPropertyAnalyzer.kill();
252
253 for (auto& range : m_tryRanges) {
254 int start = range.start->bind();
255 int end = range.end->bind();
256
257 // This will happen for empty try blocks and for some cases of finally blocks:
258 //
259 // try {
260 // try {
261 // } finally {
262 // return 42;
263 // // *HERE*
264 // }
265 // } finally {
266 // print("things");
267 // }
268 //
269 // The return will pop scopes to execute the outer finally block. But this includes
270 // popping the try context for the inner try. The try context is live in the fall-through
271 // part of the finally block not because we will emit a handler that overlaps the finally,
272 // but because we haven't yet had a chance to plant the catch target. Then when we finish
273 // emitting code for the outer finally block, we repush the try contex, this time with a
274 // new start index. But that means that the start index for the try range corresponding
275 // to the inner-finally-following-the-return (marked as "*HERE*" above) will be greater
276 // than the end index of the try block. This is harmless since end < start handlers will
277 // never get matched in our logic, but we do the runtime a favor and choose to not emit
278 // such handlers at all.
279 if (end <= start)
280 continue;
281
282 UnlinkedHandlerInfo info(static_cast<uint32_t>(start), static_cast<uint32_t>(end),
283 static_cast<uint32_t>(range.tryData->target->bind()), range.tryData->handlerType);
284 m_codeBlock->addExceptionHandler(info);
285 }
286
287
288 if (isGeneratorOrAsyncFunctionBodyParseMode(m_codeBlock->parseMode()))
289 performGeneratorification(*this, m_codeBlock.get(), m_writer, m_generatorFrameSymbolTable.get(), m_generatorFrameSymbolTableIndex);
290
291 RELEASE_ASSERT(static_cast<unsigned>(m_codeBlock->numCalleeLocals()) < static_cast<unsigned>(FirstConstantRegisterIndex));
292 m_codeBlock->setInstructions(m_writer.finalize());
293
294 m_codeBlock->shrinkToFit();
295
296 if (m_expressionTooDeep)
297 return ParserError(ParserError::OutOfMemory);
298 return ParserError(ParserError::ErrorNone);
299}
300
301BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
302 : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
303 , m_codeGenerationMode(codeGenerationMode)
304 , m_scopeNode(programNode)
305 , m_thisRegister(CallFrame::thisArgumentOffset())
306 , m_codeType(GlobalCode)
307 , m_vm(vm)
308 , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction() || programNode->usesEval())
309{
310 ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());
311
312 m_codeBlock->setNumParameters(1); // Allocate space for "this"
313
314 emitEnter();
315
316 allocateAndEmitScope();
317
318 emitCheckTraps();
319
320 const FunctionStack& functionStack = programNode->functionStack();
321
322 for (auto* function : functionStack)
323 m_functionsToInitialize.append(std::make_pair(function, TopLevelFunctionVariable));
324
325 if (Options::validateBytecode()) {
326 for (auto& entry : programNode->varDeclarations())
327 RELEASE_ASSERT(entry.value.isVar());
328 }
329 codeBlock->setVariableDeclarations(programNode->varDeclarations());
330 codeBlock->setLexicalDeclarations(programNode->lexicalVariables());
331 // Even though this program may have lexical variables that go under TDZ, when linking the get_from_scope/put_to_scope
332 // operations we emit we will have ResolveTypes that implictly do TDZ checks. Therefore, we don't need
333 // additional TDZ checks on top of those. This is why we can omit pushing programNode->lexicalVariables()
334 // to the TDZ stack.
335
336 if (needsToUpdateArrowFunctionContext()) {
337 initializeArrowFunctionContextScopeIfNeeded();
338 emitPutThisToArrowFunctionContextScope();
339 }
340}
341
342BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
343 : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
344 , m_codeGenerationMode(codeGenerationMode)
345 , m_scopeNode(functionNode)
346 , m_codeType(FunctionCode)
347 , m_vm(vm)
348 , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
349 , m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
350 // FIXME: We should be able to have tail call elimination with the profiler
351 // enabled. This is currently not possible because the profiler expects
352 // op_will_call / op_did_call pairs before and after a call, which are not
353 // compatible with tail calls (we have no way of emitting op_did_call).
354 // https://bugs.webkit.org/show_bug.cgi?id=148819
355 //
356 // Note that we intentionally enable tail call for naked constructors since it does not have special code for "return".
357 , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && isStrictMode())
358 , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval())
359 , m_derivedContextType(codeBlock->derivedContextType())
360{
361 SymbolTable* functionSymbolTable = SymbolTable::create(m_vm);
362 functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
363 int symbolTableConstantIndex = 0;
364
365 FunctionParameters& parameters = *functionNode->parameters();
366 // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
367 // This implements IsSimpleParameterList in the Ecma 2015 spec.
368 // If IsSimpleParameterList is false, we will create a strict-mode like arguments object.
369 // IsSimpleParameterList is false if the argument list contains any default parameter values,
370 // a rest parameter, or any destructuring patterns.
371 // If we do have default parameters, destructuring parameters, or a rest parameter, our parameters will be allocated in a different scope.
372 bool isSimpleParameterList = parameters.isSimpleParameterList();
373
374 SourceParseMode parseMode = codeBlock->parseMode();
375
376 bool containsArrowOrEvalButNotInArrowBlock = ((functionNode->usesArrowFunction() && functionNode->doAnyInnerArrowFunctionsUseAnyFeature()) || functionNode->usesEval()) && !m_codeBlock->isArrowFunction();
377 bool shouldCaptureSomeOfTheThings = shouldEmitDebugHooks() || functionNode->needsActivation() || containsArrowOrEvalButNotInArrowBlock;
378
379 bool shouldCaptureAllOfTheThings = shouldEmitDebugHooks() || codeBlock->usesEval();
380 bool needsArguments = ((functionNode->usesArguments() && !codeBlock->isArrowFunction()) || codeBlock->usesEval() || (functionNode->usesArrowFunction() && !codeBlock->isArrowFunction() && isArgumentsUsedInInnerArrowFunction()));
381
382 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode)) {
383 // Generator and AsyncFunction never provides "arguments". "arguments" reference will be resolved in an upper generator function scope.
384 needsArguments = false;
385 }
386
387 if (isGeneratorOrAsyncFunctionWrapperParseMode(parseMode) && needsArguments) {
388 // Generator does not provide "arguments". Instead, wrapping GeneratorFunction provides "arguments".
389 // This is because arguments of a generator should be evaluated before starting it.
390 // To workaround it, we evaluate these arguments as arguments of a wrapping generator function, and reference it from a generator.
391 //
392 // function *gen(a, b = hello())
393 // {
394 // return {
395 // @generatorNext: function (@generator, @generatorState, @generatorValue, @generatorResumeMode, @generatorFrame)
396 // {
397 // arguments; // This `arguments` should reference to the gen's arguments.
398 // ...
399 // }
400 // }
401 // }
402 shouldCaptureSomeOfTheThings = true;
403 }
404
405 if (shouldCaptureAllOfTheThings)
406 functionNode->varDeclarations().markAllVariablesAsCaptured();
407
408 auto captures = scopedLambda<bool (UniquedStringImpl*)>([&] (UniquedStringImpl* uid) -> bool {
409 if (!shouldCaptureSomeOfTheThings)
410 return false;
411 if (needsArguments && uid == propertyNames().arguments.impl()) {
412 // Actually, we only need to capture the arguments object when we "need full activation"
413 // because of name scopes. But historically we did it this way, so for now we just preserve
414 // the old behavior.
415 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=143072
416 return true;
417 }
418 return functionNode->captures(uid);
419 });
420 auto varKind = [&] (UniquedStringImpl* uid) -> VarKind {
421 return captures(uid) ? VarKind::Scope : VarKind::Stack;
422 };
423
424 m_calleeRegister.setIndex(CallFrameSlot::callee);
425
426 initializeParameters(parameters);
427 ASSERT(!(isSimpleParameterList && m_restParameter));
428
429 emitEnter();
430
431 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode))
432 m_generatorRegister = &m_parameters[1];
433
434 allocateAndEmitScope();
435
436 emitCheckTraps();
437
438 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())) {
439 ASSERT(parseMode != SourceParseMode::GeneratorBodyMode);
440 ASSERT(!isAsyncFunctionBodyParseMode(parseMode));
441 bool isDynamicScope = functionNameScopeIsDynamic(codeBlock->usesEval(), codeBlock->isStrictMode());
442 bool isFunctionNameCaptured = captures(functionNode->ident().impl());
443 bool markAsCaptured = isDynamicScope || isFunctionNameCaptured;
444 emitPushFunctionNameScope(functionNode->ident(), &m_calleeRegister, markAsCaptured);
445 }
446
447 if (shouldCaptureSomeOfTheThings)
448 m_lexicalEnvironmentRegister = addVar();
449
450 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode) || shouldCaptureSomeOfTheThings || shouldEmitTypeProfilerHooks())
451 symbolTableConstantIndex = addConstantValue(functionSymbolTable)->index();
452
453 // We can allocate the "var" environment if we don't have default parameter expressions. If we have
454 // default parameter expressions, we have to hold off on allocating the "var" environment because
455 // the parent scope of the "var" environment is the parameter environment.
456 if (isSimpleParameterList)
457 initializeVarLexicalEnvironment(symbolTableConstantIndex, functionSymbolTable, shouldCaptureSomeOfTheThings);
458
459 // Figure out some interesting facts about our arguments.
460 bool capturesAnyArgumentByName = false;
461 if (functionNode->hasCapturedVariables()) {
462 FunctionParameters& parameters = *functionNode->parameters();
463 for (size_t i = 0; i < parameters.size(); ++i) {
464 auto pattern = parameters.at(i).first;
465 if (!pattern->isBindingNode())
466 continue;
467 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
468 capturesAnyArgumentByName |= captures(ident.impl());
469 }
470 }
471
472 if (capturesAnyArgumentByName)
473 ASSERT(m_lexicalEnvironmentRegister);
474
475 // Need to know what our functions are called. Parameters have some goofy behaviors when it
476 // comes to functions of the same name.
477 for (FunctionMetadataNode* function : functionNode->functionStack())
478 m_functions.add(function->ident().impl());
479
480 if (needsArguments) {
481 // Create the arguments object now. We may put the arguments object into the activation if
482 // it is captured. Either way, we create two arguments object variables: one is our
483 // private variable that is immutable, and another that is the user-visible variable. The
484 // immutable one is only used here, or during formal parameter resolutions if we opt for
485 // DirectArguments.
486
487 m_argumentsRegister = addVar();
488 m_argumentsRegister->ref();
489 }
490
491 if (needsArguments && !codeBlock->isStrictMode() && isSimpleParameterList) {
492 // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we
493 // use DirectArguments. With ScopedArguments, we lift all of our arguments into the
494 // activation.
495
496 if (capturesAnyArgumentByName) {
497 functionSymbolTable->setArgumentsLength(vm, parameters.size());
498
499 // For each parameter, we have two possibilities:
500 // Either it's a binding node with no function overlap, in which case it gets a name
501 // in the symbol table - or it just gets space reserved in the symbol table. Either
502 // way we lift the value into the scope.
503 for (unsigned i = 0; i < parameters.size(); ++i) {
504 ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
505 functionSymbolTable->setArgumentOffset(vm, i, offset);
506 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first)) {
507 VarOffset varOffset(offset);
508 SymbolTableEntry entry(varOffset);
509 // Stores to these variables via the ScopedArguments object will not do
510 // notifyWrite(), since that would be cumbersome. Also, watching formal
511 // parameters when "arguments" is in play is unlikely to be super profitable.
512 // So, we just disable it.
513 entry.disableWatching(m_vm);
514 functionSymbolTable->set(NoLockingNecessary, name, entry);
515 }
516 OpPutToScope::emit(this, m_lexicalEnvironmentRegister, UINT_MAX, virtualRegisterForArgument(1 + i), GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization), SymbolTableOrScopeDepth::symbolTable(VirtualRegister { symbolTableConstantIndex }), offset.offset());
517 }
518
519 // This creates a scoped arguments object and copies the overflow arguments into the
520 // scope. It's the equivalent of calling ScopedArguments::createByCopying().
521 OpCreateScopedArguments::emit(this, m_argumentsRegister, m_lexicalEnvironmentRegister);
522 } else {
523 // We're going to put all parameters into the DirectArguments object. First ensure
524 // that the symbol table knows that this is happening.
525 for (unsigned i = 0; i < parameters.size(); ++i) {
526 if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first))
527 functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i))));
528 }
529
530 OpCreateDirectArguments::emit(this, m_argumentsRegister);
531 }
532 } else if (isSimpleParameterList) {
533 // Create the formal parameters the normal way. Any of them could be captured, or not. If
534 // captured, lift them into the scope. We cannot do this if we have default parameter expressions
535 // because when default parameter expressions exist, they belong in their own lexical environment
536 // separate from the "var" lexical environment.
537 for (unsigned i = 0; i < parameters.size(); ++i) {
538 UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first);
539 if (!name)
540 continue;
541
542 if (!captures(name)) {
543 // This is the easy case - just tell the symbol table about the argument. It will
544 // be accessed directly.
545 functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(virtualRegisterForArgument(1 + i))));
546 continue;
547 }
548
549 ScopeOffset offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
550 const Identifier& ident =
551 static_cast<const BindingNode*>(parameters.at(i).first)->boundProperty();
552 functionSymbolTable->set(NoLockingNecessary, name, SymbolTableEntry(VarOffset(offset)));
553
554 OpPutToScope::emit(this, m_lexicalEnvironmentRegister, addConstant(ident), virtualRegisterForArgument(1 + i), GetPutInfo(ThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization), SymbolTableOrScopeDepth::symbolTable(VirtualRegister { symbolTableConstantIndex }), offset.offset());
555 }
556 }
557
558 if (needsArguments && (codeBlock->isStrictMode() || !isSimpleParameterList)) {
559 // Allocate a cloned arguments object.
560 OpCreateClonedArguments::emit(this, m_argumentsRegister);
561 }
562
563 // There are some variables that need to be preinitialized to something other than Undefined:
564 //
565 // - "arguments": unless it's used as a function or parameter, this should refer to the
566 // arguments object.
567 //
568 // - functions: these always override everything else.
569 //
570 // The most logical way to do all of this is to initialize none of the variables until now,
571 // and then initialize them in BytecodeGenerator::generate() in such an order that the rules
572 // for how these things override each other end up holding. We would initialize "arguments" first,
573 // then all arguments, then the functions.
574 //
575 // But some arguments are already initialized by default, since if they aren't captured and we
576 // don't have "arguments" then we just point the symbol table at the stack slot of those
577 // arguments. We end up initializing the rest of the arguments that have an uncomplicated
578 // binding (i.e. don't involve destructuring) above when figuring out how to lay them out,
579 // because that's just the simplest thing. This means that when we initialize them, we have to
580 // watch out for the things that override arguments (namely, functions).
581
582 // This is our final act of weirdness. "arguments" is overridden by everything except the
583 // callee. We add it to the symbol table if it's not already there and it's not an argument.
584 bool shouldCreateArgumentsVariableInParameterScope = false;
585 if (needsArguments) {
586 // If "arguments" is overridden by a function or destructuring parameter name, then it's
587 // OK for us to call createVariable() because it won't change anything. It's also OK for
588 // us to them tell BytecodeGenerator::generate() to write to it because it will do so
589 // before it initializes functions and destructuring parameters. But if "arguments" is
590 // overridden by a "simple" function parameter, then we have to bail: createVariable()
591 // would assert and BytecodeGenerator::generate() would write the "arguments" after the
592 // argument value had already been properly initialized.
593
594 bool haveParameterNamedArguments = false;
595 for (unsigned i = 0; i < parameters.size(); ++i) {
596 UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first);
597 if (name == propertyNames().arguments.impl()) {
598 haveParameterNamedArguments = true;
599 break;
600 }
601 }
602
603 bool shouldCreateArgumensVariable = !haveParameterNamedArguments
604 && !SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(m_codeBlock->parseMode());
605 shouldCreateArgumentsVariableInParameterScope = shouldCreateArgumensVariable && !isSimpleParameterList;
606 // Do not create arguments variable in case of Arrow function. Value will be loaded from parent scope
607 if (shouldCreateArgumensVariable && !shouldCreateArgumentsVariableInParameterScope) {
608 createVariable(
609 propertyNames().arguments, varKind(propertyNames().arguments.impl()), functionSymbolTable);
610
611 m_needToInitializeArguments = true;
612 }
613 }
614
615 for (FunctionMetadataNode* function : functionNode->functionStack()) {
616 const Identifier& ident = function->ident();
617 createVariable(ident, varKind(ident.impl()), functionSymbolTable);
618 m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
619 }
620 for (auto& entry : functionNode->varDeclarations()) {
621 ASSERT(!entry.value.isLet() && !entry.value.isConst());
622 if (!entry.value.isVar()) // This is either a parameter or callee.
623 continue;
624 if (shouldCreateArgumentsVariableInParameterScope && entry.key.get() == propertyNames().arguments.impl())
625 continue;
626 createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), functionSymbolTable, IgnoreExisting);
627 }
628
629
630 if (functionNode->needsNewTargetRegisterForThisScope() || isNewTargetUsedInInnerArrowFunction() || codeBlock->usesEval())
631 m_newTargetRegister = addVar();
632
633 switch (parseMode) {
634 case SourceParseMode::GeneratorWrapperFunctionMode:
635 case SourceParseMode::GeneratorWrapperMethodMode: {
636 m_generatorRegister = addVar();
637
638 // FIXME: Emit to_this only when Generator uses it.
639 // https://bugs.webkit.org/show_bug.cgi?id=151586
640 emitToThis();
641
642 emitCreateGenerator(m_generatorRegister, &m_calleeRegister);
643 break;
644 }
645
646 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
647 case SourceParseMode::AsyncGeneratorWrapperFunctionMode: {
648 m_generatorRegister = addVar();
649
650 // FIXME: Emit to_this only when Generator uses it.
651 // https://bugs.webkit.org/show_bug.cgi?id=151586
652 emitToThis();
653
654 emitCreateAsyncGenerator(m_generatorRegister, &m_calleeRegister);
655 break;
656 }
657
658 case SourceParseMode::AsyncArrowFunctionMode:
659 case SourceParseMode::AsyncMethodMode:
660 case SourceParseMode::AsyncFunctionMode: {
661 ASSERT(!isConstructor());
662 ASSERT(constructorKind() == ConstructorKind::None);
663 m_generatorRegister = addVar();
664 m_promiseRegister = addVar();
665
666 if (parseMode != SourceParseMode::AsyncArrowFunctionMode) {
667 // FIXME: Emit to_this only when AsyncFunctionBody uses it.
668 // https://bugs.webkit.org/show_bug.cgi?id=151586
669 emitToThis();
670 }
671
672 emitNewGenerator(m_generatorRegister);
673 emitNewPromise(promiseRegister(), m_isBuiltinFunction);
674 break;
675 }
676
677 case SourceParseMode::AsyncGeneratorBodyMode:
678 case SourceParseMode::AsyncFunctionBodyMode:
679 case SourceParseMode::AsyncArrowFunctionBodyMode:
680 case SourceParseMode::GeneratorBodyMode: {
681 // |this| is already filled correctly before here.
682 if (m_newTargetRegister)
683 emitLoad(m_newTargetRegister, jsUndefined());
684 break;
685 }
686
687 default: {
688 if (SourceParseMode::ArrowFunctionMode != parseMode) {
689 if (isConstructor()) {
690 if (m_newTargetRegister)
691 move(m_newTargetRegister, &m_thisRegister);
692 switch (constructorKind()) {
693 case ConstructorKind::Naked:
694 // Naked constructor not create |this| automatically.
695 break;
696 case ConstructorKind::None:
697 case ConstructorKind::Base:
698 emitCreateThis(&m_thisRegister);
699 break;
700 case ConstructorKind::Extends:
701 moveEmptyValue(&m_thisRegister);
702 break;
703 }
704 } else {
705 switch (constructorKind()) {
706 case ConstructorKind::None: {
707 bool shouldEmitToThis = false;
708 if (functionNode->usesThis() || codeBlock->usesEval() || m_scopeNode->doAnyInnerArrowFunctionsUseThis() || m_scopeNode->doAnyInnerArrowFunctionsUseEval())
709 shouldEmitToThis = true;
710 else if ((functionNode->usesSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty()) && !codeBlock->isStrictMode()) {
711 // We must emit to_this when we're not in strict mode because we
712 // will convert |this| to an object, and that object may be passed
713 // to a strict function as |this|. This is observable because that
714 // strict function's to_this will just return the object.
715 //
716 // We don't need to emit this for strict-mode code because
717 // strict-mode code may call another strict function, which will
718 // to_this if it directly uses this; this is OK, because we defer
719 // to_this until |this| is used directly. Strict-mode code might
720 // also call a sloppy mode function, and that will to_this, which
721 // will defer the conversion, again, until necessary.
722 shouldEmitToThis = true;
723 }
724
725 if (shouldEmitToThis)
726 emitToThis();
727 break;
728 }
729 case ConstructorKind::Naked:
730 emitThrowTypeError("Cannot call a constructor without |new|");
731 break;
732 case ConstructorKind::Base:
733 case ConstructorKind::Extends:
734 emitThrowTypeError("Cannot call a class constructor without |new|");
735 break;
736 }
737 }
738 }
739 break;
740 }
741 }
742
743 // We need load |super| & |this| for arrow function before initializeDefaultParameterValuesAndSetupFunctionScopeStack
744 // if we have default parameter expression. Because |super| & |this| values can be used there
745 if ((SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && !isSimpleParameterList) || parseMode == SourceParseMode::AsyncArrowFunctionBodyMode) {
746 if (functionNode->usesThis() || functionNode->usesSuperProperty())
747 emitLoadThisFromArrowFunctionLexicalEnvironment();
748
749 if (m_scopeNode->needsNewTargetRegisterForThisScope())
750 emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
751 }
752
753 if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunction()) {
754 bool canReuseLexicalEnvironment = isSimpleParameterList;
755 initializeArrowFunctionContextScopeIfNeeded(functionSymbolTable, canReuseLexicalEnvironment);
756 emitPutThisToArrowFunctionContextScope();
757 emitPutNewTargetToArrowFunctionContextScope();
758 emitPutDerivedConstructorToArrowFunctionContextScope();
759 }
760
761 // All "addVar()"s needs to happen before "initializeDefaultParameterValuesAndSetupFunctionScopeStack()" is called
762 // because a function's default parameter ExpressionNodes will use temporary registers.
763 pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);
764
765 Ref<Label> catchLabel = newLabel();
766 TryData* tryFormalParametersData = nullptr;
767 bool needTryCatch = isAsyncFunctionWrapperParseMode(parseMode) && !isSimpleParameterList;
768 if (needTryCatch) {
769 Ref<Label> tryFormalParametersStart = newEmittedLabel();
770 tryFormalParametersData = pushTry(tryFormalParametersStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
771 }
772
773 initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope);
774
775 if (needTryCatch) {
776 Ref<Label> didNotThrow = newLabel();
777 emitJump(didNotThrow.get());
778 emitLabel(catchLabel.get());
779 popTry(tryFormalParametersData, catchLabel.get());
780
781 RefPtr<RegisterID> thrownValue = newTemporary();
782 emitOutOfLineCatchHandler(thrownValue.get(), nullptr, tryFormalParametersData);
783
784 // @rejectPromiseWithFirstResolvingFunctionCallCheck(@promise, thrownValue);
785 // return @promise;
786 RefPtr<RegisterID> rejectPromise = moveLinkTimeConstant(nullptr, LinkTimeConstant::rejectPromiseWithFirstResolvingFunctionCallCheck);
787 CallArguments args(*this, nullptr, 2);
788 emitLoad(args.thisRegister(), jsUndefined());
789 move(args.argumentRegister(0), promiseRegister());
790 move(args.argumentRegister(1), thrownValue.get());
791 JSTextPosition divot(functionNode->firstLine(), functionNode->startOffset(), functionNode->lineStartOffset());
792 emitCall(newTemporary(), rejectPromise.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
793
794 emitReturn(promiseRegister());
795 emitLabel(didNotThrow.get());
796 }
797
798 // If we don't have default parameter expression, then loading |this| inside an arrow function must be done
799 // after initializeDefaultParameterValuesAndSetupFunctionScopeStack() because that function sets up the
800 // SymbolTable stack and emitLoadThisFromArrowFunctionLexicalEnvironment() consults the SymbolTable stack
801 if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(parseMode) && isSimpleParameterList) {
802 if (functionNode->usesThis() || functionNode->usesSuperProperty())
803 emitLoadThisFromArrowFunctionLexicalEnvironment();
804
805 if (m_scopeNode->needsNewTargetRegisterForThisScope())
806 emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
807 }
808
809 // Set up the lexical environment scope as the generator frame. We store the saved and resumed generator registers into this scope with the symbol keys.
810 // Since they are symbol keyed, these variables cannot be reached from the usual code.
811 if (isGeneratorOrAsyncFunctionBodyParseMode(parseMode)) {
812 m_generatorFrameSymbolTable.set(m_vm, functionSymbolTable);
813 m_generatorFrameSymbolTableIndex = symbolTableConstantIndex;
814 if (m_lexicalEnvironmentRegister)
815 move(generatorFrameRegister(), m_lexicalEnvironmentRegister);
816 else {
817 // It would be possible that generator does not need to suspend and resume any registers.
818 // In this case, we would like to avoid creating a lexical environment as much as possible.
819 // op_create_generator_frame_environment is a marker, which is similar to op_yield.
820 // Generatorification inserts lexical environment creation if necessary. Otherwise, we convert it to op_mov frame, `undefined`.
821 OpCreateGeneratorFrameEnvironment::emit(this, generatorFrameRegister(), scopeRegister(), VirtualRegister { symbolTableConstantIndex }, addConstantValue(jsUndefined()));
822 }
823 static_assert(static_cast<unsigned>(JSGenerator::Field::Frame) == static_cast<unsigned>(JSAsyncGenerator::Field::Frame));
824 emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::Frame), generatorFrameRegister());
825 }
826
827 bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
828 pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
829}
830
831BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
832 : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
833 , m_codeGenerationMode(codeGenerationMode)
834 , m_scopeNode(evalNode)
835 , m_thisRegister(CallFrame::thisArgumentOffset())
836 , m_codeType(EvalCode)
837 , m_vm(vm)
838 , m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
839 , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction() || evalNode->usesEval())
840 , m_derivedContextType(codeBlock->derivedContextType())
841{
842 m_codeBlock->setNumParameters(1);
843
844 pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);
845
846 emitEnter();
847
848 allocateAndEmitScope();
849
850 emitCheckTraps();
851
852 for (FunctionMetadataNode* function : evalNode->functionStack()) {
853 m_codeBlock->addFunctionDecl(makeFunction(function));
854 m_functionsToInitialize.append(std::make_pair(function, TopLevelFunctionVariable));
855 }
856
857 const VariableEnvironment& varDeclarations = evalNode->varDeclarations();
858 Vector<Identifier, 0, UnsafeVectorOverflow> variables;
859 Vector<Identifier, 0, UnsafeVectorOverflow> hoistedFunctions;
860 for (auto& entry : varDeclarations) {
861 ASSERT(entry.value.isVar());
862 ASSERT(entry.key->isAtom() || entry.key->isSymbol());
863 if (entry.value.isSloppyModeHoistingCandidate())
864 hoistedFunctions.append(Identifier::fromUid(m_vm, entry.key.get()));
865 else
866 variables.append(Identifier::fromUid(m_vm, entry.key.get()));
867 }
868 codeBlock->adoptVariables(variables);
869 codeBlock->adoptFunctionHoistingCandidates(WTFMove(hoistedFunctions));
870
871 if (evalNode->needsNewTargetRegisterForThisScope())
872 m_newTargetRegister = addVar();
873
874 if (codeBlock->isArrowFunctionContext() && (evalNode->usesThis() || evalNode->usesSuperProperty()))
875 emitLoadThisFromArrowFunctionLexicalEnvironment();
876
877 if (evalNode->needsNewTargetRegisterForThisScope())
878 emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
879
880 if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunctionContext() && !isDerivedConstructorContext()) {
881 initializeArrowFunctionContextScopeIfNeeded();
882 emitPutThisToArrowFunctionContextScope();
883 }
884
885 bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
886 pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
887}
888
889BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* parentScopeTDZVariables)
890 : BytecodeGeneratorBase(Strong<UnlinkedCodeBlock>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
891 , m_codeGenerationMode(codeGenerationMode)
892 , m_scopeNode(moduleProgramNode)
893 , m_thisRegister(CallFrame::thisArgumentOffset())
894 , m_codeType(ModuleCode)
895 , m_vm(vm)
896 , m_usesNonStrictEval(false)
897 , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction() || moduleProgramNode->usesEval())
898{
899 ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());
900
901 SymbolTable* moduleEnvironmentSymbolTable = SymbolTable::create(m_vm);
902 moduleEnvironmentSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
903 moduleEnvironmentSymbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope);
904
905 bool shouldCaptureAllOfTheThings = shouldEmitDebugHooks() || codeBlock->usesEval();
906 if (shouldCaptureAllOfTheThings)
907 moduleProgramNode->varDeclarations().markAllVariablesAsCaptured();
908
909 auto captures = [&] (UniquedStringImpl* uid) -> bool {
910 return moduleProgramNode->captures(uid);
911 };
912 auto lookUpVarKind = [&] (UniquedStringImpl* uid, const VariableEnvironmentEntry& entry) -> VarKind {
913 // Allocate the exported variables in the module environment.
914 if (entry.isExported())
915 return VarKind::Scope;
916
917 // Allocate the namespace variables in the module environment to instantiate
918 // it from the outside of the module code.
919 if (entry.isImportedNamespace())
920 return VarKind::Scope;
921
922 if (entry.isCaptured())
923 return VarKind::Scope;
924 return captures(uid) ? VarKind::Scope : VarKind::Stack;
925 };
926
927 emitEnter();
928
929 allocateAndEmitScope();
930
931 emitCheckTraps();
932
933 m_calleeRegister.setIndex(CallFrameSlot::callee);
934
935 m_codeBlock->setNumParameters(1); // Allocate space for "this"
936
937 // Now declare all variables.
938
939 createVariable(m_vm.propertyNames->builtinNames().metaPrivateName(), VarKind::Scope, moduleEnvironmentSymbolTable, VerifyExisting);
940
941 for (auto& entry : moduleProgramNode->varDeclarations()) {
942 ASSERT(!entry.value.isLet() && !entry.value.isConst());
943 if (!entry.value.isVar()) // This is either a parameter or callee.
944 continue;
945 // Imported bindings are not allocated in the module environment as usual variables' way.
946 // These references remain the "Dynamic" in the unlinked code block. Later, when linking
947 // the code block, we resolve the reference to the "ModuleVar".
948 if (entry.value.isImported() && !entry.value.isImportedNamespace())
949 continue;
950 createVariable(Identifier::fromUid(m_vm, entry.key.get()), lookUpVarKind(entry.key.get(), entry.value), moduleEnvironmentSymbolTable, IgnoreExisting);
951 }
952
953 VariableEnvironment& lexicalVariables = moduleProgramNode->lexicalVariables();
954 instantiateLexicalVariables(lexicalVariables, moduleEnvironmentSymbolTable, ScopeRegisterType::Block, lookUpVarKind);
955
956 // We keep the symbol table in the constant pool.
957 RegisterID* constantSymbolTable = nullptr;
958 if (shouldEmitTypeProfilerHooks())
959 constantSymbolTable = addConstantValue(moduleEnvironmentSymbolTable);
960 else
961 constantSymbolTable = addConstantValue(moduleEnvironmentSymbolTable->cloneScopePart(m_vm));
962
963 pushTDZVariables(lexicalVariables, TDZCheckOptimization::Optimize, TDZRequirement::UnderTDZ);
964 bool isWithScope = false;
965 m_lexicalScopeStack.append({ moduleEnvironmentSymbolTable, m_topMostScope, isWithScope, constantSymbolTable->index() });
966 emitPrefillStackTDZVariables(lexicalVariables, moduleEnvironmentSymbolTable);
967
968 // makeFunction assumes that there's correct TDZ stack entries.
969 // So it should be called after putting our lexical environment to the TDZ stack correctly.
970
971 for (FunctionMetadataNode* function : moduleProgramNode->functionStack()) {
972 const auto& iterator = moduleProgramNode->varDeclarations().find(function->ident().impl());
973 RELEASE_ASSERT(iterator != moduleProgramNode->varDeclarations().end());
974 RELEASE_ASSERT(!iterator->value.isImported());
975
976 VarKind varKind = lookUpVarKind(iterator->key.get(), iterator->value);
977 if (varKind == VarKind::Scope) {
978 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
979 // Section 15.2.1.16.4, step 16-a-iv-1.
980 // All heap allocated function declarations should be instantiated when the module environment
981 // is created. They include the exported function declarations and not-exported-but-heap-allocated
982 // function declarations. This is required because exported function should be instantiated before
983 // executing the any module in the dependency graph. This enables the modules to link the imported
984 // bindings before executing the any module code.
985 //
986 // And since function declarations are instantiated before executing the module body code, the spec
987 // allows the functions inside the module to be executed before its module body is executed under
988 // the circular dependencies. The following is the example.
989 //
990 // Module A (executed first):
991 // import { b } from "B";
992 // // Here, the module "B" is not executed yet, but the function declaration is already instantiated.
993 // // So we can call the function exported from "B".
994 // b();
995 //
996 // export function a() {
997 // }
998 //
999 // Module B (executed second):
1000 // import { a } from "A";
1001 //
1002 // export function b() {
1003 // c();
1004 // }
1005 //
1006 // // c is not exported, but since it is referenced from the b, we should instantiate it before
1007 // // executing the "B" module code.
1008 // function c() {
1009 // a();
1010 // }
1011 //
1012 // Module EntryPoint (executed last):
1013 // import "B";
1014 // import "A";
1015 //
1016 m_codeBlock->addFunctionDecl(makeFunction(function));
1017 } else {
1018 // Stack allocated functions can be allocated when executing the module's body.
1019 m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
1020 }
1021 }
1022
1023 // Remember the constant register offset to the top-most symbol table. This symbol table will be
1024 // cloned in the code block linking. After that, to create the module environment, we retrieve
1025 // the cloned symbol table from the linked code block by using this offset.
1026 codeBlock->setModuleEnvironmentSymbolTableConstantRegisterOffset(constantSymbolTable->index());
1027}
1028
1029BytecodeGenerator::~BytecodeGenerator()
1030{
1031}
1032
1033void BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack(
1034 FunctionParameters& parameters, bool isSimpleParameterList, FunctionNode* functionNode, SymbolTable* functionSymbolTable,
1035 int symbolTableConstantIndex, const ScopedLambda<bool (UniquedStringImpl*)>& captures, bool shouldCreateArgumentsVariableInParameterScope)
1036{
1037 Vector<std::pair<Identifier, RefPtr<RegisterID>>> valuesToMoveIntoVars;
1038 ASSERT(!(isSimpleParameterList && shouldCreateArgumentsVariableInParameterScope));
1039 if (!isSimpleParameterList) {
1040 // Refer to the ES6 spec section 9.2.12: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
1041 // This implements step 21.
1042 VariableEnvironment environment;
1043 Vector<Identifier> allParameterNames;
1044 for (unsigned i = 0; i < parameters.size(); i++)
1045 parameters.at(i).first->collectBoundIdentifiers(allParameterNames);
1046 if (shouldCreateArgumentsVariableInParameterScope)
1047 allParameterNames.append(propertyNames().arguments);
1048 IdentifierSet parameterSet;
1049 for (auto& ident : allParameterNames) {
1050 parameterSet.add(ident.impl());
1051 auto addResult = environment.add(ident);
1052 addResult.iterator->value.setIsLet(); // When we have default parameter expressions, parameters act like "let" variables.
1053 if (captures(ident.impl()))
1054 addResult.iterator->value.setIsCaptured();
1055 }
1056 // This implements step 25 of section 9.2.12.
1057 pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
1058
1059 if (shouldCreateArgumentsVariableInParameterScope) {
1060 Variable argumentsVariable = variable(propertyNames().arguments);
1061 initializeVariable(argumentsVariable, m_argumentsRegister);
1062 liftTDZCheckIfPossible(argumentsVariable);
1063 }
1064
1065 RefPtr<RegisterID> temp = newTemporary();
1066 for (unsigned i = 0; i < parameters.size(); i++) {
1067 std::pair<DestructuringPatternNode*, ExpressionNode*> parameter = parameters.at(i);
1068 if (parameter.first->isRestParameter())
1069 continue;
1070 if ((i + 1) < m_parameters.size())
1071 move(temp.get(), &m_parameters[i + 1]);
1072 else
1073 emitGetArgument(temp.get(), i);
1074 if (parameter.second) {
1075 RefPtr<RegisterID> condition = emitIsUndefined(newTemporary(), temp.get());
1076 Ref<Label> skipDefaultParameterBecauseNotUndefined = newLabel();
1077 emitJumpIfFalse(condition.get(), skipDefaultParameterBecauseNotUndefined.get());
1078 emitNode(temp.get(), parameter.second);
1079 emitLabel(skipDefaultParameterBecauseNotUndefined.get());
1080 }
1081
1082 parameter.first->bindValue(*this, temp.get());
1083 }
1084
1085 // Final act of weirdness for default parameters. If a "var" also
1086 // has the same name as a parameter, it should start out as the
1087 // value of that parameter. Note, though, that they will be distinct
1088 // bindings.
1089 // This is step 28 of section 9.2.12.
1090 for (auto& entry : functionNode->varDeclarations()) {
1091 if (!entry.value.isVar()) // This is either a parameter or callee.
1092 continue;
1093
1094 if (parameterSet.contains(entry.key)) {
1095 Identifier ident = Identifier::fromUid(m_vm, entry.key.get());
1096 Variable var = variable(ident);
1097 RegisterID* scope = emitResolveScope(nullptr, var);
1098 RefPtr<RegisterID> value = emitGetFromScope(newTemporary(), scope, var, DoNotThrowIfNotFound);
1099 valuesToMoveIntoVars.append(std::make_pair(ident, value));
1100 }
1101 }
1102
1103 // Functions with default parameter expressions must have a separate environment
1104 // record for parameters and "var"s. The "var" environment record must have the
1105 // parameter environment record as its parent.
1106 // See step 28 of section 9.2.12.
1107 bool hasCapturedVariables = !!m_lexicalEnvironmentRegister;
1108 initializeVarLexicalEnvironment(symbolTableConstantIndex, functionSymbolTable, hasCapturedVariables);
1109 }
1110
1111 // This completes step 28 of section 9.2.12.
1112 for (unsigned i = 0; i < valuesToMoveIntoVars.size(); i++) {
1113 ASSERT(!isSimpleParameterList);
1114 Variable var = variable(valuesToMoveIntoVars[i].first);
1115 RegisterID* scope = emitResolveScope(nullptr, var);
1116 emitPutToScope(scope, var, valuesToMoveIntoVars[i].second.get(), DoNotThrowIfNotFound, InitializationMode::NotInitialization);
1117 }
1118}
1119
1120bool BytecodeGenerator::needsDerivedConstructorInArrowFunctionLexicalEnvironment()
1121{
1122 ASSERT(m_codeBlock->isClassContext() || !(isConstructor() && constructorKind() == ConstructorKind::Extends));
1123 return m_codeBlock->isClassContext() && isSuperUsedInInnerArrowFunction();
1124}
1125
1126void BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded(SymbolTable* functionSymbolTable, bool canReuseLexicalEnvironment)
1127{
1128 ASSERT(!m_arrowFunctionContextLexicalEnvironmentRegister);
1129
1130 if (canReuseLexicalEnvironment && m_lexicalEnvironmentRegister) {
1131 RELEASE_ASSERT(!m_codeBlock->isArrowFunction());
1132 RELEASE_ASSERT(functionSymbolTable);
1133
1134 m_arrowFunctionContextLexicalEnvironmentRegister = m_lexicalEnvironmentRegister;
1135
1136 ScopeOffset offset;
1137
1138 if (isThisUsedInInnerArrowFunction()) {
1139 offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
1140 functionSymbolTable->set(NoLockingNecessary, propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset)));
1141 }
1142
1143 if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) {
1144 offset = functionSymbolTable->takeNextScopeOffset();
1145 functionSymbolTable->set(NoLockingNecessary, propertyNames().builtinNames().newTargetLocalPrivateName().impl(), SymbolTableEntry(VarOffset(offset)));
1146 }
1147
1148 if (needsDerivedConstructorInArrowFunctionLexicalEnvironment()) {
1149 offset = functionSymbolTable->takeNextScopeOffset(NoLockingNecessary);
1150 functionSymbolTable->set(NoLockingNecessary, propertyNames().builtinNames().derivedConstructorPrivateName().impl(), SymbolTableEntry(VarOffset(offset)));
1151 }
1152
1153 return;
1154 }
1155
1156 VariableEnvironment environment;
1157
1158 if (isThisUsedInInnerArrowFunction()) {
1159 auto addResult = environment.add(propertyNames().thisIdentifier);
1160 addResult.iterator->value.setIsCaptured();
1161 addResult.iterator->value.setIsLet();
1162 }
1163
1164 if (m_codeType == FunctionCode && isNewTargetUsedInInnerArrowFunction()) {
1165 auto addTarget = environment.add(propertyNames().builtinNames().newTargetLocalPrivateName());
1166 addTarget.iterator->value.setIsCaptured();
1167 addTarget.iterator->value.setIsLet();
1168 }
1169
1170 if (needsDerivedConstructorInArrowFunctionLexicalEnvironment()) {
1171 auto derivedConstructor = environment.add(propertyNames().builtinNames().derivedConstructorPrivateName());
1172 derivedConstructor.iterator->value.setIsCaptured();
1173 derivedConstructor.iterator->value.setIsLet();
1174 }
1175
1176 if (environment.size() > 0) {
1177 size_t size = m_lexicalScopeStack.size();
1178 pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
1179
1180 ASSERT_UNUSED(size, m_lexicalScopeStack.size() == size + 1);
1181
1182 m_arrowFunctionContextLexicalEnvironmentRegister = m_lexicalScopeStack.last().m_scope;
1183 }
1184}
1185
1186RegisterID* BytecodeGenerator::initializeNextParameter()
1187{
1188 VirtualRegister reg = virtualRegisterForArgument(m_codeBlock->numParameters());
1189 m_parameters.grow(m_parameters.size() + 1);
1190 auto& parameter = registerFor(reg);
1191 parameter.setIndex(reg.offset());
1192 m_codeBlock->addParameter();
1193 return &parameter;
1194}
1195
1196void BytecodeGenerator::initializeParameters(FunctionParameters& parameters)
1197{
1198 // Make sure the code block knows about all of our parameters, and make sure that parameters
1199 // needing destructuring are noted.
1200 m_thisRegister.setIndex(initializeNextParameter()->index()); // this
1201
1202 bool nonSimpleArguments = false;
1203 for (unsigned i = 0; i < parameters.size(); ++i) {
1204 auto parameter = parameters.at(i);
1205 auto pattern = parameter.first;
1206 if (pattern->isRestParameter()) {
1207 RELEASE_ASSERT(!m_restParameter);
1208 m_restParameter = static_cast<RestParameterNode*>(pattern);
1209 nonSimpleArguments = true;
1210 continue;
1211 }
1212 if (parameter.second) {
1213 nonSimpleArguments = true;
1214 continue;
1215 }
1216 if (!nonSimpleArguments)
1217 initializeNextParameter();
1218 }
1219}
1220
1221void BytecodeGenerator::initializeVarLexicalEnvironment(int symbolTableConstantIndex, SymbolTable* functionSymbolTable, bool hasCapturedVariables)
1222{
1223 if (hasCapturedVariables) {
1224 RELEASE_ASSERT(m_lexicalEnvironmentRegister);
1225 OpCreateLexicalEnvironment::emit(this, m_lexicalEnvironmentRegister, scopeRegister(), VirtualRegister { symbolTableConstantIndex }, addConstantValue(jsUndefined()));
1226
1227 OpMov::emit(this, scopeRegister(), m_lexicalEnvironmentRegister);
1228
1229 pushLocalControlFlowScope();
1230 }
1231 bool isWithScope = false;
1232 m_lexicalScopeStack.append({ functionSymbolTable, m_lexicalEnvironmentRegister, isWithScope, symbolTableConstantIndex });
1233 m_varScopeLexicalScopeStackIndex = m_lexicalScopeStack.size() - 1;
1234}
1235
1236UniquedStringImpl* BytecodeGenerator::visibleNameForParameter(DestructuringPatternNode* pattern)
1237{
1238 if (pattern->isBindingNode()) {
1239 const Identifier& ident = static_cast<const BindingNode*>(pattern)->boundProperty();
1240 if (!m_functions.contains(ident.impl()))
1241 return ident.impl();
1242 }
1243 return nullptr;
1244}
1245
1246RegisterID* BytecodeGenerator::newBlockScopeVariable()
1247{
1248 reclaimFreeRegisters();
1249
1250 return newRegister();
1251}
1252
1253Ref<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
1254{
1255 shrinkToFit(m_labelScopes);
1256
1257 // Allocate new label scope.
1258 m_labelScopes.append(type, name, labelScopeDepth(), newLabel(), type == LabelScope::Loop ? RefPtr<Label>(newLabel()) : RefPtr<Label>()); // Only loops have continue targets.
1259 return m_labelScopes.last();
1260}
1261
1262void BytecodeGenerator::emitEnter()
1263{
1264 OpEnter::emit(this);
1265
1266 if (LIKELY(Options::optimizeRecursiveTailCalls())) {
1267 // We must add the end of op_enter as a potential jump target, because the bytecode parser may decide to split its basic block
1268 // to have somewhere to jump to if there is a recursive tail-call that points to this function.
1269 m_codeBlock->addJumpTarget(instructions().size());
1270 // This disables peephole optimizations when an instruction is a jump target
1271 m_lastOpcodeID = op_end;
1272 }
1273}
1274
1275void BytecodeGenerator::emitLoopHint()
1276{
1277 OpLoopHint::emit(this);
1278 emitCheckTraps();
1279}
1280
1281void BytecodeGenerator::emitJump(Label& target)
1282{
1283 OpJmp::emit(this, target.bind(this));
1284}
1285
1286void BytecodeGenerator::emitCheckTraps()
1287{
1288 OpCheckTraps::emit(this);
1289}
1290
1291void ALWAYS_INLINE BytecodeGenerator::rewind()
1292{
1293 ASSERT(m_lastInstruction.isValid());
1294 m_lastOpcodeID = op_end;
1295 m_writer.rewind(m_lastInstruction);
1296}
1297
1298template<typename BinOp, typename JmpOp>
1299bool BytecodeGenerator::fuseCompareAndJump(RegisterID* cond, Label& target, bool swapOperands)
1300{
1301 ASSERT(canDoPeepholeOptimization());
1302 auto binop = m_lastInstruction->as<BinOp>();
1303 if (cond->index() == binop.m_dst.offset() && cond->isTemporary() && !cond->refCount()) {
1304 rewind();
1305
1306 if (swapOperands)
1307 std::swap(binop.m_lhs, binop.m_rhs);
1308
1309 JmpOp::emit(this, binop.m_lhs, binop.m_rhs, target.bind(this));
1310 return true;
1311 }
1312 return false;
1313}
1314
1315template<typename UnaryOp, typename JmpOp>
1316bool BytecodeGenerator::fuseTestAndJmp(RegisterID* cond, Label& target)
1317{
1318 ASSERT(canDoPeepholeOptimization());
1319 auto unop = m_lastInstruction->as<UnaryOp>();
1320 if (cond->index() == unop.m_dst.offset() && cond->isTemporary() && !cond->refCount()) {
1321 rewind();
1322
1323 JmpOp::emit(this, unop.m_operand, target.bind(this));
1324 return true;
1325 }
1326 return false;
1327}
1328
1329void BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label& target)
1330{
1331 if (canDoPeepholeOptimization()) {
1332 if (m_lastOpcodeID == op_less) {
1333 if (fuseCompareAndJump<OpLess, OpJless>(cond, target))
1334 return;
1335 } else if (m_lastOpcodeID == op_lesseq) {
1336 if (fuseCompareAndJump<OpLesseq, OpJlesseq>(cond, target))
1337 return;
1338 } else if (m_lastOpcodeID == op_greater) {
1339 if (fuseCompareAndJump<OpGreater, OpJgreater>(cond, target))
1340 return;
1341 } else if (m_lastOpcodeID == op_greatereq) {
1342 if (fuseCompareAndJump<OpGreatereq, OpJgreatereq>(cond, target))
1343 return;
1344 } else if (m_lastOpcodeID == op_eq) {
1345 if (fuseCompareAndJump<OpEq, OpJeq>(cond, target))
1346 return;
1347 } else if (m_lastOpcodeID == op_stricteq) {
1348 if (fuseCompareAndJump<OpStricteq, OpJstricteq>(cond, target))
1349 return;
1350 } else if (m_lastOpcodeID == op_neq) {
1351 if (fuseCompareAndJump<OpNeq, OpJneq>(cond, target))
1352 return;
1353 } else if (m_lastOpcodeID == op_nstricteq) {
1354 if (fuseCompareAndJump<OpNstricteq, OpJnstricteq>(cond, target))
1355 return;
1356 } else if (m_lastOpcodeID == op_below) {
1357 if (fuseCompareAndJump<OpBelow, OpJbelow>(cond, target))
1358 return;
1359 } else if (m_lastOpcodeID == op_beloweq) {
1360 if (fuseCompareAndJump<OpBeloweq, OpJbeloweq>(cond, target))
1361 return;
1362 } else if (m_lastOpcodeID == op_eq_null && target.isForward()) {
1363 if (fuseTestAndJmp<OpEqNull, OpJeqNull>(cond, target))
1364 return;
1365 } else if (m_lastOpcodeID == op_neq_null && target.isForward()) {
1366 if (fuseTestAndJmp<OpNeqNull, OpJneqNull>(cond, target))
1367 return;
1368 } else if (m_lastOpcodeID == op_is_undefined_or_null && target.isForward()) {
1369 if (fuseTestAndJmp<OpIsUndefinedOrNull, OpJundefinedOrNull>(cond, target))
1370 return;
1371 }
1372 }
1373
1374 OpJtrue::emit(this, cond, target.bind(this));
1375}
1376
1377void BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label& target)
1378{
1379 if (canDoPeepholeOptimization()) {
1380 if (m_lastOpcodeID == op_less && target.isForward()) {
1381 if (fuseCompareAndJump<OpLess, OpJnless>(cond, target))
1382 return;
1383 } else if (m_lastOpcodeID == op_lesseq && target.isForward()) {
1384 if (fuseCompareAndJump<OpLesseq, OpJnlesseq>(cond, target))
1385 return;
1386 } else if (m_lastOpcodeID == op_greater && target.isForward()) {
1387 if (fuseCompareAndJump<OpGreater, OpJngreater>(cond, target))
1388 return;
1389 } else if (m_lastOpcodeID == op_greatereq && target.isForward()) {
1390 if (fuseCompareAndJump<OpGreatereq, OpJngreatereq>(cond, target))
1391 return;
1392 } else if (m_lastOpcodeID == op_eq && target.isForward()) {
1393 if (fuseCompareAndJump<OpEq, OpJneq>(cond, target))
1394 return;
1395 } else if (m_lastOpcodeID == op_stricteq && target.isForward()) {
1396 if (fuseCompareAndJump<OpStricteq, OpJnstricteq>(cond, target))
1397 return;
1398 } else if (m_lastOpcodeID == op_neq && target.isForward()) {
1399 if (fuseCompareAndJump<OpNeq, OpJeq>(cond, target))
1400 return;
1401 } else if (m_lastOpcodeID == op_nstricteq && target.isForward()) {
1402 if (fuseCompareAndJump<OpNstricteq, OpJstricteq>(cond, target))
1403 return;
1404 } else if (m_lastOpcodeID == op_below && target.isForward()) {
1405 if (fuseCompareAndJump<OpBelow, OpJbeloweq>(cond, target, true))
1406 return;
1407 } else if (m_lastOpcodeID == op_beloweq && target.isForward()) {
1408 if (fuseCompareAndJump<OpBeloweq, OpJbelow>(cond, target, true))
1409 return;
1410 } else if (m_lastOpcodeID == op_not) {
1411 if (fuseTestAndJmp<OpNot, OpJtrue>(cond, target))
1412 return;
1413 } else if (m_lastOpcodeID == op_eq_null && target.isForward()) {
1414 if (fuseTestAndJmp<OpEqNull, OpJneqNull>(cond, target))
1415 return;
1416 } else if (m_lastOpcodeID == op_neq_null && target.isForward()) {
1417 if (fuseTestAndJmp<OpNeqNull, OpJeqNull>(cond, target))
1418 return;
1419 } else if (m_lastOpcodeID == op_is_undefined_or_null && target.isForward()) {
1420 if (fuseTestAndJmp<OpIsUndefinedOrNull, OpJnundefinedOrNull>(cond, target))
1421 return;
1422 }
1423 }
1424
1425 OpJfalse::emit(this, cond, target.bind(this));
1426}
1427
1428void BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label& target)
1429{
1430 OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::callFunction), target.bind(this));
1431}
1432
1433void BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label& target)
1434{
1435 OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::applyFunction), target.bind(this));
1436}
1437
1438bool BytecodeGenerator::hasConstant(const Identifier& ident) const
1439{
1440 UniquedStringImpl* rep = ident.impl();
1441 return m_identifierMap.contains(rep);
1442}
1443
1444unsigned BytecodeGenerator::addConstant(const Identifier& ident)
1445{
1446 UniquedStringImpl* rep = ident.impl();
1447 IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
1448 if (result.isNewEntry)
1449 m_codeBlock->addIdentifier(ident);
1450
1451 return result.iterator->value;
1452}
1453
1454// We can't hash JSValue(), so we use a dedicated data member to cache it.
1455RegisterID* BytecodeGenerator::addConstantEmptyValue()
1456{
1457 if (!m_emptyValueRegister) {
1458 int index = addConstantIndex();
1459 m_codeBlock->addConstant(JSValue());
1460 m_emptyValueRegister = &m_constantPoolRegisters[index];
1461 }
1462
1463 return m_emptyValueRegister;
1464}
1465
1466RegisterID* BytecodeGenerator::addConstantValue(JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
1467{
1468 if (!v)
1469 return addConstantEmptyValue();
1470
1471 int index = m_nextConstantOffset;
1472
1473 if (sourceCodeRepresentation == SourceCodeRepresentation::Double && v.isInt32())
1474 v = jsDoubleNumber(v.asNumber());
1475 EncodedJSValueWithRepresentation valueMapKey { JSValue::encode(v), sourceCodeRepresentation };
1476 JSValueMap::AddResult result = m_jsValueMap.add(valueMapKey, m_nextConstantOffset);
1477 if (result.isNewEntry) {
1478 addConstantIndex();
1479 m_codeBlock->addConstant(v, sourceCodeRepresentation);
1480 } else
1481 index = result.iterator->value;
1482 return &m_constantPoolRegisters[index];
1483}
1484
1485RegisterID* BytecodeGenerator::moveLinkTimeConstant(RegisterID* dst, LinkTimeConstant type)
1486{
1487 RegisterID* constant = m_linkTimeConstantRegisters.ensure(type, [&] {
1488 int index = addConstantIndex();
1489 m_codeBlock->addConstant(type);
1490 return &m_constantPoolRegisters[index];
1491 }).iterator->value;
1492 if (!dst)
1493 return constant;
1494
1495 OpMov::emit(this, dst, constant);
1496
1497 return dst;
1498}
1499
1500RegisterID* BytecodeGenerator::moveEmptyValue(RegisterID* dst)
1501{
1502 RefPtr<RegisterID> emptyValue = addConstantEmptyValue();
1503
1504 OpMov::emit(this, dst, emptyValue.get());
1505
1506 return dst;
1507}
1508
1509RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
1510{
1511 ASSERT(src != m_emptyValueRegister);
1512
1513 m_staticPropertyAnalyzer.mov(dst, src);
1514 OpMov::emit(this, dst, src);
1515
1516 return dst;
1517}
1518
1519RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src, ResultType type)
1520{
1521 switch (opcodeID) {
1522 case op_not:
1523 emitUnaryOp<OpNot>(dst, src);
1524 break;
1525 case op_negate:
1526 OpNegate::emit(this, dst, src, type);
1527 break;
1528 case op_bitnot:
1529 emitUnaryOp<OpBitnot>(dst, src);
1530 break;
1531 case op_to_number:
1532 emitUnaryOp<OpToNumber>(dst, src);
1533 break;
1534 case op_to_numeric:
1535 emitUnaryOp<OpToNumeric>(dst, src);
1536 break;
1537 default:
1538 ASSERT_NOT_REACHED();
1539 }
1540 return dst;
1541}
1542
1543RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
1544{
1545 switch (opcodeID) {
1546 case op_eq:
1547 return emitBinaryOp<OpEq>(dst, src1, src2, types);
1548 case op_neq:
1549 return emitBinaryOp<OpNeq>(dst, src1, src2, types);
1550 case op_stricteq:
1551 return emitBinaryOp<OpStricteq>(dst, src1, src2, types);
1552 case op_nstricteq:
1553 return emitBinaryOp<OpNstricteq>(dst, src1, src2, types);
1554 case op_less:
1555 return emitBinaryOp<OpLess>(dst, src1, src2, types);
1556 case op_lesseq:
1557 return emitBinaryOp<OpLesseq>(dst, src1, src2, types);
1558 case op_greater:
1559 return emitBinaryOp<OpGreater>(dst, src1, src2, types);
1560 case op_greatereq:
1561 return emitBinaryOp<OpGreatereq>(dst, src1, src2, types);
1562 case op_below:
1563 return emitBinaryOp<OpBelow>(dst, src1, src2, types);
1564 case op_beloweq:
1565 return emitBinaryOp<OpBeloweq>(dst, src1, src2, types);
1566 case op_mod:
1567 return emitBinaryOp<OpMod>(dst, src1, src2, types);
1568 case op_pow:
1569 return emitBinaryOp<OpPow>(dst, src1, src2, types);
1570 case op_lshift:
1571 return emitBinaryOp<OpLshift>(dst, src1, src2, types);
1572 case op_rshift:
1573 return emitBinaryOp<OpRshift>(dst, src1, src2, types);
1574 case op_urshift:
1575 return emitBinaryOp<OpUrshift>(dst, src1, src2, types);
1576 case op_add:
1577 return emitBinaryOp<OpAdd>(dst, src1, src2, types);
1578 case op_mul:
1579 return emitBinaryOp<OpMul>(dst, src1, src2, types);
1580 case op_div:
1581 return emitBinaryOp<OpDiv>(dst, src1, src2, types);
1582 case op_sub:
1583 return emitBinaryOp<OpSub>(dst, src1, src2, types);
1584 case op_bitand:
1585 return emitBinaryOp<OpBitand>(dst, src1, src2, types);
1586 case op_bitxor:
1587 return emitBinaryOp<OpBitxor>(dst, src1, src2, types);
1588 case op_bitor:
1589 return emitBinaryOp<OpBitor>(dst, src1, src2, types);
1590 default:
1591 ASSERT_NOT_REACHED();
1592 return nullptr;
1593 }
1594}
1595
1596RegisterID* BytecodeGenerator::emitToObject(RegisterID* dst, RegisterID* src, const Identifier& message)
1597{
1598 OpToObject::emit(this, dst, src, addConstant(message));
1599 return dst;
1600}
1601
1602RegisterID* BytecodeGenerator::emitToNumber(RegisterID* dst, RegisterID* src)
1603{
1604 return emitUnaryOp<OpToNumber>(dst, src);
1605}
1606
1607RegisterID* BytecodeGenerator::emitToNumeric(RegisterID* dst, RegisterID* src)
1608{
1609 return emitUnaryOp<OpToNumeric>(dst, src);
1610}
1611
1612RegisterID* BytecodeGenerator::emitToString(RegisterID* dst, RegisterID* src)
1613{
1614 return emitUnaryOp<OpToString>(dst, src);
1615}
1616
1617RegisterID* BytecodeGenerator::emitTypeOf(RegisterID* dst, RegisterID* src)
1618{
1619 return emitUnaryOp<OpTypeof>(dst, src);
1620}
1621
1622RegisterID* BytecodeGenerator::emitInc(RegisterID* srcDst)
1623{
1624 OpInc::emit(this, srcDst);
1625 return srcDst;
1626}
1627
1628RegisterID* BytecodeGenerator::emitDec(RegisterID* srcDst)
1629{
1630 OpDec::emit(this, srcDst);
1631 return srcDst;
1632}
1633
1634bool BytecodeGenerator::emitEqualityOpImpl(RegisterID* dst, RegisterID* src1, RegisterID* src2)
1635{
1636 if (!canDoPeepholeOptimization())
1637 return false;
1638
1639 if (m_lastInstruction->is<OpTypeof>()) {
1640 auto op = m_lastInstruction->as<OpTypeof>();
1641 if (src1->index() == op.m_dst.offset()
1642 && src1->isTemporary()
1643 && m_codeBlock->isConstantRegisterIndex(src2->index())
1644 && m_codeBlock->constantRegister(src2->index()).get().isString()) {
1645 const String& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
1646 if (value == "undefined") {
1647 rewind();
1648 OpIsUndefined::emit(this, dst, op.m_value);
1649 return true;
1650 }
1651 if (value == "boolean") {
1652 rewind();
1653 OpIsBoolean::emit(this, dst, op.m_value);
1654 return true;
1655 }
1656 if (value == "number") {
1657 rewind();
1658 OpIsNumber::emit(this, dst, op.m_value);
1659 return true;
1660 }
1661 if (value == "string") {
1662 rewind();
1663 OpIsCellWithType::emit(this, dst, op.m_value, StringType);
1664 return true;
1665 }
1666 if (value == "symbol") {
1667 rewind();
1668 OpIsCellWithType::emit(this, dst, op.m_value, SymbolType);
1669 return true;
1670 }
1671 if (Options::useBigInt() && value == "bigint") {
1672 rewind();
1673 OpIsCellWithType::emit(this, dst, op.m_value, BigIntType);
1674 return true;
1675 }
1676 if (value == "object") {
1677 rewind();
1678 OpIsObjectOrNull::emit(this, dst, op.m_value);
1679 return true;
1680 }
1681 if (value == "function") {
1682 rewind();
1683 OpIsFunction::emit(this, dst, op.m_value);
1684 return true;
1685 }
1686 }
1687 }
1688
1689 return false;
1690}
1691
1692void BytecodeGenerator::emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
1693{
1694 ASSERT(shouldEmitTypeProfilerHooks());
1695
1696 unsigned start = startDivot.offset; // Ranges are inclusive of their endpoints, AND 0 indexed.
1697 unsigned end = endDivot.offset - 1; // End Ranges already go one past the inclusive range, so subtract 1.
1698 unsigned instructionOffset = instructions().size() - 1;
1699 m_codeBlock->addTypeProfilerExpressionInfo(instructionOffset, start, end);
1700}
1701
1702void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag)
1703{
1704 if (!shouldEmitTypeProfilerHooks())
1705 return;
1706
1707 if (!registerToProfile)
1708 return;
1709
1710 OpProfileType::emit(this, registerToProfile, { }, flag, { }, resolveType());
1711
1712 // Don't emit expression info for this version of profile type. This generally means
1713 // we're profiling information for something that isn't in the actual text of a JavaScript
1714 // program. For example, implicit return undefined from a function call.
1715}
1716
1717void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
1718{
1719 emitProfileType(registerToProfile, ProfileTypeBytecodeDoesNotHaveGlobalID, startDivot, endDivot);
1720}
1721
1722void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
1723{
1724 if (!shouldEmitTypeProfilerHooks())
1725 return;
1726
1727 if (!registerToProfile)
1728 return;
1729
1730 OpProfileType::emit(this, registerToProfile, { }, flag, { }, resolveType());
1731 emitTypeProfilerExpressionInfo(startDivot, endDivot);
1732}
1733
1734void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const Variable& var, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
1735{
1736 if (!shouldEmitTypeProfilerHooks())
1737 return;
1738
1739 if (!registerToProfile)
1740 return;
1741
1742 ProfileTypeBytecodeFlag flag;
1743 SymbolTableOrScopeDepth symbolTableOrScopeDepth;
1744 if (var.local() || var.offset().isScope()) {
1745 flag = ProfileTypeBytecodeLocallyResolved;
1746 ASSERT(var.symbolTableConstantIndex());
1747 symbolTableOrScopeDepth = SymbolTableOrScopeDepth::symbolTable(VirtualRegister { var.symbolTableConstantIndex() });
1748 } else {
1749 flag = ProfileTypeBytecodeClosureVar;
1750 symbolTableOrScopeDepth = SymbolTableOrScopeDepth::scopeDepth(localScopeDepth());
1751 }
1752
1753 OpProfileType::emit(this, registerToProfile, symbolTableOrScopeDepth, flag, addConstant(var.ident()), resolveType());
1754 emitTypeProfilerExpressionInfo(startDivot, endDivot);
1755}
1756
1757void BytecodeGenerator::emitProfileControlFlow(int textOffset)
1758{
1759 if (shouldEmitControlFlowProfilerHooks()) {
1760 RELEASE_ASSERT(textOffset >= 0);
1761
1762 OpProfileControlFlow::emit(this, textOffset);
1763 m_codeBlock->addOpProfileControlFlowBytecodeOffset(m_lastInstruction.offset());
1764 }
1765}
1766
1767unsigned BytecodeGenerator::addConstantIndex()
1768{
1769 unsigned index = m_nextConstantOffset;
1770 m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
1771 ++m_nextConstantOffset;
1772 return index;
1773}
1774
1775RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
1776{
1777 return emitLoad(dst, jsBoolean(b));
1778}
1779
1780RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
1781{
1782 ASSERT(!identifier.isSymbol());
1783 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
1784 if (!stringInMap)
1785 stringInMap = jsOwnedString(vm(), identifier.string());
1786
1787 return emitLoad(dst, JSValue(stringInMap));
1788}
1789
1790RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v, SourceCodeRepresentation sourceCodeRepresentation)
1791{
1792 RegisterID* constantID = addConstantValue(v, sourceCodeRepresentation);
1793 if (dst)
1794 return move(dst, constantID);
1795 return constantID;
1796}
1797
1798RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, IdentifierSet& set)
1799{
1800 if (m_codeBlock->numberOfConstantIdentifierSets()) {
1801 for (const auto& entry : m_codeBlock->constantIdentifierSets()) {
1802 if (entry.first != set)
1803 continue;
1804
1805 return &m_constantPoolRegisters[entry.second];
1806 }
1807 }
1808
1809 unsigned index = addConstantIndex();
1810 m_codeBlock->addSetConstant(set);
1811 RegisterID* m_setRegister = &m_constantPoolRegisters[index];
1812
1813 if (dst)
1814 return move(dst, m_setRegister);
1815
1816 return m_setRegister;
1817}
1818
1819template<typename LookUpVarKindFunctor>
1820bool BytecodeGenerator::instantiateLexicalVariables(const VariableEnvironment& lexicalVariables, SymbolTable* symbolTable, ScopeRegisterType scopeRegisterType, LookUpVarKindFunctor lookUpVarKind)
1821{
1822 bool hasCapturedVariables = false;
1823 {
1824 for (auto& entry : lexicalVariables) {
1825 ASSERT(entry.value.isLet() || entry.value.isConst() || entry.value.isFunction());
1826 ASSERT(!entry.value.isVar());
1827 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get());
1828 ASSERT(symbolTableEntry.isNull());
1829
1830 // Imported bindings which are not the namespace bindings are not allocated
1831 // in the module environment as usual variables' way.
1832 // And since these types of the variables only seen in the module environment,
1833 // other lexical environment need not to take care this.
1834 if (entry.value.isImported() && !entry.value.isImportedNamespace())
1835 continue;
1836
1837 VarKind varKind = lookUpVarKind(entry.key.get(), entry.value);
1838 VarOffset varOffset;
1839 if (varKind == VarKind::Scope) {
1840 varOffset = VarOffset(symbolTable->takeNextScopeOffset(NoLockingNecessary));
1841 hasCapturedVariables = true;
1842 } else {
1843 ASSERT(varKind == VarKind::Stack);
1844 RegisterID* local;
1845 if (scopeRegisterType == ScopeRegisterType::Block) {
1846 local = newBlockScopeVariable();
1847 local->ref();
1848 } else
1849 local = addVar();
1850 varOffset = VarOffset(local->virtualRegister());
1851 }
1852
1853 SymbolTableEntry newEntry(varOffset, static_cast<unsigned>(entry.value.isConst() ? PropertyAttribute::ReadOnly : PropertyAttribute::None));
1854 symbolTable->add(NoLockingNecessary, entry.key.get(), newEntry);
1855 }
1856 }
1857 return hasCapturedVariables;
1858}
1859
1860void BytecodeGenerator::emitPrefillStackTDZVariables(const VariableEnvironment& lexicalVariables, SymbolTable* symbolTable)
1861{
1862 // Prefill stack variables with the TDZ empty value.
1863 // Scope variables will be initialized to the TDZ empty value when JSLexicalEnvironment is allocated.
1864 for (auto& entry : lexicalVariables) {
1865 // Imported bindings which are not the namespace bindings are not allocated
1866 // in the module environment as usual variables' way.
1867 // And since these types of the variables only seen in the module environment,
1868 // other lexical environment need not to take care this.
1869 if (entry.value.isImported() && !entry.value.isImportedNamespace())
1870 continue;
1871
1872 if (entry.value.isFunction())
1873 continue;
1874
1875 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get());
1876 ASSERT(!symbolTableEntry.isNull());
1877 VarOffset offset = symbolTableEntry.varOffset();
1878 if (offset.isScope())
1879 continue;
1880
1881 ASSERT(offset.isStack());
1882 moveEmptyValue(&registerFor(offset.stackOffset()));
1883 }
1884}
1885
1886void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType, RegisterID** constantSymbolTableResult, bool shouldInitializeBlockScopedFunctions)
1887{
1888 VariableEnvironment& environment = node->lexicalVariables();
1889 RegisterID* constantSymbolTableResultTemp = nullptr;
1890 pushLexicalScopeInternal(environment, tdzCheckOptimization, nestedScopeType, &constantSymbolTableResultTemp, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
1891
1892 if (shouldInitializeBlockScopedFunctions)
1893 initializeBlockScopedFunctions(environment, node->functionStack(), constantSymbolTableResultTemp);
1894
1895 if (constantSymbolTableResult && constantSymbolTableResultTemp)
1896 *constantSymbolTableResult = constantSymbolTableResultTemp;
1897}
1898
1899void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment& environment, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType,
1900 RegisterID** constantSymbolTableResult, TDZRequirement tdzRequirement, ScopeType scopeType, ScopeRegisterType scopeRegisterType)
1901{
1902 if (!environment.size())
1903 return;
1904
1905 if (shouldEmitDebugHooks())
1906 environment.markAllVariablesAsCaptured();
1907
1908 SymbolTable* symbolTable = SymbolTable::create(m_vm);
1909 switch (scopeType) {
1910 case ScopeType::CatchScope:
1911 symbolTable->setScopeType(SymbolTable::ScopeType::CatchScope);
1912 break;
1913 case ScopeType::LetConstScope:
1914 symbolTable->setScopeType(SymbolTable::ScopeType::LexicalScope);
1915 break;
1916 case ScopeType::FunctionNameScope:
1917 symbolTable->setScopeType(SymbolTable::ScopeType::FunctionNameScope);
1918 break;
1919 }
1920
1921 if (nestedScopeType == NestedScopeType::IsNested)
1922 symbolTable->markIsNestedLexicalScope();
1923
1924 auto lookUpVarKind = [] (UniquedStringImpl*, const VariableEnvironmentEntry& entry) -> VarKind {
1925 return entry.isCaptured() ? VarKind::Scope : VarKind::Stack;
1926 };
1927
1928 bool hasCapturedVariables = instantiateLexicalVariables(environment, symbolTable, scopeRegisterType, lookUpVarKind);
1929
1930 RegisterID* newScope = nullptr;
1931 RegisterID* constantSymbolTable = nullptr;
1932 int symbolTableConstantIndex = 0;
1933 if (shouldEmitTypeProfilerHooks()) {
1934 constantSymbolTable = addConstantValue(symbolTable);
1935 symbolTableConstantIndex = constantSymbolTable->index();
1936 }
1937 if (hasCapturedVariables) {
1938 if (scopeRegisterType == ScopeRegisterType::Block) {
1939 newScope = newBlockScopeVariable();
1940 newScope->ref();
1941 } else
1942 newScope = addVar();
1943 if (!constantSymbolTable) {
1944 ASSERT(!shouldEmitTypeProfilerHooks());
1945 constantSymbolTable = addConstantValue(symbolTable->cloneScopePart(m_vm));
1946 symbolTableConstantIndex = constantSymbolTable->index();
1947 }
1948 if (constantSymbolTableResult)
1949 *constantSymbolTableResult = constantSymbolTable;
1950
1951 OpCreateLexicalEnvironment::emit(this, newScope, scopeRegister(), VirtualRegister { symbolTableConstantIndex }, addConstantValue(tdzRequirement == TDZRequirement::UnderTDZ ? jsTDZValue() : jsUndefined()));
1952
1953 move(scopeRegister(), newScope);
1954
1955 pushLocalControlFlowScope();
1956 }
1957
1958 bool isWithScope = false;
1959 m_lexicalScopeStack.append({ symbolTable, newScope, isWithScope, symbolTableConstantIndex });
1960 pushTDZVariables(environment, tdzCheckOptimization, tdzRequirement);
1961
1962 if (tdzRequirement == TDZRequirement::UnderTDZ)
1963 emitPrefillStackTDZVariables(environment, symbolTable);
1964}
1965
1966void BytecodeGenerator::initializeBlockScopedFunctions(VariableEnvironment& environment, FunctionStack& functionStack, RegisterID* constantSymbolTable)
1967{
1968 /*
1969 * We must transform block scoped function declarations in strict mode like so:
1970 *
1971 * function foo() {
1972 * if (c) {
1973 * function foo() { ... }
1974 * if (bar) { ... }
1975 * else { ... }
1976 * function baz() { ... }
1977 * }
1978 * }
1979 *
1980 * to:
1981 *
1982 * function foo() {
1983 * if (c) {
1984 * let foo = function foo() { ... }
1985 * let baz = function baz() { ... }
1986 * if (bar) { ... }
1987 * else { ... }
1988 * }
1989 * }
1990 *
1991 * But without the TDZ checks.
1992 */
1993
1994 if (!environment.size()) {
1995 RELEASE_ASSERT(!functionStack.size());
1996 return;
1997 }
1998
1999 if (!functionStack.size())
2000 return;
2001
2002 SymbolTable* symbolTable = m_lexicalScopeStack.last().m_symbolTable;
2003 RegisterID* scope = m_lexicalScopeStack.last().m_scope;
2004 RefPtr<RegisterID> temp = newTemporary();
2005 int symbolTableIndex = constantSymbolTable ? constantSymbolTable->index() : 0;
2006 for (FunctionMetadataNode* function : functionStack) {
2007 const Identifier& name = function->ident();
2008 auto iter = environment.find(name.impl());
2009 RELEASE_ASSERT(iter != environment.end());
2010 RELEASE_ASSERT(iter->value.isFunction());
2011 // We purposefully don't hold the symbol table lock around this loop because emitNewFunctionExpressionCommon may GC.
2012 SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, name.impl());
2013 RELEASE_ASSERT(!entry.isNull());
2014 emitNewFunctionExpressionCommon(temp.get(), function);
2015 bool isLexicallyScoped = true;
2016 emitPutToScope(scope, variableForLocalEntry(name, entry, symbolTableIndex, isLexicallyScoped), temp.get(), DoNotThrowIfNotFound, InitializationMode::Initialization);
2017 }
2018}
2019
2020void BytecodeGenerator::hoistSloppyModeFunctionIfNecessary(const Identifier& functionName)
2021{
2022 if (m_scopeNode->hasSloppyModeHoistedFunction(functionName.impl())) {
2023 if (codeType() != EvalCode) {
2024 Variable currentFunctionVariable = variable(functionName);
2025 RefPtr<RegisterID> currentValue;
2026 if (RegisterID* local = currentFunctionVariable.local())
2027 currentValue = local;
2028 else {
2029 RefPtr<RegisterID> scope = emitResolveScope(nullptr, currentFunctionVariable);
2030 currentValue = emitGetFromScope(newTemporary(), scope.get(), currentFunctionVariable, DoNotThrowIfNotFound);
2031 }
2032
2033 ASSERT(m_varScopeLexicalScopeStackIndex);
2034 ASSERT(*m_varScopeLexicalScopeStackIndex < m_lexicalScopeStack.size());
2035 LexicalScopeStackEntry varScope = m_lexicalScopeStack[*m_varScopeLexicalScopeStackIndex];
2036 SymbolTable* varSymbolTable = varScope.m_symbolTable;
2037 ASSERT(varSymbolTable->scopeType() == SymbolTable::ScopeType::VarScope);
2038 SymbolTableEntry entry = varSymbolTable->get(NoLockingNecessary, functionName.impl());
2039 if (functionName == propertyNames().arguments && entry.isNull()) {
2040 // "arguments" might be put in the parameter scope when we have a non-simple
2041 // parameter list since "arguments" is visible to expressions inside the
2042 // parameter evaluation list.
2043 // e.g:
2044 // function foo(x = arguments) { { function arguments() { } } }
2045 RELEASE_ASSERT(*m_varScopeLexicalScopeStackIndex > 0);
2046 varScope = m_lexicalScopeStack[*m_varScopeLexicalScopeStackIndex - 1];
2047 SymbolTable* parameterSymbolTable = varScope.m_symbolTable;
2048 entry = parameterSymbolTable->get(NoLockingNecessary, functionName.impl());
2049 }
2050 RELEASE_ASSERT(!entry.isNull());
2051 bool isLexicallyScoped = false;
2052 emitPutToScope(varScope.m_scope, variableForLocalEntry(functionName, entry, varScope.m_symbolTableConstantIndex, isLexicallyScoped), currentValue.get(), DoNotThrowIfNotFound, InitializationMode::NotInitialization);
2053 } else {
2054 Variable currentFunctionVariable = variable(functionName);
2055 RefPtr<RegisterID> currentValue;
2056 if (RegisterID* local = currentFunctionVariable.local())
2057 currentValue = local;
2058 else {
2059 RefPtr<RegisterID> scope = emitResolveScope(nullptr, currentFunctionVariable);
2060 currentValue = emitGetFromScope(newTemporary(), scope.get(), currentFunctionVariable, DoNotThrowIfNotFound);
2061 }
2062
2063 RefPtr<RegisterID> scopeId = emitResolveScopeForHoistingFuncDeclInEval(nullptr, functionName);
2064 RefPtr<RegisterID> checkResult = emitIsUndefined(newTemporary(), scopeId.get());
2065
2066 Ref<Label> isNotVarScopeLabel = newLabel();
2067 emitJumpIfTrue(checkResult.get(), isNotVarScopeLabel.get());
2068
2069 // Put to outer scope
2070 emitPutToScope(scopeId.get(), functionName, currentValue.get(), DoNotThrowIfNotFound, InitializationMode::NotInitialization);
2071 emitLabel(isNotVarScopeLabel.get());
2072
2073 }
2074 }
2075}
2076
2077RegisterID* BytecodeGenerator::emitResolveScopeForHoistingFuncDeclInEval(RegisterID* dst, const Identifier& property)
2078{
2079 ASSERT(m_codeType == EvalCode);
2080
2081 dst = finalDestination(dst);
2082 OpResolveScopeForHoistingFuncDeclInEval::emit(this, kill(dst), m_topMostScope, addConstant(property));
2083 return dst;
2084}
2085
2086void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node)
2087{
2088 VariableEnvironment& environment = node->lexicalVariables();
2089 popLexicalScopeInternal(environment);
2090}
2091
2092void BytecodeGenerator::popLexicalScopeInternal(VariableEnvironment& environment)
2093{
2094 // NOTE: This function only makes sense for scopes that aren't ScopeRegisterType::Var (only function name scope right now is ScopeRegisterType::Var).
2095 // This doesn't make sense for ScopeRegisterType::Var because we deref RegisterIDs here.
2096 if (!environment.size())
2097 return;
2098
2099 if (shouldEmitDebugHooks())
2100 environment.markAllVariablesAsCaptured();
2101
2102 auto stackEntry = m_lexicalScopeStack.takeLast();
2103 SymbolTable* symbolTable = stackEntry.m_symbolTable;
2104 bool hasCapturedVariables = false;
2105 for (auto& entry : environment) {
2106 if (entry.value.isCaptured()) {
2107 hasCapturedVariables = true;
2108 continue;
2109 }
2110 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, entry.key.get());
2111 ASSERT(!symbolTableEntry.isNull());
2112 VarOffset offset = symbolTableEntry.varOffset();
2113 ASSERT(offset.isStack());
2114 RegisterID* local = &registerFor(offset.stackOffset());
2115 local->deref();
2116 }
2117
2118 if (hasCapturedVariables) {
2119 RELEASE_ASSERT(stackEntry.m_scope);
2120 emitGetParentScope(scopeRegister(), stackEntry.m_scope);
2121 popLocalControlFlowScope();
2122 stackEntry.m_scope->deref();
2123 }
2124
2125 m_TDZStack.removeLast();
2126 m_cachedVariablesUnderTDZ = { };
2127}
2128
2129void BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode* node, RegisterID* loopSymbolTable)
2130{
2131 VariableEnvironment& environment = node->lexicalVariables();
2132 if (!environment.size())
2133 return;
2134 if (shouldEmitDebugHooks())
2135 environment.markAllVariablesAsCaptured();
2136 if (!environment.hasCapturedVariables())
2137 return;
2138
2139 RELEASE_ASSERT(loopSymbolTable);
2140
2141 // This function needs to do setup for a for loop's activation if any of
2142 // the for loop's lexically declared variables are captured (that is, variables
2143 // declared in the loop header, not the loop body). This function needs to
2144 // make a copy of the current activation and copy the values from the previous
2145 // activation into the new activation because each iteration of a for loop
2146 // gets a new activation.
2147
2148 auto stackEntry = m_lexicalScopeStack.last();
2149 SymbolTable* symbolTable = stackEntry.m_symbolTable;
2150 RegisterID* loopScope = stackEntry.m_scope;
2151 ASSERT(symbolTable->scopeSize());
2152 ASSERT(loopScope);
2153 Vector<std::pair<RegisterID*, Identifier>> activationValuesToCopyOver;
2154
2155 {
2156 activationValuesToCopyOver.reserveInitialCapacity(symbolTable->scopeSize());
2157
2158 for (auto end = symbolTable->end(NoLockingNecessary), ptr = symbolTable->begin(NoLockingNecessary); ptr != end; ++ptr) {
2159 if (!ptr->value.varOffset().isScope())
2160 continue;
2161
2162 RefPtr<UniquedStringImpl> ident = ptr->key;
2163 Identifier identifier = Identifier::fromUid(m_vm, ident.get());
2164
2165 RegisterID* transitionValue = newBlockScopeVariable();
2166 transitionValue->ref();
2167 emitGetFromScope(transitionValue, loopScope, variableForLocalEntry(identifier, ptr->value, loopSymbolTable->index(), true), DoNotThrowIfNotFound);
2168 activationValuesToCopyOver.uncheckedAppend(std::make_pair(transitionValue, identifier));
2169 }
2170 }
2171
2172 // We need this dynamic behavior of the executing code to ensure
2173 // each loop iteration has a new activation object. (It's pretty ugly).
2174 // Also, this new activation needs to be assigned to the same register
2175 // as the previous scope because the loop body is compiled under
2176 // the assumption that the scope's register index is constant even
2177 // though the value in that register will change on each loop iteration.
2178 emitGetParentScope(scopeRegister(), loopScope);
2179
2180 OpCreateLexicalEnvironment::emit(this, loopScope, scopeRegister(), loopSymbolTable, addConstantValue(jsTDZValue()));
2181
2182 move(scopeRegister(), loopScope);
2183
2184 {
2185 for (const auto& pair : activationValuesToCopyOver) {
2186 const Identifier& identifier = pair.second;
2187 SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, identifier.impl());
2188 RELEASE_ASSERT(!entry.isNull());
2189 RegisterID* transitionValue = pair.first;
2190 emitPutToScope(loopScope, variableForLocalEntry(identifier, entry, loopSymbolTable->index(), true), transitionValue, DoNotThrowIfNotFound, InitializationMode::NotInitialization);
2191 transitionValue->deref();
2192 }
2193 }
2194}
2195
2196Variable BytecodeGenerator::variable(const Identifier& property, ThisResolutionType thisResolutionType)
2197{
2198 if (property == propertyNames().thisIdentifier && thisResolutionType == ThisResolutionType::Local)
2199 return Variable(property, VarOffset(thisRegister()->virtualRegister()), thisRegister(), static_cast<unsigned>(PropertyAttribute::ReadOnly), Variable::SpecialVariable, 0, false);
2200
2201 // We can optimize lookups if the lexical variable is found before a "with" or "catch"
2202 // scope because we're guaranteed static resolution. If we have to pass through
2203 // a "with" or "catch" scope we loose this guarantee.
2204 // We can't optimize cases like this:
2205 // {
2206 // let x = ...;
2207 // with (o) {
2208 // doSomethingWith(x);
2209 // }
2210 // }
2211 // Because we can't gaurantee static resolution on x.
2212 // But, in this case, we are guaranteed static resolution:
2213 // {
2214 // let x = ...;
2215 // with (o) {
2216 // let x = ...;
2217 // doSomethingWith(x);
2218 // }
2219 // }
2220 for (unsigned i = m_lexicalScopeStack.size(); i--; ) {
2221 auto& stackEntry = m_lexicalScopeStack[i];
2222 if (stackEntry.m_isWithScope)
2223 return Variable(property);
2224 SymbolTable* symbolTable = stackEntry.m_symbolTable;
2225 SymbolTableEntry symbolTableEntry = symbolTable->get(NoLockingNecessary, property.impl());
2226 if (symbolTableEntry.isNull())
2227 continue;
2228 bool resultIsCallee = false;
2229 if (symbolTable->scopeType() == SymbolTable::ScopeType::FunctionNameScope) {
2230 if (m_usesNonStrictEval) {
2231 // We don't know if an eval has introduced a "var" named the same thing as the function name scope variable name.
2232 // We resort to dynamic lookup to answer this question.
2233 Variable result = Variable(property);
2234 return result;
2235 }
2236 resultIsCallee = true;
2237 }
2238 Variable result = variableForLocalEntry(property, symbolTableEntry, stackEntry.m_symbolTableConstantIndex, symbolTable->scopeType() == SymbolTable::ScopeType::LexicalScope);
2239 if (resultIsCallee)
2240 result.setIsReadOnly();
2241 return result;
2242 }
2243
2244 return Variable(property);
2245}
2246
2247Variable BytecodeGenerator::variableForLocalEntry(
2248 const Identifier& property, const SymbolTableEntry& entry, int symbolTableConstantIndex, bool isLexicallyScoped)
2249{
2250 VarOffset offset = entry.varOffset();
2251
2252 RegisterID* local;
2253 if (offset.isStack())
2254 local = &registerFor(offset.stackOffset());
2255 else
2256 local = nullptr;
2257
2258 return Variable(property, offset, local, entry.getAttributes(), Variable::NormalVariable, symbolTableConstantIndex, isLexicallyScoped);
2259}
2260
2261void BytecodeGenerator::createVariable(
2262 const Identifier& property, VarKind varKind, SymbolTable* symbolTable, ExistingVariableMode existingVariableMode)
2263{
2264 ASSERT(property != propertyNames().thisIdentifier);
2265 SymbolTableEntry entry = symbolTable->get(NoLockingNecessary, property.impl());
2266
2267 if (!entry.isNull()) {
2268 if (existingVariableMode == IgnoreExisting)
2269 return;
2270
2271 // Do some checks to ensure that the variable we're being asked to create is sufficiently
2272 // compatible with the one we have already created.
2273
2274 VarOffset offset = entry.varOffset();
2275
2276 // We can't change our minds about whether it's captured.
2277 if (offset.kind() != varKind) {
2278 dataLog(
2279 "Trying to add variable called ", property, " as ", varKind,
2280 " but it was already added as ", offset, ".\n");
2281 RELEASE_ASSERT_NOT_REACHED();
2282 }
2283
2284 return;
2285 }
2286
2287 VarOffset varOffset;
2288 if (varKind == VarKind::Scope)
2289 varOffset = VarOffset(symbolTable->takeNextScopeOffset(NoLockingNecessary));
2290 else {
2291 ASSERT(varKind == VarKind::Stack);
2292 varOffset = VarOffset(virtualRegisterForLocal(m_calleeLocals.size()));
2293 }
2294 SymbolTableEntry newEntry(varOffset, 0);
2295 symbolTable->add(NoLockingNecessary, property.impl(), newEntry);
2296
2297 if (varKind == VarKind::Stack) {
2298 RegisterID* local = addVar();
2299 RELEASE_ASSERT(local->index() == varOffset.stackOffset().offset());
2300 }
2301}
2302
2303RegisterID* BytecodeGenerator::emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue)
2304{
2305 OpOverridesHasInstance::emit(this, dst, constructor, hasInstanceValue);
2306 return dst;
2307}
2308
2309// Indicates the least upper bound of resolve type based on local scope. The bytecode linker
2310// will start with this ResolveType and compute the least upper bound including intercepting scopes.
2311ResolveType BytecodeGenerator::resolveType()
2312{
2313 for (unsigned i = m_lexicalScopeStack.size(); i--; ) {
2314 if (m_lexicalScopeStack[i].m_isWithScope)
2315 return Dynamic;
2316 if (m_usesNonStrictEval && m_lexicalScopeStack[i].m_symbolTable->scopeType() == SymbolTable::ScopeType::FunctionNameScope) {
2317 // We never want to assign to a FunctionNameScope. Returning Dynamic here achieves this goal.
2318 // If we aren't in non-strict eval mode, then NodesCodeGen needs to take care not to emit
2319 // a put_to_scope with the destination being the function name scope variable.
2320 return Dynamic;
2321 }
2322 }
2323
2324 if (m_usesNonStrictEval)
2325 return GlobalPropertyWithVarInjectionChecks;
2326 return GlobalProperty;
2327}
2328
2329RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Variable& variable)
2330{
2331 switch (variable.offset().kind()) {
2332 case VarKind::Stack:
2333 return nullptr;
2334
2335 case VarKind::DirectArgument:
2336 return argumentsRegister();
2337
2338 case VarKind::Scope: {
2339 // This always refers to the activation that *we* allocated, and not the current scope that code
2340 // lives in. Note that this will change once we have proper support for block scoping. Once that
2341 // changes, it will be correct for this code to return scopeRegister(). The only reason why we
2342 // don't do that already is that m_lexicalEnvironment is required by ConstDeclNode. ConstDeclNode
2343 // requires weird things because it is a shameful pile of nonsense, but block scoping would make
2344 // that code sensible and obviate the need for us to do bad things.
2345 for (unsigned i = m_lexicalScopeStack.size(); i--; ) {
2346 auto& stackEntry = m_lexicalScopeStack[i];
2347 // We should not resolve a variable to VarKind::Scope if a "with" scope lies in between the current
2348 // scope and the resolved scope.
2349 RELEASE_ASSERT(!stackEntry.m_isWithScope);
2350
2351 if (stackEntry.m_symbolTable->get(NoLockingNecessary, variable.ident().impl()).isNull())
2352 continue;
2353
2354 RegisterID* scope = stackEntry.m_scope;
2355 RELEASE_ASSERT(scope);
2356 return scope;
2357 }
2358
2359 RELEASE_ASSERT_NOT_REACHED();
2360 return nullptr;
2361
2362 }
2363 case VarKind::Invalid:
2364 // Indicates non-local resolution.
2365
2366 dst = tempDestination(dst);
2367 OpResolveScope::emit(this, kill(dst), scopeRegister(), addConstant(variable.ident()), resolveType(), localScopeDepth());
2368 return dst;
2369 }
2370
2371 RELEASE_ASSERT_NOT_REACHED();
2372 return nullptr;
2373}
2374
2375RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable& variable, ResolveMode resolveMode)
2376{
2377 switch (variable.offset().kind()) {
2378 case VarKind::Stack:
2379 return move(dst, variable.local());
2380
2381 case VarKind::DirectArgument: {
2382 OpGetFromArguments::emit(this, kill(dst), scope, variable.offset().capturedArgumentsOffset().offset());
2383 return dst;
2384 }
2385
2386 case VarKind::Scope:
2387 case VarKind::Invalid: {
2388 OpGetFromScope::emit(
2389 this,
2390 kill(dst),
2391 scope,
2392 addConstant(variable.ident()),
2393 GetPutInfo(resolveMode, variable.offset().isScope() ? LocalClosureVar : resolveType(), InitializationMode::NotInitialization),
2394 localScopeDepth(),
2395 variable.offset().isScope() ? variable.offset().scopeOffset().offset() : 0);
2396 return dst;
2397 } }
2398
2399 RELEASE_ASSERT_NOT_REACHED();
2400}
2401
2402RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Variable& variable, RegisterID* value, ResolveMode resolveMode, InitializationMode initializationMode)
2403{
2404 switch (variable.offset().kind()) {
2405 case VarKind::Stack:
2406 move(variable.local(), value);
2407 return value;
2408
2409 case VarKind::DirectArgument:
2410 OpPutToArguments::emit(this, scope, variable.offset().capturedArgumentsOffset().offset(), value);
2411 return value;
2412
2413 case VarKind::Scope:
2414 case VarKind::Invalid: {
2415 GetPutInfo getPutInfo(0);
2416 SymbolTableOrScopeDepth symbolTableOrScopeDepth;
2417 ScopeOffset offset;
2418 if (variable.offset().isScope()) {
2419 offset = variable.offset().scopeOffset();
2420 getPutInfo = GetPutInfo(resolveMode, LocalClosureVar, initializationMode);
2421 symbolTableOrScopeDepth = SymbolTableOrScopeDepth::symbolTable(VirtualRegister { variable.symbolTableConstantIndex() });
2422 } else {
2423 ASSERT(resolveType() != LocalClosureVar);
2424 getPutInfo = GetPutInfo(resolveMode, resolveType(), initializationMode);
2425 symbolTableOrScopeDepth = SymbolTableOrScopeDepth::scopeDepth(localScopeDepth());
2426 }
2427 OpPutToScope::emit(this, scope, addConstant(variable.ident()), value, getPutInfo, symbolTableOrScopeDepth, !!offset ? offset.offset() : 0);
2428 return value;
2429 } }
2430
2431 RELEASE_ASSERT_NOT_REACHED();
2432}
2433
2434RegisterID* BytecodeGenerator::initializeVariable(const Variable& variable, RegisterID* value)
2435{
2436 RELEASE_ASSERT(variable.offset().kind() != VarKind::Invalid);
2437 RegisterID* scope = emitResolveScope(nullptr, variable);
2438 return emitPutToScope(scope, variable, value, ThrowIfNotFound, InitializationMode::NotInitialization);
2439}
2440
2441RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype)
2442{
2443 OpInstanceof::emit(this, dst, value, basePrototype);
2444 return dst;
2445}
2446
2447RegisterID* BytecodeGenerator::emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue)
2448{
2449 OpInstanceofCustom::emit(this, dst, value, constructor, hasInstanceValue);
2450 return dst;
2451}
2452
2453RegisterID* BytecodeGenerator::emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base)
2454{
2455 OpInByVal::emit(this, dst, base, property);
2456 return dst;
2457}
2458
2459RegisterID* BytecodeGenerator::emitInById(RegisterID* dst, RegisterID* base, const Identifier& property)
2460{
2461 OpInById::emit(this, dst, base, addConstant(property));
2462 return dst;
2463}
2464
2465RegisterID* BytecodeGenerator::emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
2466{
2467 ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties are not supported with tryGetById.");
2468
2469 OpTryGetById::emit(this, kill(dst), base, addConstant(property));
2470 return dst;
2471}
2472
2473RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
2474{
2475 ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val.");
2476
2477 OpGetById::emit(this, kill(dst), base, addConstant(property));
2478 return dst;
2479}
2480
2481RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, RegisterID* thisVal, const Identifier& property)
2482{
2483 ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val.");
2484
2485 OpGetByIdWithThis::emit(this, kill(dst), base, thisVal, addConstant(property));
2486 return dst;
2487}
2488
2489RegisterID* BytecodeGenerator::emitDirectGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
2490{
2491 ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with get_by_val_direct.");
2492
2493 OpGetByIdDirect::emit(this, kill(dst), base, addConstant(property));
2494 return dst;
2495}
2496
2497RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
2498{
2499 ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with put_by_val.");
2500
2501 unsigned propertyIndex = addConstant(property);
2502
2503 m_staticPropertyAnalyzer.putById(base, propertyIndex);
2504
2505 OpPutById::emit(this, base, propertyIndex, value, PutByIdNone); // is not direct
2506 return value;
2507}
2508
2509RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, RegisterID* thisValue, const Identifier& property, RegisterID* value)
2510{
2511 ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with put_by_val.");
2512
2513 unsigned propertyIndex = addConstant(property);
2514
2515 OpPutByIdWithThis::emit(this, base, thisValue, propertyIndex, value);
2516
2517 return value;
2518}
2519
2520RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType putType)
2521{
2522 ASSERT_WITH_MESSAGE(!parseIndex(property), "Indexed properties should be handled with put_by_val(direct).");
2523
2524 unsigned propertyIndex = addConstant(property);
2525
2526 m_staticPropertyAnalyzer.putById(base, propertyIndex);
2527
2528 PutByIdFlags type = (putType == PropertyNode::KnownDirect || property != m_vm.propertyNames->underscoreProto) ? PutByIdIsDirect : PutByIdNone;
2529 OpPutById::emit(this, base, propertyIndex, value, type);
2530 return value;
2531}
2532
2533void BytecodeGenerator::emitPutGetterById(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter)
2534{
2535 unsigned propertyIndex = addConstant(property);
2536 m_staticPropertyAnalyzer.putById(base, propertyIndex);
2537
2538 OpPutGetterById::emit(this, base, propertyIndex, attributes, getter);
2539}
2540
2541void BytecodeGenerator::emitPutSetterById(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* setter)
2542{
2543 unsigned propertyIndex = addConstant(property);
2544 m_staticPropertyAnalyzer.putById(base, propertyIndex);
2545
2546 OpPutSetterById::emit(this, base, propertyIndex, attributes, setter);
2547}
2548
2549void BytecodeGenerator::emitPutGetterSetter(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter, RegisterID* setter)
2550{
2551 unsigned propertyIndex = addConstant(property);
2552
2553 m_staticPropertyAnalyzer.putById(base, propertyIndex);
2554
2555 OpPutGetterSetterById::emit(this, base, propertyIndex, attributes, getter, setter);
2556}
2557
2558void BytecodeGenerator::emitPutGetterByVal(RegisterID* base, RegisterID* property, unsigned attributes, RegisterID* getter)
2559{
2560 OpPutGetterByVal::emit(this, base, property, attributes, getter);
2561}
2562
2563void BytecodeGenerator::emitPutSetterByVal(RegisterID* base, RegisterID* property, unsigned attributes, RegisterID* setter)
2564{
2565 OpPutSetterByVal::emit(this, base, property, attributes, setter);
2566}
2567
2568void BytecodeGenerator::emitPutGeneratorFields(RegisterID* nextFunction)
2569{
2570 emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSGenerator::Field::Next), nextFunction);
2571
2572 // We do not store 'this' in arrow function within constructor,
2573 // because it might be not initialized, if super is called later.
2574 if (!(isDerivedConstructorContext() && m_codeBlock->parseMode() == SourceParseMode::AsyncArrowFunctionMode))
2575 emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSGenerator::Field::This), &m_thisRegister);
2576}
2577
2578void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction)
2579{
2580 ASSERT(isAsyncGeneratorWrapperParseMode(parseMode()));
2581
2582 emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSAsyncGenerator::Field::Next), nextFunction);
2583 emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSAsyncGenerator::Field::This), &m_thisRegister);
2584}
2585
2586RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
2587{
2588 OpDelById::emit(this, dst, base, addConstant(property));
2589 return dst;
2590}
2591
2592RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
2593{
2594 for (size_t i = m_forInContextStack.size(); i--; ) {
2595 ForInContext& context = m_forInContextStack[i].get();
2596 if (context.local() != property)
2597 continue;
2598
2599 if (context.isIndexedForInContext()) {
2600 auto& indexedContext = context.asIndexedForInContext();
2601 kill(dst);
2602 if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Narrow>(this, dst, base, property))
2603 OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(this, dst, base, indexedContext.index());
2604 else if (OpGetByVal::checkWithoutMetadataID<OpcodeSize::Wide16>(this, dst, base, property))
2605 OpGetByVal::emitWithSmallestSizeRequirement<OpcodeSize::Wide16>(this, dst, base, indexedContext.index());
2606 else
2607 OpGetByVal::emit<OpcodeSize::Wide32>(this, dst, base, indexedContext.index());
2608 indexedContext.addGetInst(m_lastInstruction.offset(), property->index());
2609 return dst;
2610 }
2611
2612 // We cannot do the above optimization here since OpGetDirectPname => OpGetByVal conversion involves different metadata ID allocation.
2613 StructureForInContext& structureContext = context.asStructureForInContext();
2614 OpGetDirectPname::emit<OpcodeSize::Wide32>(this, kill(dst), base, property, structureContext.index(), structureContext.enumerator());
2615
2616 structureContext.addGetInst(m_lastInstruction.offset(), property->index());
2617 return dst;
2618 }
2619
2620 OpGetByVal::emit(this, kill(dst), base, property);
2621 return dst;
2622}
2623
2624RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* thisValue, RegisterID* property)
2625{
2626 OpGetByValWithThis::emit(this, kill(dst), base, thisValue, property);
2627 return dst;
2628}
2629
2630RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
2631{
2632 OpPutByVal::emit(this, base, property, value);
2633 return value;
2634}
2635
2636RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value)
2637{
2638 OpPutByValWithThis::emit(this, base, thisValue, property, value);
2639 return value;
2640}
2641
2642RegisterID* BytecodeGenerator::emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
2643{
2644 OpPutByValDirect::emit(this, base, property, value);
2645 return value;
2646}
2647
2648RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
2649{
2650 OpDelByVal::emit(this, dst, base, property);
2651 return dst;
2652}
2653
2654RegisterID* BytecodeGenerator::emitGetInternalField(RegisterID* dst, RegisterID* base, unsigned index)
2655{
2656 OpGetInternalField::emit(this, dst, base, index);
2657 return dst;
2658}
2659
2660RegisterID* BytecodeGenerator::emitPutInternalField(RegisterID* base, unsigned index, RegisterID* value)
2661{
2662 OpPutInternalField::emit(this, base, index, value);
2663 return value;
2664}
2665
2666void BytecodeGenerator::emitSuperSamplerBegin()
2667{
2668 OpSuperSamplerBegin::emit(this);
2669}
2670
2671void BytecodeGenerator::emitSuperSamplerEnd()
2672{
2673 OpSuperSamplerEnd::emit(this);
2674}
2675
2676RegisterID* BytecodeGenerator::emitIdWithProfile(RegisterID* src, SpeculatedType profile)
2677{
2678 OpIdentityWithProfile::emit(this, src, static_cast<uint32_t>(profile >> 32), static_cast<uint32_t>(profile));
2679 return src;
2680}
2681
2682void BytecodeGenerator::emitUnreachable()
2683{
2684 OpUnreachable::emit(this);
2685}
2686
2687RegisterID* BytecodeGenerator::emitGetArgument(RegisterID* dst, int32_t index)
2688{
2689 OpGetArgument::emit(this, dst, index + 1 /* Including |this| */);
2690 return dst;
2691}
2692
2693RegisterID* BytecodeGenerator::emitCreateThis(RegisterID* dst)
2694{
2695 OpCreateThis::emit(this, dst, dst, 0);
2696 m_staticPropertyAnalyzer.createThis(dst, m_lastInstruction);
2697 return dst;
2698}
2699
2700RegisterID* BytecodeGenerator::emitCreatePromise(RegisterID* dst, RegisterID* newTarget, bool isInternalPromise)
2701{
2702 OpCreatePromise::emit(this, dst, newTarget, isInternalPromise);
2703 return dst;
2704}
2705
2706RegisterID* BytecodeGenerator::emitNewPromise(RegisterID* dst, bool isInternalPromise)
2707{
2708 OpNewPromise::emit(this, dst, isInternalPromise);
2709 return dst;
2710}
2711
2712RegisterID* BytecodeGenerator::emitCreateGenerator(RegisterID* dst, RegisterID* newTarget)
2713{
2714 OpCreateGenerator::emit(this, dst, newTarget);
2715 return dst;
2716}
2717
2718RegisterID* BytecodeGenerator::emitNewGenerator(RegisterID* dst)
2719{
2720 OpNewGenerator::emit(this, dst);
2721 return dst;
2722}
2723
2724RegisterID* BytecodeGenerator::emitCreateAsyncGenerator(RegisterID* dst, RegisterID* newTarget)
2725{
2726 OpCreateAsyncGenerator::emit(this, dst, newTarget);
2727 return dst;
2728}
2729
2730void BytecodeGenerator::emitTDZCheck(RegisterID* target)
2731{
2732 OpCheckTdz::emit(this, target);
2733}
2734
2735bool BytecodeGenerator::needsTDZCheck(const Variable& variable)
2736{
2737 for (unsigned i = m_TDZStack.size(); i--;) {
2738 auto iter = m_TDZStack[i].find(variable.ident().impl());
2739 if (iter == m_TDZStack[i].end())
2740 continue;
2741 return iter->value != TDZNecessityLevel::NotNeeded;
2742 }
2743
2744 return false;
2745}
2746
2747void BytecodeGenerator::emitTDZCheckIfNecessary(const Variable& variable, RegisterID* target, RegisterID* scope)
2748{
2749 if (needsTDZCheck(variable)) {
2750 if (target)
2751 emitTDZCheck(target);
2752 else {
2753 RELEASE_ASSERT(!variable.isLocal() && scope);
2754 RefPtr<RegisterID> result = emitGetFromScope(newTemporary(), scope, variable, DoNotThrowIfNotFound);
2755 emitTDZCheck(result.get());
2756 }
2757 }
2758}
2759
2760void BytecodeGenerator::liftTDZCheckIfPossible(const Variable& variable)
2761{
2762 RefPtr<UniquedStringImpl> identifier(variable.ident().impl());
2763 for (unsigned i = m_TDZStack.size(); i--;) {
2764 auto iter = m_TDZStack[i].find(identifier);
2765 if (iter != m_TDZStack[i].end()) {
2766 if (iter->value == TDZNecessityLevel::Optimize) {
2767 m_cachedVariablesUnderTDZ = { };
2768 iter->value = TDZNecessityLevel::NotNeeded;
2769 }
2770 break;
2771 }
2772 }
2773}
2774
2775void BytecodeGenerator::pushTDZVariables(const VariableEnvironment& environment, TDZCheckOptimization optimization, TDZRequirement requirement)
2776{
2777 if (!environment.size())
2778 return;
2779
2780 TDZNecessityLevel level;
2781 if (requirement == TDZRequirement::UnderTDZ) {
2782 if (optimization == TDZCheckOptimization::Optimize)
2783 level = TDZNecessityLevel::Optimize;
2784 else
2785 level = TDZNecessityLevel::DoNotOptimize;
2786 } else
2787 level = TDZNecessityLevel::NotNeeded;
2788
2789 TDZMap map;
2790 for (const auto& entry : environment)
2791 map.add(entry.key, entry.value.isFunction() ? TDZNecessityLevel::NotNeeded : level);
2792
2793 m_TDZStack.append(WTFMove(map));
2794 m_cachedVariablesUnderTDZ = { };
2795}
2796
2797Optional<CompactVariableMap::Handle> BytecodeGenerator::getVariablesUnderTDZ()
2798{
2799 if (m_cachedVariablesUnderTDZ) {
2800 if (!m_hasCachedVariablesUnderTDZ) {
2801 ASSERT(m_cachedVariablesUnderTDZ.environment().toVariableEnvironment().isEmpty());
2802 return WTF::nullopt;
2803 }
2804 return m_cachedVariablesUnderTDZ;
2805 }
2806
2807 // We keep track of variablesThatDontNeedTDZ in this algorithm to prevent
2808 // reporting that "x" is under TDZ if this function is called at "...".
2809 //
2810 // {
2811 // {
2812 // let x;
2813 // ...
2814 // }
2815 // let x;
2816 // }
2817 SmallPtrSet<UniquedStringImpl*, 16> variablesThatDontNeedTDZ;
2818 VariableEnvironment environment;
2819 for (unsigned i = m_TDZStack.size(); i--; ) {
2820 auto& map = m_TDZStack[i];
2821 for (auto& entry : map) {
2822 if (entry.value != TDZNecessityLevel::NotNeeded) {
2823 if (!variablesThatDontNeedTDZ.contains(entry.key.get()))
2824 environment.add(entry.key.get());
2825 } else
2826 variablesThatDontNeedTDZ.add(entry.key.get());
2827 }
2828 }
2829
2830 m_cachedVariablesUnderTDZ = m_vm.m_compactVariableMap->get(environment);
2831 m_hasCachedVariablesUnderTDZ = !environment.isEmpty();
2832 if (!m_hasCachedVariablesUnderTDZ)
2833 return WTF::nullopt;
2834
2835 return m_cachedVariablesUnderTDZ;
2836}
2837
2838void BytecodeGenerator::preserveTDZStack(BytecodeGenerator::PreservedTDZStack& preservedStack)
2839{
2840 preservedStack.m_preservedTDZStack = m_TDZStack;
2841}
2842
2843void BytecodeGenerator::restoreTDZStack(const BytecodeGenerator::PreservedTDZStack& preservedStack)
2844{
2845 m_TDZStack = preservedStack.m_preservedTDZStack;
2846 m_cachedVariablesUnderTDZ = { };
2847}
2848
2849RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
2850{
2851 OpNewObject::emit(this, dst, 0);
2852 m_staticPropertyAnalyzer.newObject(dst, m_lastInstruction);
2853
2854 return dst;
2855}
2856
2857JSValue BytecodeGenerator::addBigIntConstant(const Identifier& identifier, uint8_t radix, bool sign)
2858{
2859 return m_bigIntMap.ensure(BigIntMapEntry(identifier.impl(), radix, sign), [&] {
2860 auto scope = DECLARE_CATCH_SCOPE(vm());
2861 auto parseIntSign = sign ? JSBigInt::ParseIntSign::Signed : JSBigInt::ParseIntSign::Unsigned;
2862 JSBigInt* bigIntInMap = JSBigInt::parseInt(nullptr, vm(), identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, parseIntSign);
2863 // FIXME: [ESNext] Enables a way to throw an error on ByteCodeGenerator step
2864 // https://bugs.webkit.org/show_bug.cgi?id=180139
2865 scope.assertNoException();
2866 RELEASE_ASSERT(bigIntInMap);
2867 addConstantValue(bigIntInMap);
2868
2869 return bigIntInMap;
2870 }).iterator->value;
2871}
2872
2873JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
2874{
2875 JSString*& stringInMap = m_stringMap.add(identifier.impl(), nullptr).iterator->value;
2876 if (!stringInMap) {
2877 stringInMap = jsString(vm(), identifier.string());
2878 addConstantValue(stringInMap);
2879 }
2880 return stringInMap;
2881}
2882
2883RegisterID* BytecodeGenerator::addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&& descriptor, int endOffset)
2884{
2885 auto result = m_templateObjectDescriptorSet.add(WTFMove(descriptor));
2886 JSTemplateObjectDescriptor* descriptorValue = m_templateDescriptorMap.ensure(endOffset, [&] {
2887 return JSTemplateObjectDescriptor::create(vm(), result.iterator->copyRef(), endOffset);
2888 }).iterator->value;
2889 int index = addConstantIndex();
2890 m_codeBlock->addConstant(descriptorValue);
2891 return &m_constantPoolRegisters[index];
2892}
2893
2894RegisterID* BytecodeGenerator::emitNewArrayBuffer(RegisterID* dst, JSImmutableButterfly* array, IndexingType recommendedIndexingType)
2895{
2896 OpNewArrayBuffer::emit(this, dst, addConstantValue(array), recommendedIndexingType);
2897 return dst;
2898}
2899
2900RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length, IndexingType recommendedIndexingType)
2901{
2902 Vector<RefPtr<RegisterID>, 16, UnsafeVectorOverflow> argv;
2903 for (ElementNode* n = elements; n; n = n->next()) {
2904 if (!length)
2905 break;
2906 length--;
2907 ASSERT(!n->value()->isSpreadExpression());
2908 argv.append(newTemporary());
2909 // op_new_array requires the initial values to be a sequential range of registers
2910 ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() - 1);
2911 emitNode(argv.last().get(), n->value());
2912 }
2913 ASSERT(!length);
2914 OpNewArray::emit(this, dst, argv.size() ? argv[0].get() : VirtualRegister { 0 }, argv.size(), recommendedIndexingType);
2915 return dst;
2916}
2917
2918RegisterID* BytecodeGenerator::emitNewArrayWithSpread(RegisterID* dst, ElementNode* elements)
2919{
2920 BitVector bitVector;
2921 Vector<RefPtr<RegisterID>, 16> argv;
2922 for (ElementNode* node = elements; node; node = node->next()) {
2923 bitVector.set(argv.size(), node->value()->isSpreadExpression());
2924
2925 argv.append(newTemporary());
2926 // op_new_array_with_spread requires the initial values to be a sequential range of registers.
2927 RELEASE_ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() - 1);
2928 }
2929
2930 RELEASE_ASSERT(argv.size());
2931
2932 {
2933 unsigned i = 0;
2934 for (ElementNode* node = elements; node; node = node->next()) {
2935 if (node->value()->isSpreadExpression()) {
2936 ExpressionNode* expression = static_cast<SpreadExpressionNode*>(node->value())->expression();
2937 RefPtr<RegisterID> tmp = newTemporary();
2938 emitNode(tmp.get(), expression);
2939
2940 OpSpread::emit(this, argv[i].get(), tmp.get());
2941 } else {
2942 ExpressionNode* expression = node->value();
2943 emitNode(argv[i].get(), expression);
2944 }
2945 i++;
2946 }
2947 }
2948
2949 unsigned bitVectorIndex = m_codeBlock->addBitVector(WTFMove(bitVector));
2950 OpNewArrayWithSpread::emit(this, dst, argv[0].get(), argv.size(), bitVectorIndex);
2951 return dst;
2952}
2953
2954RegisterID* BytecodeGenerator::emitNewArrayWithSize(RegisterID* dst, RegisterID* length)
2955{
2956 OpNewArrayWithSize::emit(this, dst, length);
2957 return dst;
2958}
2959
2960RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
2961{
2962 OpNewRegexp::emit(this, dst, addConstantValue(regExp));
2963 return dst;
2964}
2965
2966void BytecodeGenerator::emitNewFunctionExpressionCommon(RegisterID* dst, FunctionMetadataNode* function)
2967{
2968 unsigned index = m_codeBlock->addFunctionExpr(makeFunction(function));
2969
2970 switch (function->parseMode()) {
2971 case SourceParseMode::GeneratorWrapperFunctionMode:
2972 case SourceParseMode::GeneratorWrapperMethodMode:
2973 OpNewGeneratorFuncExp::emit(this, dst, scopeRegister(), index);
2974 break;
2975 case SourceParseMode::AsyncFunctionMode:
2976 case SourceParseMode::AsyncMethodMode:
2977 case SourceParseMode::AsyncArrowFunctionMode:
2978 OpNewAsyncFuncExp::emit(this, dst, scopeRegister(), index);
2979 break;
2980 case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
2981 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
2982 OpNewAsyncGeneratorFuncExp::emit(this, dst, scopeRegister(), index);
2983 break;
2984 default:
2985 OpNewFuncExp::emit(this, dst, scopeRegister(), index);
2986 break;
2987 }
2988}
2989
2990RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func)
2991{
2992 emitNewFunctionExpressionCommon(dst, func->metadata());
2993 return dst;
2994}
2995
2996RegisterID* BytecodeGenerator::emitNewArrowFunctionExpression(RegisterID* dst, ArrowFuncExprNode* func)
2997{
2998 ASSERT(SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode).contains(func->metadata()->parseMode()));
2999 emitNewFunctionExpressionCommon(dst, func->metadata());
3000 return dst;
3001}
3002
3003RegisterID* BytecodeGenerator::emitNewMethodDefinition(RegisterID* dst, MethodDefinitionNode* func)
3004{
3005 ASSERT(isMethodParseMode(func->metadata()->parseMode()));
3006 emitNewFunctionExpressionCommon(dst, func->metadata());
3007 return dst;
3008}
3009
3010RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name,
3011 const Identifier& ecmaName, const SourceCode& classSource)
3012{
3013 UnlinkedFunctionExecutable* executable = m_vm.builtinExecutables()->createDefaultConstructor(constructorKind, name);
3014 executable->setInvalidTypeProfilingOffsets();
3015 executable->setEcmaName(ecmaName);
3016 executable->setClassSource(classSource);
3017
3018 unsigned index = m_codeBlock->addFunctionExpr(executable);
3019
3020 OpNewFuncExp::emit(this, dst, scopeRegister(), index);
3021 return dst;
3022}
3023
3024RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionMetadataNode* function)
3025{
3026 unsigned index = m_codeBlock->addFunctionDecl(makeFunction(function));
3027 if (isGeneratorWrapperParseMode(function->parseMode()))
3028 OpNewGeneratorFunc::emit(this, dst, scopeRegister(), index);
3029 else if (function->parseMode() == SourceParseMode::AsyncFunctionMode)
3030 OpNewAsyncFunc::emit(this, dst, scopeRegister(), index);
3031 else if (isAsyncGeneratorWrapperParseMode(function->parseMode()))
3032 OpNewAsyncGeneratorFunc::emit(this, dst, scopeRegister(), index);
3033 else
3034 OpNewFunc::emit(this, dst, scopeRegister(), index);
3035 return dst;
3036}
3037
3038void BytecodeGenerator::emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name)
3039{
3040 if (valueNode->isBaseFuncExprNode()) {
3041 FunctionMetadataNode* metadata = static_cast<BaseFuncExprNode*>(valueNode)->metadata();
3042 if (!metadata->ecmaName().isNull())
3043 return;
3044 } else if (valueNode->isClassExprNode()) {
3045 ClassExprNode* classExprNode = static_cast<ClassExprNode*>(valueNode);
3046 if (!classExprNode->ecmaName().isNull())
3047 return;
3048 if (classExprNode->hasStaticProperty(m_vm.propertyNames->name))
3049 return;
3050 } else
3051 return;
3052
3053 // FIXME: We should use an op_call to an internal function here instead.
3054 // https://bugs.webkit.org/show_bug.cgi?id=155547
3055 OpSetFunctionName::emit(this, value, name);
3056}
3057
3058RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3059{
3060 return emitCall<OpCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
3061}
3062
3063RegisterID* BytecodeGenerator::emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3064{
3065 if (m_inTailPosition) {
3066 m_codeBlock->setHasTailCalls();
3067 return emitCall<OpTailCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
3068 }
3069 return emitCall<OpCall>(dst, func, expectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
3070}
3071
3072RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3073{
3074 return emitCall<OpCallEval>(dst, func, NoExpectedFunction, callArguments, divot, divotStart, divotEnd, debuggableCall);
3075}
3076
3077ExpectedFunction BytecodeGenerator::expectedFunctionForIdentifier(const Identifier& identifier)
3078{
3079 if (identifier == propertyNames().Object || identifier == propertyNames().builtinNames().ObjectPrivateName())
3080 return ExpectObjectConstructor;
3081 if (identifier == propertyNames().Array || identifier == propertyNames().builtinNames().ArrayPrivateName())
3082 return ExpectArrayConstructor;
3083 return NoExpectedFunction;
3084}
3085
3086ExpectedFunction BytecodeGenerator::emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, Label& done)
3087{
3088 Ref<Label> realCall = newLabel();
3089 switch (expectedFunction) {
3090 case ExpectObjectConstructor: {
3091 // If the number of arguments is non-zero, then we can't do anything interesting.
3092 if (callArguments.argumentCountIncludingThis() >= 2)
3093 return NoExpectedFunction;
3094
3095 OpJneqPtr::emit(this, func, moveLinkTimeConstant(nullptr, LinkTimeConstant::Object), realCall->bind(this));
3096
3097 if (dst != ignoredResult())
3098 emitNewObject(dst);
3099 break;
3100 }
3101
3102 case ExpectArrayConstructor: {
3103 // If you're doing anything other than "new Array()" or "new Array(foo)" then we
3104 // don't do inline it, for now. The only reason is that call arguments are in
3105 // the opposite order of what op_new_array expects, so we'd either need to change
3106 // how op_new_array works or we'd need an op_new_array_reverse. Neither of these
3107 // things sounds like it's worth it.
3108 if (callArguments.argumentCountIncludingThis() > 2)
3109 return NoExpectedFunction;
3110
3111 OpJneqPtr::emit(this, func, moveLinkTimeConstant(nullptr, LinkTimeConstant::Array), realCall->bind(this));
3112
3113 if (dst != ignoredResult()) {
3114 if (callArguments.argumentCountIncludingThis() == 2)
3115 emitNewArrayWithSize(dst, callArguments.argumentRegister(0));
3116 else {
3117 ASSERT(callArguments.argumentCountIncludingThis() == 1);
3118 OpNewArray::emit(this, dst, VirtualRegister { 0 }, 0, ArrayWithUndecided);
3119 }
3120 }
3121 break;
3122 }
3123
3124 default:
3125 ASSERT(expectedFunction == NoExpectedFunction);
3126 return NoExpectedFunction;
3127 }
3128
3129 OpJmp::emit(this, done.bind(this));
3130 emitLabel(realCall.get());
3131
3132 return expectedFunction;
3133}
3134
3135template<typename CallOp>
3136RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3137{
3138 constexpr auto opcodeID = CallOp::opcodeID;
3139 ASSERT(opcodeID == op_call || opcodeID == op_call_eval || opcodeID == op_tail_call);
3140 ASSERT(func->refCount());
3141
3142 // Generate code for arguments.
3143 unsigned argument = 0;
3144 if (callArguments.argumentsNode()) {
3145 ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
3146 if (n && n->m_expr->isSpreadExpression()) {
3147 RELEASE_ASSERT(!n->m_next);
3148 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
3149 if (expression->isArrayLiteral()) {
3150 auto* elements = static_cast<ArrayNode*>(expression)->elements();
3151 if (elements && !elements->next() && elements->value()->isSpreadExpression()) {
3152 ExpressionNode* expression = static_cast<SpreadExpressionNode*>(elements->value())->expression();
3153 RefPtr<RegisterID> argumentRegister = emitNode(callArguments.argumentRegister(0), expression);
3154 OpSpread::emit(this, argumentRegister.get(), argumentRegister.get());
3155
3156 return emitCallVarargs<typename VarArgsOp<CallOp>::type>(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, debuggableCall);
3157 }
3158 }
3159 RefPtr<RegisterID> argumentRegister;
3160 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
3161 RefPtr<RegisterID> thisRegister = move(newTemporary(), callArguments.thisRegister());
3162 return emitCallVarargs<typename VarArgsOp<CallOp>::type>(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, debuggableCall);
3163 }
3164 for (; n; n = n->m_next)
3165 emitNode(callArguments.argumentRegister(argument++), n);
3166 }
3167
3168 // Reserve space for call frame.
3169 Vector<RefPtr<RegisterID>, CallFrame::headerSizeInRegisters, UnsafeVectorOverflow> callFrame;
3170 for (int i = 0; i < CallFrame::headerSizeInRegisters; ++i)
3171 callFrame.append(newTemporary());
3172
3173 if (shouldEmitDebugHooks() && debuggableCall == DebuggableCall::Yes)
3174 emitDebugHook(WillExecuteExpression, divotStart);
3175
3176 emitExpressionInfo(divot, divotStart, divotEnd);
3177
3178 Ref<Label> done = newLabel();
3179 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
3180
3181 if (opcodeID == op_tail_call)
3182 emitLogShadowChickenTailIfNecessary();
3183
3184 // Emit call.
3185 ASSERT(dst);
3186 ASSERT(dst != ignoredResult());
3187 CallOp::emit(this, dst, func, callArguments.argumentCountIncludingThis(), callArguments.stackOffset());
3188
3189 if (expectedFunction != NoExpectedFunction)
3190 emitLabel(done.get());
3191
3192 return dst;
3193}
3194
3195RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3196{
3197 return emitCallVarargs<OpCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
3198}
3199
3200RegisterID* BytecodeGenerator::emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3201{
3202 if (m_inTailPosition)
3203 return emitCallVarargs<OpTailCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
3204 return emitCallVarargs<OpCallVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
3205}
3206
3207RegisterID* BytecodeGenerator::emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3208{
3209 return emitCallVarargs<OpConstructVarargs>(dst, func, thisRegister, arguments, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
3210}
3211
3212RegisterID* BytecodeGenerator::emitCallForwardArgumentsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3213{
3214 // We must emit a tail call here because we did not allocate an arguments object thus we would otherwise have no way to correctly make this call.
3215 ASSERT(m_inTailPosition || !Options::useTailCalls());
3216 return emitCallVarargs<OpTailCallForwardArguments>(dst, func, thisRegister, nullptr, firstFreeRegister, firstVarArgOffset, divot, divotStart, divotEnd, debuggableCall);
3217}
3218
3219template<typename VarargsOp>
3220RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall debuggableCall)
3221{
3222 if (shouldEmitDebugHooks() && debuggableCall == DebuggableCall::Yes)
3223 emitDebugHook(WillExecuteExpression, divotStart);
3224
3225 emitExpressionInfo(divot, divotStart, divotEnd);
3226
3227 if (VarargsOp::opcodeID == op_tail_call_varargs)
3228 emitLogShadowChickenTailIfNecessary();
3229
3230 // Emit call.
3231 ASSERT(dst != ignoredResult());
3232 VarargsOp::emit(this, dst, func, thisRegister, arguments ? arguments : VirtualRegister(0), firstFreeRegister, firstVarArgOffset);
3233 return dst;
3234}
3235
3236void BytecodeGenerator::emitLogShadowChickenPrologueIfNecessary()
3237{
3238 if (!shouldEmitDebugHooks() && !Options::alwaysUseShadowChicken())
3239 return;
3240 OpLogShadowChickenPrologue::emit(this, scopeRegister());
3241}
3242
3243void BytecodeGenerator::emitLogShadowChickenTailIfNecessary()
3244{
3245 if (!shouldEmitDebugHooks() && !Options::alwaysUseShadowChicken())
3246 return;
3247 OpLogShadowChickenTail::emit(this, thisRegister(), scopeRegister());
3248}
3249
3250void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
3251 RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition& position)
3252{
3253 DefinePropertyAttributes attributes;
3254 if (options & PropertyConfigurable)
3255 attributes.setConfigurable(true);
3256
3257 if (options & PropertyWritable)
3258 attributes.setWritable(true);
3259 else if (valueRegister)
3260 attributes.setWritable(false);
3261
3262 if (options & PropertyEnumerable)
3263 attributes.setEnumerable(true);
3264
3265 if (valueRegister)
3266 attributes.setValue();
3267 if (getterRegister)
3268 attributes.setGet();
3269 if (setterRegister)
3270 attributes.setSet();
3271
3272 ASSERT(!valueRegister || (!getterRegister && !setterRegister));
3273
3274 emitExpressionInfo(position, position, position);
3275
3276 if (attributes.hasGet() || attributes.hasSet()) {
3277 RefPtr<RegisterID> throwTypeErrorFunction;
3278 if (!attributes.hasGet() || !attributes.hasSet())
3279 throwTypeErrorFunction = moveLinkTimeConstant(nullptr, LinkTimeConstant::throwTypeErrorFunction);
3280
3281 RefPtr<RegisterID> getter;
3282 if (attributes.hasGet())
3283 getter = getterRegister;
3284 else
3285 getter = throwTypeErrorFunction;
3286
3287 RefPtr<RegisterID> setter;
3288 if (attributes.hasSet())
3289 setter = setterRegister;
3290 else
3291 setter = throwTypeErrorFunction;
3292
3293 OpDefineAccessorProperty::emit(this, newObj, propertyNameRegister, getter.get(), setter.get(), emitLoad(nullptr, jsNumber(attributes.rawRepresentation())));
3294 } else {
3295 OpDefineDataProperty::emit(this, newObj, propertyNameRegister, valueRegister, emitLoad(nullptr, jsNumber(attributes.rawRepresentation())));
3296 }
3297}
3298
3299RegisterID* BytecodeGenerator::emitReturn(RegisterID* src, ReturnFrom from)
3300{
3301 // Normal functions and naked constructors do not handle `return` specially.
3302 if (isConstructor() && constructorKind() != ConstructorKind::Naked) {
3303 bool isDerived = constructorKind() == ConstructorKind::Extends;
3304 bool srcIsThis = src->index() == m_thisRegister.index();
3305
3306 if (isDerived && (srcIsThis || from == ReturnFrom::Finally))
3307 emitTDZCheck(src);
3308
3309 if (!srcIsThis || from == ReturnFrom::Finally) {
3310 Ref<Label> isObjectLabel = newLabel();
3311 emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
3312
3313 if (isDerived) {
3314 Ref<Label> isUndefinedLabel = newLabel();
3315 emitJumpIfTrue(emitIsUndefined(newTemporary(), src), isUndefinedLabel.get());
3316 emitThrowTypeError("Cannot return a non-object type in the constructor of a derived class.");
3317 emitLabel(isUndefinedLabel.get());
3318 emitTDZCheck(&m_thisRegister);
3319 }
3320 OpRet::emit(this, &m_thisRegister);
3321 emitLabel(isObjectLabel.get());
3322 }
3323 }
3324
3325 OpRet::emit(this, src);
3326 return src;
3327}
3328
3329RegisterID* BytecodeGenerator::emitEnd(RegisterID* src)
3330{
3331 OpEnd::emit(this, src);
3332 return src;
3333}
3334
3335
3336RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, RegisterID* lazyThis, ExpectedFunction expectedFunction, CallArguments& callArguments, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
3337{
3338 ASSERT(func->refCount());
3339
3340 // Generate code for arguments.
3341 unsigned argument = 0;
3342 if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
3343
3344 ArgumentListNode* n = callArguments.argumentsNode()->m_listNode;
3345 if (n && n->m_expr->isSpreadExpression()) {
3346 RELEASE_ASSERT(!n->m_next);
3347 auto expression = static_cast<SpreadExpressionNode*>(n->m_expr)->expression();
3348 if (expression->isArrayLiteral()) {
3349 auto* elements = static_cast<ArrayNode*>(expression)->elements();
3350 if (elements && !elements->next() && elements->value()->isSpreadExpression()) {
3351 ExpressionNode* expression = static_cast<SpreadExpressionNode*>(elements->value())->expression();
3352 RefPtr<RegisterID> argumentRegister = emitNode(callArguments.argumentRegister(0), expression);
3353 OpSpread::emit(this, argumentRegister.get(), argumentRegister.get());
3354
3355 move(callArguments.thisRegister(), lazyThis);
3356 RefPtr<RegisterID> thisRegister = move(newTemporary(), callArguments.thisRegister());
3357 return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
3358 }
3359 }
3360 RefPtr<RegisterID> argumentRegister;
3361 argumentRegister = expression->emitBytecode(*this, callArguments.argumentRegister(0));
3362 move(callArguments.thisRegister(), lazyThis);
3363 return emitConstructVarargs(dst, func, callArguments.thisRegister(), argumentRegister.get(), newTemporary(), 0, divot, divotStart, divotEnd, DebuggableCall::No);
3364 }
3365
3366 for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
3367 emitNode(callArguments.argumentRegister(argument++), n);
3368 }
3369
3370 move(callArguments.thisRegister(), lazyThis);
3371
3372 // Reserve space for call frame.
3373 Vector<RefPtr<RegisterID>, CallFrame::headerSizeInRegisters, UnsafeVectorOverflow> callFrame;
3374 for (int i = 0; i < CallFrame::headerSizeInRegisters; ++i)
3375 callFrame.append(newTemporary());
3376
3377 emitExpressionInfo(divot, divotStart, divotEnd);
3378
3379 Ref<Label> done = newLabel();
3380 expectedFunction = emitExpectedFunctionSnippet(dst, func, expectedFunction, callArguments, done.get());
3381
3382 OpConstruct::emit(this, dst, func, callArguments.argumentCountIncludingThis(), callArguments.stackOffset());
3383
3384 if (expectedFunction != NoExpectedFunction)
3385 emitLabel(done.get());
3386
3387 return dst;
3388}
3389
3390RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
3391{
3392 OpStrcat::emit(this, dst, src, count);
3393 return dst;
3394}
3395
3396void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
3397{
3398 OpToPrimitive::emit(this, dst, src);
3399}
3400
3401void BytecodeGenerator::emitGetScope()
3402{
3403 OpGetScope::emit(this, scopeRegister());
3404}
3405
3406RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* objectScope)
3407{
3408 pushLocalControlFlowScope();
3409 RegisterID* newScope = newBlockScopeVariable();
3410 newScope->ref();
3411
3412 OpPushWithScope::emit(this, newScope, scopeRegister(), objectScope);
3413
3414 move(scopeRegister(), newScope);
3415 m_lexicalScopeStack.append({ nullptr, newScope, true, 0 });
3416
3417 return newScope;
3418}
3419
3420RegisterID* BytecodeGenerator::emitGetParentScope(RegisterID* dst, RegisterID* scope)
3421{
3422 OpGetParentScope::emit(this, dst, scope);
3423 return dst;
3424}
3425
3426void BytecodeGenerator::emitPopWithScope()
3427{
3428 emitGetParentScope(scopeRegister(), scopeRegister());
3429 popLocalControlFlowScope();
3430 auto stackEntry = m_lexicalScopeStack.takeLast();
3431 stackEntry.m_scope->deref();
3432 RELEASE_ASSERT(stackEntry.m_isWithScope);
3433}
3434
3435void BytecodeGenerator::emitDebugHook(DebugHookType debugHookType, const JSTextPosition& divot)
3436{
3437 if (!shouldEmitDebugHooks())
3438 return;
3439
3440 emitExpressionInfo(divot, divot, divot);
3441 OpDebug::emit(this, debugHookType, false);
3442}
3443
3444void BytecodeGenerator::emitDebugHook(DebugHookType debugHookType, unsigned line, unsigned charOffset, unsigned lineStart)
3445{
3446 emitDebugHook(debugHookType, JSTextPosition(line, charOffset, lineStart));
3447}
3448
3449void BytecodeGenerator::emitDebugHook(StatementNode* statement)
3450{
3451 // DebuggerStatementNode will output its own special debug hook.
3452 if (statement->isDebuggerStatement())
3453 return;
3454
3455 emitDebugHook(WillExecuteStatement, statement->position());
3456}
3457
3458void BytecodeGenerator::emitDebugHook(ExpressionNode* expr)
3459{
3460 emitDebugHook(WillExecuteStatement, expr->position());
3461}
3462
3463void BytecodeGenerator::emitWillLeaveCallFrameDebugHook()
3464{
3465 RELEASE_ASSERT(m_scopeNode->isFunctionNode());
3466 emitDebugHook(WillLeaveCallFrame, m_scopeNode->lastLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset());
3467}
3468
3469void BytecodeGenerator::pushFinallyControlFlowScope(FinallyContext& finallyContext)
3470{
3471 ControlFlowScope scope(ControlFlowScope::Finally, currentLexicalScopeIndex(), &finallyContext);
3472 m_controlFlowScopeStack.append(WTFMove(scope));
3473
3474 m_finallyDepth++;
3475 m_currentFinallyContext = &finallyContext;
3476}
3477
3478void BytecodeGenerator::popFinallyControlFlowScope()
3479{
3480 ASSERT(m_controlFlowScopeStack.size());
3481 ASSERT(m_controlFlowScopeStack.last().isFinallyScope());
3482 ASSERT(m_finallyDepth > 0);
3483 ASSERT(m_currentFinallyContext);
3484 m_currentFinallyContext = m_currentFinallyContext->outerContext();
3485 m_finallyDepth--;
3486 m_controlFlowScopeStack.removeLast();
3487}
3488
3489LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
3490{
3491 shrinkToFit(m_labelScopes);
3492
3493 if (!m_labelScopes.size())
3494 return nullptr;
3495
3496 // We special-case the following, which is a syntax error in Firefox:
3497 // label:
3498 // break;
3499 if (name.isEmpty()) {
3500 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
3501 LabelScope& scope = m_labelScopes[i];
3502 if (scope.type() != LabelScope::NamedLabel)
3503 return &scope;
3504 }
3505 return nullptr;
3506 }
3507
3508 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
3509 LabelScope& scope = m_labelScopes[i];
3510 if (scope.name() && *scope.name() == name)
3511 return &scope;
3512 }
3513 return nullptr;
3514}
3515
3516LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
3517{
3518 shrinkToFit(m_labelScopes);
3519
3520 if (!m_labelScopes.size())
3521 return nullptr;
3522
3523 if (name.isEmpty()) {
3524 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
3525 LabelScope& scope = m_labelScopes[i];
3526 if (scope.type() == LabelScope::Loop) {
3527 ASSERT(scope.continueTarget());
3528 return &scope;
3529 }
3530 }
3531 return nullptr;
3532 }
3533
3534 // Continue to the loop nested nearest to the label scope that matches
3535 // 'name'.
3536 LabelScope* result = nullptr;
3537 for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
3538 LabelScope& scope = m_labelScopes[i];
3539 if (scope.type() == LabelScope::Loop) {
3540 ASSERT(scope.continueTarget());
3541 result = &scope;
3542 }
3543 if (scope.name() && *scope.name() == name)
3544 return result; // may be null.
3545 }
3546 return nullptr;
3547}
3548
3549void BytecodeGenerator::allocateAndEmitScope()
3550{
3551 m_scopeRegister = addVar();
3552 m_scopeRegister->ref();
3553 m_codeBlock->setScopeRegister(scopeRegister()->virtualRegister());
3554 emitGetScope();
3555 m_topMostScope = addVar();
3556 move(m_topMostScope, scopeRegister());
3557}
3558
3559TryData* BytecodeGenerator::pushTry(Label& start, Label& handlerLabel, HandlerType handlerType)
3560{
3561 m_tryData.append(TryData { handlerLabel, handlerType });
3562 TryData* result = &m_tryData.last();
3563
3564 m_tryContextStack.append(TryContext {
3565 start,
3566 result
3567 });
3568
3569 return result;
3570}
3571
3572void BytecodeGenerator::popTry(TryData* tryData, Label& end)
3573{
3574 m_usesExceptions = true;
3575
3576 ASSERT_UNUSED(tryData, m_tryContextStack.last().tryData == tryData);
3577
3578 m_tryRanges.append(TryRange {
3579 m_tryContextStack.last().start.copyRef(),
3580 end,
3581 m_tryContextStack.last().tryData
3582 });
3583 m_tryContextStack.removeLast();
3584}
3585
3586void BytecodeGenerator::emitOutOfLineCatchHandler(RegisterID* thrownValueRegister, RegisterID* completionTypeRegister, TryData* data)
3587{
3588 RegisterID* unused = newTemporary();
3589 emitOutOfLineExceptionHandler(unused, thrownValueRegister, completionTypeRegister, data);
3590}
3591
3592void BytecodeGenerator::emitOutOfLineFinallyHandler(RegisterID* exceptionRegister, RegisterID* completionTypeRegister, TryData* data)
3593{
3594 RegisterID* unused = newTemporary();
3595 ASSERT(completionTypeRegister);
3596 emitOutOfLineExceptionHandler(exceptionRegister, unused, completionTypeRegister, data);
3597}
3598
3599void BytecodeGenerator::emitOutOfLineExceptionHandler(RegisterID* exceptionRegister, RegisterID* thrownValueRegister, RegisterID* completionTypeRegister, TryData* data)
3600{
3601 VirtualRegister completionTypeVirtualRegister = completionTypeRegister ? completionTypeRegister : VirtualRegister();
3602 m_exceptionHandlersToEmit.append({ data, exceptionRegister, thrownValueRegister, completionTypeVirtualRegister });
3603}
3604
3605void BytecodeGenerator::restoreScopeRegister(int lexicalScopeIndex)
3606{
3607 if (lexicalScopeIndex == CurrentLexicalScopeIndex)
3608 return; // No change needed.
3609
3610 if (lexicalScopeIndex != OutermostLexicalScopeIndex) {
3611 ASSERT(lexicalScopeIndex < static_cast<int>(m_lexicalScopeStack.size()));
3612 int endIndex = lexicalScopeIndex + 1;
3613 for (size_t i = endIndex; i--; ) {
3614 if (m_lexicalScopeStack[i].m_scope) {
3615 move(scopeRegister(), m_lexicalScopeStack[i].m_scope);
3616 return;
3617 }
3618 }
3619 }
3620 // Note that if we don't find a local scope in the current function/program,
3621 // we must grab the outer-most scope of this bytecode generation.
3622 move(scopeRegister(), m_topMostScope);
3623}
3624
3625void BytecodeGenerator::restoreScopeRegister()
3626{
3627 restoreScopeRegister(currentLexicalScopeIndex());
3628}
3629
3630int BytecodeGenerator::labelScopeDepthToLexicalScopeIndex(int targetLabelScopeDepth)
3631{
3632 ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0);
3633 size_t scopeDelta = labelScopeDepth() - targetLabelScopeDepth;
3634 ASSERT(scopeDelta <= m_controlFlowScopeStack.size());
3635 if (!scopeDelta)
3636 return CurrentLexicalScopeIndex;
3637
3638 ControlFlowScope& targetScope = m_controlFlowScopeStack[targetLabelScopeDepth];
3639 return targetScope.lexicalScopeIndex;
3640}
3641
3642void BytecodeGenerator::emitThrow(RegisterID* exc)
3643{
3644 m_usesExceptions = true;
3645 OpThrow::emit(this, exc);
3646}
3647
3648RegisterID* BytecodeGenerator::emitArgumentCount(RegisterID* dst)
3649{
3650 OpArgumentCount::emit(this, dst);
3651 return dst;
3652}
3653
3654unsigned BytecodeGenerator::localScopeDepth() const
3655{
3656 return m_localScopeDepth;
3657}
3658
3659int BytecodeGenerator::labelScopeDepth() const
3660{
3661 unsigned depth = localScopeDepth() + m_finallyDepth;
3662 ASSERT(depth == m_controlFlowScopeStack.size());
3663 return depth;
3664}
3665
3666void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, RegisterID* raw)
3667{
3668 RefPtr<RegisterID> message = newTemporary();
3669 emitToString(message.get(), raw);
3670 OpThrowStaticError::emit(this, message.get(), errorType);
3671}
3672
3673void BytecodeGenerator::emitThrowStaticError(ErrorType errorType, const Identifier& message)
3674{
3675 OpThrowStaticError::emit(this, addConstantValue(addStringConstant(message)), errorType);
3676}
3677
3678void BytecodeGenerator::emitThrowReferenceError(const String& message)
3679{
3680 emitThrowStaticError(ErrorType::ReferenceError, Identifier::fromString(m_vm, message));
3681}
3682
3683void BytecodeGenerator::emitThrowTypeError(const String& message)
3684{
3685 emitThrowStaticError(ErrorType::TypeError, Identifier::fromString(m_vm, message));
3686}
3687
3688void BytecodeGenerator::emitThrowTypeError(const Identifier& message)
3689{
3690 emitThrowStaticError(ErrorType::TypeError, message);
3691}
3692
3693void BytecodeGenerator::emitThrowRangeError(const Identifier& message)
3694{
3695 emitThrowStaticError(ErrorType::RangeError, message);
3696}
3697
3698void BytecodeGenerator::emitThrowOutOfMemoryError()
3699{
3700 emitThrowStaticError(ErrorType::Error, Identifier::fromString(m_vm, "Out of memory"));
3701}
3702
3703void BytecodeGenerator::emitPushFunctionNameScope(const Identifier& property, RegisterID* callee, bool isCaptured)
3704{
3705 // There is some nuance here:
3706 // If we're in strict mode code, the function name scope variable acts exactly like a "const" variable.
3707 // If we're not in strict mode code, we want to allow bogus assignments to the name scoped variable.
3708 // This means any assignment to the variable won't throw, but it won't actually assign a new value to it.
3709 // To accomplish this, we don't report that this scope is a lexical scope. This will prevent
3710 // any throws when trying to assign to the variable (while still ensuring it keeps its original
3711 // value). There is some ugliness and exploitation of a leaky abstraction here, but it's better than
3712 // having a completely new op code and a class to handle name scopes which are so close in functionality
3713 // to lexical environments.
3714 VariableEnvironment nameScopeEnvironment;
3715 auto addResult = nameScopeEnvironment.add(property);
3716 if (isCaptured)
3717 addResult.iterator->value.setIsCaptured();
3718 addResult.iterator->value.setIsConst(); // The function name scope name acts like a const variable.
3719 unsigned numVars = m_codeBlock->m_numVars;
3720 pushLexicalScopeInternal(nameScopeEnvironment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::NotUnderTDZ, ScopeType::FunctionNameScope, ScopeRegisterType::Var);
3721 ASSERT_UNUSED(numVars, m_codeBlock->m_numVars == static_cast<int>(numVars + 1)); // Should have only created one new "var" for the function name scope.
3722 bool shouldTreatAsLexicalVariable = isStrictMode();
3723 Variable functionVar = variableForLocalEntry(property, m_lexicalScopeStack.last().m_symbolTable->get(NoLockingNecessary, property.impl()), m_lexicalScopeStack.last().m_symbolTableConstantIndex, shouldTreatAsLexicalVariable);
3724 emitPutToScope(m_lexicalScopeStack.last().m_scope, functionVar, callee, ThrowIfNotFound, InitializationMode::NotInitialization);
3725}
3726
3727void BytecodeGenerator::pushLocalControlFlowScope()
3728{
3729 ControlFlowScope scope(ControlFlowScope::Label, currentLexicalScopeIndex());
3730 m_controlFlowScopeStack.append(WTFMove(scope));
3731 m_localScopeDepth++;
3732}
3733
3734void BytecodeGenerator::popLocalControlFlowScope()
3735{
3736 ASSERT(m_controlFlowScopeStack.size());
3737 ASSERT(!m_controlFlowScopeStack.last().isFinallyScope());
3738 m_controlFlowScopeStack.removeLast();
3739 m_localScopeDepth--;
3740}
3741
3742void BytecodeGenerator::emitPushCatchScope(VariableEnvironment& environment)
3743{
3744 pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::CatchScope, ScopeRegisterType::Block);
3745}
3746
3747void BytecodeGenerator::emitPopCatchScope(VariableEnvironment& environment)
3748{
3749 popLexicalScopeInternal(environment);
3750}
3751
3752void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
3753{
3754 switch (type) {
3755 case SwitchInfo::SwitchImmediate: {
3756 size_t tableIndex = m_codeBlock->numberOfSwitchJumpTables();
3757 m_codeBlock->addSwitchJumpTable();
3758 OpSwitchImm::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
3759 break;
3760 }
3761 case SwitchInfo::SwitchCharacter: {
3762 size_t tableIndex = m_codeBlock->numberOfSwitchJumpTables();
3763 m_codeBlock->addSwitchJumpTable();
3764 OpSwitchChar::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
3765 break;
3766 }
3767 case SwitchInfo::SwitchString: {
3768 size_t tableIndex = m_codeBlock->numberOfStringSwitchJumpTables();
3769 m_codeBlock->addStringSwitchJumpTable();
3770 OpSwitchString::emit(this, tableIndex, BoundLabel(), scrutineeRegister);
3771 break;
3772 }
3773 default:
3774 RELEASE_ASSERT_NOT_REACHED();
3775 }
3776
3777 SwitchInfo info = { m_lastInstruction.offset(), type };
3778 m_switchContextStack.append(info);
3779}
3780
3781static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
3782{
3783 UNUSED_PARAM(max);
3784 ASSERT(node->isNumber());
3785 double value = static_cast<NumberNode*>(node)->value();
3786 int32_t key = static_cast<int32_t>(value);
3787 ASSERT(key == value);
3788 ASSERT(key >= min);
3789 ASSERT(key <= max);
3790 return key - min;
3791}
3792
3793static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
3794{
3795 UNUSED_PARAM(max);
3796 ASSERT(node->isString());
3797 StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
3798 ASSERT(clause->length() == 1);
3799
3800 int32_t key = (*clause)[0];
3801 ASSERT(key >= min);
3802 ASSERT(key <= max);
3803 return key - min;
3804}
3805
3806static void prepareJumpTableForSwitch(
3807 UnlinkedSimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount,
3808 const Vector<Ref<Label>, 8>& labels, ExpressionNode** nodes, int32_t min, int32_t max,
3809 int32_t (*keyGetter)(ExpressionNode*, int32_t min, int32_t max))
3810{
3811 jumpTable.min = min;
3812 jumpTable.branchOffsets.resize(max - min + 1);
3813 jumpTable.branchOffsets.fill(0);
3814 for (uint32_t i = 0; i < clauseCount; ++i) {
3815 // We're emitting this after the clause labels should have been fixed, so
3816 // the labels should not be "forward" references
3817 ASSERT(!labels[i]->isForward());
3818 jumpTable.add(keyGetter(nodes[i], min, max), labels[i]->bind(switchAddress));
3819 }
3820}
3821
3822static void prepareJumpTableForStringSwitch(UnlinkedStringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, const Vector<Ref<Label>, 8>& labels, ExpressionNode** nodes)
3823{
3824 for (uint32_t i = 0; i < clauseCount; ++i) {
3825 // We're emitting this after the clause labels should have been fixed, so
3826 // the labels should not be "forward" references
3827 ASSERT(!labels[i]->isForward());
3828
3829 ASSERT(nodes[i]->isString());
3830 StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
3831 jumpTable.offsetTable.add(clause, UnlinkedStringJumpTable::OffsetLocation { labels[i]->bind(switchAddress) });
3832 }
3833}
3834
3835void BytecodeGenerator::endSwitch(uint32_t clauseCount, const Vector<Ref<Label>, 8>& labels, ExpressionNode** nodes, Label& defaultLabel, int32_t min, int32_t max)
3836{
3837 SwitchInfo switchInfo = m_switchContextStack.last();
3838 m_switchContextStack.removeLast();
3839
3840 BoundLabel defaultTarget = defaultLabel.bind(switchInfo.bytecodeOffset);
3841 auto handleSwitch = [&](auto* op, auto bytecode) {
3842 op->setDefaultOffset(defaultTarget, [&]() {
3843 m_codeBlock->addOutOfLineJumpTarget(switchInfo.bytecodeOffset, defaultTarget);
3844 return BoundLabel();
3845 });
3846
3847 UnlinkedSimpleJumpTable& jumpTable = m_codeBlock->switchJumpTable(bytecode.m_tableIndex);
3848 prepareJumpTableForSwitch(
3849 jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max,
3850 switchInfo.switchType == SwitchInfo::SwitchImmediate
3851 ? keyForImmediateSwitch
3852 : keyForCharacterSwitch);
3853 };
3854
3855 auto ref = m_writer.ref(switchInfo.bytecodeOffset);
3856 switch (switchInfo.switchType) {
3857 case SwitchInfo::SwitchImmediate: {
3858 handleSwitch(ref->cast<OpSwitchImm>(), ref->as<OpSwitchImm>());
3859 break;
3860 }
3861 case SwitchInfo::SwitchCharacter: {
3862 handleSwitch(ref->cast<OpSwitchChar>(), ref->as<OpSwitchChar>());
3863 break;
3864 }
3865
3866 case SwitchInfo::SwitchString: {
3867 ref->cast<OpSwitchString>()->setDefaultOffset(defaultTarget, [&]() {
3868 m_codeBlock->addOutOfLineJumpTarget(switchInfo.bytecodeOffset, defaultTarget);
3869 return BoundLabel();
3870 });
3871
3872 UnlinkedStringJumpTable& jumpTable = m_codeBlock->stringSwitchJumpTable(ref->as<OpSwitchString>().m_tableIndex);
3873 prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
3874 break;
3875 }
3876
3877 default:
3878 RELEASE_ASSERT_NOT_REACHED();
3879 break;
3880 }
3881}
3882
3883RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
3884{
3885 // It would be nice to do an even better job of identifying exactly where the expression is.
3886 // And we could make the caller pass the node pointer in, if there was some way of getting
3887 // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
3888 // is still good enough to get us an accurate line number.
3889 m_expressionTooDeep = true;
3890 return newTemporary();
3891}
3892
3893bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
3894{
3895 RegisterID* registerID = variable(ident).local();
3896 if (!registerID)
3897 return false;
3898 return registerID->index() == CallFrame::argumentOffset(argumentNumber);
3899}
3900
3901bool BytecodeGenerator::emitReadOnlyExceptionIfNeeded(const Variable& variable)
3902{
3903 // If we're in strict mode, we always throw.
3904 // If we're not in strict mode, we throw for "const" variables but not the function callee.
3905 if (isStrictMode() || variable.isConst()) {
3906 emitThrowTypeError(Identifier::fromString(m_vm, ReadonlyPropertyWriteError));
3907 return true;
3908 }
3909 return false;
3910}
3911
3912void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const ScopedLambda<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable)
3913{
3914 bool isForAwait = forLoopNode ? forLoopNode->isForAwait() : false;
3915 ASSERT(!isForAwait || (isForAwait && isAsyncFunctionParseMode(parseMode())));
3916
3917 RefPtr<RegisterID> subject = newTemporary();
3918 emitNode(subject.get(), subjectNode);
3919 RefPtr<RegisterID> iterator = isForAwait ? emitGetAsyncIterator(subject.get(), node) : emitGetIterator(subject.get(), node);
3920 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next);
3921
3922 Ref<Label> loopDone = newLabel();
3923 Ref<Label> tryStartLabel = newLabel();
3924 Ref<Label> finallyViaThrowLabel = newLabel();
3925 Ref<Label> finallyLabel = newLabel();
3926 Ref<Label> catchLabel = newLabel();
3927 Ref<Label> endCatchLabel = newLabel();
3928
3929 // RefPtr<Register> iterator's lifetime must be longer than IteratorCloseContext.
3930 FinallyContext finallyContext(*this, finallyLabel.get());
3931 pushFinallyControlFlowScope(finallyContext);
3932
3933 {
3934 Ref<LabelScope> scope = newLabelScope(LabelScope::Loop);
3935 RefPtr<RegisterID> value = newTemporary();
3936 emitLoad(value.get(), jsUndefined());
3937
3938 emitJump(*scope->continueTarget());
3939
3940 Ref<Label> loopStart = newLabel();
3941 emitLabel(loopStart.get());
3942 emitLoopHint();
3943
3944 emitLabel(tryStartLabel.get());
3945 TryData* tryData = pushTry(tryStartLabel.get(), finallyViaThrowLabel.get(), HandlerType::SynthesizedFinally);
3946 callBack(*this, value.get());
3947 emitJump(*scope->continueTarget());
3948
3949 // IteratorClose sequence for abrupt completions.
3950 {
3951 // Finally block for the enumeration.
3952 emitLabel(finallyViaThrowLabel.get());
3953 popTry(tryData, finallyViaThrowLabel.get());
3954
3955 Ref<Label> finallyBodyLabel = newLabel();
3956 RefPtr<RegisterID> finallyExceptionRegister = newTemporary();
3957
3958 emitOutOfLineFinallyHandler(finallyContext.completionValueRegister(), finallyContext.completionTypeRegister(), tryData);
3959 move(finallyExceptionRegister.get(), finallyContext.completionValueRegister());
3960 emitJump(finallyBodyLabel.get());
3961
3962 emitLabel(finallyLabel.get());
3963 moveEmptyValue(finallyExceptionRegister.get());
3964
3965 // Finally fall through case.
3966 emitLabel(finallyBodyLabel.get());
3967 restoreScopeRegister();
3968
3969 Ref<Label> finallyDone = newLabel();
3970
3971 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
3972 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get());
3973
3974 Ref<Label> returnCallTryStart = newLabel();
3975 emitLabel(returnCallTryStart.get());
3976 TryData* returnCallTryData = pushTry(returnCallTryStart.get(), catchLabel.get(), HandlerType::SynthesizedCatch);
3977
3978 CallArguments returnArguments(*this, nullptr);
3979 move(returnArguments.thisRegister(), iterator.get());
3980 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
3981
3982 if (isForAwait)
3983 emitAwait(value.get());
3984
3985 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), finallyDone.get());
3986 emitThrowTypeError("Iterator result interface is not an object."_s);
3987
3988 emitLabel(finallyDone.get());
3989 emitFinallyCompletion(finallyContext, endCatchLabel.get());
3990
3991 popTry(returnCallTryData, finallyDone.get());
3992
3993 // Catch block for exceptions that may be thrown while calling the return
3994 // handler in the enumeration finally block. The only reason we need this
3995 // catch block is because if entered the above finally block due to a thrown
3996 // exception, then we want to re-throw the original exception on exiting
3997 // the finally block. Otherwise, we'll let any new exception pass through.
3998 {
3999 emitLabel(catchLabel.get());
4000
4001 RefPtr<RegisterID> exceptionRegister = newTemporary();
4002 emitOutOfLineFinallyHandler(exceptionRegister.get(), finallyContext.completionTypeRegister(), returnCallTryData);
4003 // Since this is a synthesized catch block and we're guaranteed to never need
4004 // to resolve any symbols from the scope, we can skip restoring the scope
4005 // register here.
4006
4007 Ref<Label> throwLabel = newLabel();
4008 emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyExceptionRegister.get()), throwLabel.get());
4009 move(exceptionRegister.get(), finallyExceptionRegister.get());
4010
4011 emitLabel(throwLabel.get());
4012 emitThrow(exceptionRegister.get());
4013
4014 emitLabel(endCatchLabel.get());
4015 }
4016 }
4017
4018 emitLabel(*scope->continueTarget());
4019 if (forLoopNode) {
4020 RELEASE_ASSERT(forLoopNode->isForOfNode());
4021 prepareLexicalScopeForNextForLoopIteration(forLoopNode, forLoopSymbolTable);
4022 emitDebugHook(forLoopNode->lexpr());
4023 }
4024
4025 {
4026 emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), node, isForAwait ? EmitAwait::Yes : EmitAwait::No);
4027
4028 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get());
4029 emitGetById(value.get(), value.get(), propertyNames().value);
4030 emitJump(loopStart.get());
4031 }
4032
4033 bool breakLabelIsBound = scope->breakTargetMayBeBound();
4034 if (breakLabelIsBound)
4035 emitLabel(scope->breakTarget());
4036 popFinallyControlFlowScope();
4037 if (breakLabelIsBound) {
4038 // IteratorClose sequence for break-ed control flow.
4039 emitIteratorClose(iterator.get(), node, isForAwait ? EmitAwait::Yes : EmitAwait::No);
4040 }
4041 }
4042 emitLabel(loopDone.get());
4043}
4044
4045RegisterID* BytecodeGenerator::emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode* taggedTemplate)
4046{
4047 TemplateObjectDescriptor::StringVector rawStrings;
4048 TemplateObjectDescriptor::OptionalStringVector cookedStrings;
4049
4050 TemplateStringListNode* templateString = taggedTemplate->templateLiteral()->templateStrings();
4051 for (; templateString; templateString = templateString->next()) {
4052 auto* string = templateString->value();
4053 ASSERT(string->raw());
4054 rawStrings.append(string->raw()->impl());
4055 if (!string->cooked())
4056 cookedStrings.append(WTF::nullopt);
4057 else
4058 cookedStrings.append(string->cooked()->impl());
4059 }
4060 RefPtr<RegisterID> constant = addTemplateObjectConstant(TemplateObjectDescriptor::create(WTFMove(rawStrings), WTFMove(cookedStrings)), taggedTemplate->endOffset());
4061 if (!dst)
4062 return constant.get();
4063 return move(dst, constant.get());
4064}
4065
4066RegisterID* BytecodeGenerator::emitGetGlobalPrivate(RegisterID* dst, const Identifier& property)
4067{
4068 dst = tempDestination(dst);
4069 Variable var = variable(property);
4070 if (RegisterID* local = var.local())
4071 return move(dst, local);
4072
4073 RefPtr<RegisterID> scope = newTemporary();
4074 move(scope.get(), emitResolveScope(scope.get(), var));
4075 return emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound);
4076}
4077
4078RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)
4079{
4080 OpGetEnumerableLength::emit(this, dst, base);
4081 return dst;
4082}
4083
4084RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
4085{
4086 OpHasGenericProperty::emit(this, dst, base, propertyName);
4087 return dst;
4088}
4089
4090RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
4091{
4092 OpHasIndexedProperty::emit(this, dst, base, propertyName);
4093 return dst;
4094}
4095
4096RegisterID* BytecodeGenerator::emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
4097{
4098 OpHasStructureProperty::emit(this, dst, base, propertyName, enumerator);
4099 return dst;
4100}
4101
4102RegisterID* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base)
4103{
4104 OpGetPropertyEnumerator::emit(this, dst, base);
4105 return dst;
4106}
4107
4108RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
4109{
4110 OpEnumeratorStructurePname::emit(this, dst, enumerator, index);
4111 return dst;
4112}
4113
4114RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
4115{
4116 OpEnumeratorGenericPname::emit(this, dst, enumerator, index);
4117 return dst;
4118}
4119
4120RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)
4121{
4122 OpToIndexString::emit(this, dst, index);
4123 return dst;
4124}
4125
4126RegisterID* BytecodeGenerator::emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType type)
4127{
4128 OpIsCellWithType::emit(this, dst, src, type);
4129 return dst;
4130}
4131
4132RegisterID* BytecodeGenerator::emitIsObject(RegisterID* dst, RegisterID* src)
4133{
4134 OpIsObject::emit(this, dst, src);
4135 return dst;
4136}
4137
4138RegisterID* BytecodeGenerator::emitIsNumber(RegisterID* dst, RegisterID* src)
4139{
4140 OpIsNumber::emit(this, dst, src);
4141 return dst;
4142}
4143
4144RegisterID* BytecodeGenerator::emitIsUndefined(RegisterID* dst, RegisterID* src)
4145{
4146 OpIsUndefined::emit(this, dst, src);
4147 return dst;
4148}
4149
4150RegisterID* BytecodeGenerator::emitIsUndefinedOrNull(RegisterID* dst, RegisterID* src)
4151{
4152 OpIsUndefinedOrNull::emit(this, dst, src);
4153 return dst;
4154}
4155
4156RegisterID* BytecodeGenerator::emitIsEmpty(RegisterID* dst, RegisterID* src)
4157{
4158 OpIsEmpty::emit(this, dst, src);
4159 return dst;
4160}
4161
4162RegisterID* BytecodeGenerator::emitIteratorNext(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait doEmitAwait)
4163{
4164 {
4165 CallArguments nextArguments(*this, nullptr);
4166 move(nextArguments.thisRegister(), iterator);
4167 emitCall(dst, nextMethod, NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
4168
4169 if (doEmitAwait == EmitAwait::Yes)
4170 emitAwait(dst);
4171 }
4172 {
4173 Ref<Label> typeIsObject = newLabel();
4174 emitJumpIfTrue(emitIsObject(newTemporary(), dst), typeIsObject.get());
4175 emitThrowTypeError("Iterator result interface is not an object."_s);
4176 emitLabel(typeIsObject.get());
4177 }
4178 return dst;
4179}
4180
4181RegisterID* BytecodeGenerator::emitIteratorNextWithValue(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node)
4182{
4183 {
4184 CallArguments nextArguments(*this, nullptr, 1);
4185 move(nextArguments.thisRegister(), iterator);
4186 move(nextArguments.argumentRegister(0), value);
4187 emitCall(dst, nextMethod, NoExpectedFunction, nextArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
4188 }
4189
4190 return dst;
4191}
4192
4193void BytecodeGenerator::emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait doEmitAwait)
4194{
4195 Ref<Label> done = newLabel();
4196 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator, propertyNames().returnKeyword);
4197 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), done.get());
4198
4199 RefPtr<RegisterID> value = newTemporary();
4200 CallArguments returnArguments(*this, nullptr);
4201 move(returnArguments.thisRegister(), iterator);
4202 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
4203
4204 if (doEmitAwait == EmitAwait::Yes)
4205 emitAwait(value.get());
4206
4207 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), done.get());
4208 emitThrowTypeError("Iterator result interface is not an object."_s);
4209 emitLabel(done.get());
4210}
4211
4212void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
4213{
4214 if (!localRegister)
4215 return;
4216 unsigned bodyBytecodeStartOffset = instructions().size();
4217 m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister, bodyBytecodeStartOffset)));
4218}
4219
4220void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
4221{
4222 if (!localRegister)
4223 return;
4224 unsigned bodyBytecodeEndOffset = instructions().size();
4225 m_forInContextStack.last()->asIndexedForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
4226 m_forInContextStack.removeLast();
4227}
4228
4229RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment(const Identifier& identifier)
4230{
4231 ASSERT(m_codeBlock->isArrowFunction() || m_codeBlock->isArrowFunctionContext() || constructorKind() == ConstructorKind::Extends || m_codeType == EvalCode);
4232
4233 return emitResolveScope(nullptr, variable(identifier, ThisResolutionType::Scoped));
4234}
4235
4236void BytecodeGenerator::emitLoadThisFromArrowFunctionLexicalEnvironment()
4237{
4238 emitGetFromScope(thisRegister(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier), variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped), DoNotThrowIfNotFound);
4239}
4240
4241RegisterID* BytecodeGenerator::emitLoadNewTargetFromArrowFunctionLexicalEnvironment()
4242{
4243 Variable newTargetVar = variable(propertyNames().builtinNames().newTargetLocalPrivateName());
4244
4245 return emitGetFromScope(m_newTargetRegister, emitLoadArrowFunctionLexicalEnvironment(propertyNames().builtinNames().newTargetLocalPrivateName()), newTargetVar, ThrowIfNotFound);
4246
4247}
4248
4249RegisterID* BytecodeGenerator::emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment()
4250{
4251 Variable protoScopeVar = variable(propertyNames().builtinNames().derivedConstructorPrivateName());
4252 return emitGetFromScope(newTemporary(), emitLoadArrowFunctionLexicalEnvironment(propertyNames().builtinNames().derivedConstructorPrivateName()), protoScopeVar, ThrowIfNotFound);
4253}
4254
4255RegisterID* BytecodeGenerator::ensureThis()
4256{
4257 if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext()) {
4258 if ((needsToUpdateArrowFunctionContext() && isSuperCallUsedInInnerArrowFunction()) || m_codeBlock->parseMode() == SourceParseMode::AsyncArrowFunctionBodyMode)
4259 emitLoadThisFromArrowFunctionLexicalEnvironment();
4260
4261 emitTDZCheck(thisRegister());
4262 }
4263
4264 return thisRegister();
4265}
4266
4267bool BytecodeGenerator::isThisUsedInInnerArrowFunction()
4268{
4269 return m_scopeNode->doAnyInnerArrowFunctionsUseThis() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
4270}
4271
4272bool BytecodeGenerator::isArgumentsUsedInInnerArrowFunction()
4273{
4274 return m_scopeNode->doAnyInnerArrowFunctionsUseArguments() || m_scopeNode->doAnyInnerArrowFunctionsUseEval();
4275}
4276
4277bool BytecodeGenerator::isNewTargetUsedInInnerArrowFunction()
4278{
4279 return m_scopeNode->doAnyInnerArrowFunctionsUseNewTarget() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
4280}
4281
4282bool BytecodeGenerator::isSuperUsedInInnerArrowFunction()
4283{
4284 return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
4285}
4286
4287bool BytecodeGenerator::isSuperCallUsedInInnerArrowFunction()
4288{
4289 return m_scopeNode->doAnyInnerArrowFunctionsUseSuperCall() || m_scopeNode->doAnyInnerArrowFunctionsUseEval() || m_codeBlock->usesEval();
4290}
4291
4292void BytecodeGenerator::emitPutNewTargetToArrowFunctionContextScope()
4293{
4294 if (isNewTargetUsedInInnerArrowFunction()) {
4295 ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
4296
4297 Variable newTargetVar = variable(propertyNames().builtinNames().newTargetLocalPrivateName());
4298 emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, newTargetVar, newTarget(), DoNotThrowIfNotFound, InitializationMode::Initialization);
4299 }
4300}
4301
4302void BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope()
4303{
4304 if (needsDerivedConstructorInArrowFunctionLexicalEnvironment()) {
4305 ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
4306
4307 Variable protoScope = variable(propertyNames().builtinNames().derivedConstructorPrivateName());
4308 emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, protoScope, &m_calleeRegister, DoNotThrowIfNotFound, InitializationMode::Initialization);
4309 }
4310}
4311
4312void BytecodeGenerator::emitPutThisToArrowFunctionContextScope()
4313{
4314 if (isThisUsedInInnerArrowFunction() || (m_scopeNode->usesSuperCall() && m_codeType == EvalCode)) {
4315 ASSERT(isDerivedConstructorContext() || m_arrowFunctionContextLexicalEnvironmentRegister != nullptr);
4316
4317 Variable thisVar = variable(propertyNames().thisIdentifier, ThisResolutionType::Scoped);
4318 RegisterID* scope = isDerivedConstructorContext() ? emitLoadArrowFunctionLexicalEnvironment(propertyNames().thisIdentifier) : m_arrowFunctionContextLexicalEnvironmentRegister;
4319
4320 emitPutToScope(scope, thisVar, thisRegister(), ThrowIfNotFound, InitializationMode::NotInitialization);
4321 }
4322}
4323
4324void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
4325{
4326 if (!localRegister)
4327 return;
4328 unsigned bodyBytecodeStartOffset = instructions().size();
4329 m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister, bodyBytecodeStartOffset)));
4330}
4331
4332void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
4333{
4334 if (!localRegister)
4335 return;
4336 unsigned bodyBytecodeEndOffset = instructions().size();
4337 m_forInContextStack.last()->asStructureForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset);
4338 m_forInContextStack.removeLast();
4339}
4340
4341RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip)
4342{
4343 RefPtr<RegisterID> restArrayLength = newTemporary();
4344 OpGetRestLength::emit(this, restArrayLength.get(), numParametersToSkip);
4345
4346 OpCreateRest::emit(this, result, restArrayLength.get(), numParametersToSkip);
4347
4348 return result;
4349}
4350
4351void BytecodeGenerator::emitRequireObjectCoercible(RegisterID* value, const String& error)
4352{
4353 Ref<Label> target = newLabel();
4354 OpJnundefinedOrNull::emit(this, value, target->bind(this));
4355 emitThrowTypeError(error);
4356 emitLabel(target.get());
4357}
4358
4359void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason result)
4360{
4361 Ref<Label> mergePoint = newLabel();
4362 unsigned yieldPointIndex = m_yieldPoints++;
4363 emitGeneratorStateChange(yieldPointIndex + 1);
4364
4365 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) {
4366 int suspendReason = static_cast<int32_t>(result);
4367 emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSAsyncGenerator::Field::SuspendReason), emitLoad(nullptr, jsNumber(suspendReason)));
4368 }
4369
4370 // Split the try range here.
4371 Ref<Label> savePoint = newEmittedLabel();
4372 for (unsigned i = m_tryContextStack.size(); i--;) {
4373 TryContext& context = m_tryContextStack[i];
4374 m_tryRanges.append(TryRange {
4375 context.start.copyRef(),
4376 savePoint.copyRef(),
4377 context.tryData
4378 });
4379 // Try range will be restared at the merge point.
4380 context.start = mergePoint.get();
4381 }
4382 Vector<TryContext> savedTryContextStack;
4383 m_tryContextStack.swap(savedTryContextStack);
4384
4385
4386#if CPU(NEEDS_ALIGNED_ACCESS)
4387 // conservatively align for the bytecode rewriter: it will delete this yield and
4388 // append a fragment, so we make sure that the start of the fragments is aligned
4389 while (m_writer.position() % OpcodeSize::Wide32)
4390 OpNop::emit<OpcodeSize::Narrow>(this);
4391#endif
4392 OpYield::emit(this, generatorFrameRegister(), yieldPointIndex, argument);
4393
4394 // Restore the try contexts, which start offset is updated to the merge point.
4395 m_tryContextStack.swap(savedTryContextStack);
4396 emitLabel(mergePoint.get());
4397}
4398
4399RegisterID* BytecodeGenerator::emitYield(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason result)
4400{
4401 emitYieldPoint(argument, result);
4402
4403 Ref<Label> normalLabel = newLabel();
4404 RefPtr<RegisterID> condition = newTemporary();
4405 emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::NormalMode))));
4406 emitJumpIfTrue(condition.get(), normalLabel.get());
4407
4408 Ref<Label> throwLabel = newLabel();
4409 emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::ThrowMode))));
4410 emitJumpIfTrue(condition.get(), throwLabel.get());
4411 // Return.
4412 {
4413 RefPtr<RegisterID> returnRegister = generatorValueRegister();
4414 bool hasFinally = emitReturnViaFinallyIfNeeded(returnRegister.get());
4415 if (!hasFinally)
4416 emitReturn(returnRegister.get());
4417 }
4418
4419 // Throw.
4420 emitLabel(throwLabel.get());
4421 emitThrow(generatorValueRegister());
4422
4423 // Normal.
4424 emitLabel(normalLabel.get());
4425 return generatorValueRegister();
4426}
4427
4428RegisterID* BytecodeGenerator::emitCallIterator(RegisterID* iterator, RegisterID* argument, ThrowableExpressionData* node)
4429{
4430 CallArguments args(*this, nullptr);
4431 move(args.thisRegister(), argument);
4432 emitCall(iterator, iterator, NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
4433
4434 return iterator;
4435}
4436
4437void BytecodeGenerator::emitAwait(RegisterID* value)
4438{
4439 emitYield(value, JSAsyncGenerator::AsyncGeneratorSuspendReason::Await);
4440 move(value, generatorValueRegister());
4441}
4442
4443RegisterID* BytecodeGenerator::emitGetIterator(RegisterID* argument, ThrowableExpressionData* node)
4444{
4445 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().iteratorSymbol);
4446 emitCallIterator(iterator.get(), argument, node);
4447
4448 return iterator.get();
4449}
4450
4451RegisterID* BytecodeGenerator::emitGetAsyncIterator(RegisterID* argument, ThrowableExpressionData* node)
4452{
4453 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().asyncIteratorSymbol);
4454 Ref<Label> asyncIteratorNotFound = newLabel();
4455 Ref<Label> asyncIteratorFound = newLabel();
4456 Ref<Label> iteratorReceived = newLabel();
4457
4458 emitJumpIfTrue(emitUnaryOp<OpEqNull>(newTemporary(), iterator.get()), asyncIteratorNotFound.get());
4459
4460 emitJump(asyncIteratorFound.get());
4461 emitLabel(asyncIteratorNotFound.get());
4462
4463 RefPtr<RegisterID> commonIterator = emitGetIterator(argument, node);
4464 move(iterator.get(), commonIterator.get());
4465
4466 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next);
4467
4468 RefPtr<RegisterID> createAsyncFromSyncIterator = moveLinkTimeConstant(nullptr, LinkTimeConstant::createAsyncFromSyncIterator);
4469
4470 CallArguments args(*this, nullptr, 2);
4471 emitLoad(args.thisRegister(), jsUndefined());
4472
4473 move(args.argumentRegister(0), iterator.get());
4474 move(args.argumentRegister(1), nextMethod.get());
4475
4476 JSTextPosition divot(m_scopeNode->firstLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset());
4477 emitCall(iterator.get(), createAsyncFromSyncIterator.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
4478
4479 emitJump(iteratorReceived.get());
4480
4481 emitLabel(asyncIteratorFound.get());
4482 emitCallIterator(iterator.get(), argument, node);
4483 emitLabel(iteratorReceived.get());
4484
4485 return iterator.get();
4486}
4487
4488RegisterID* BytecodeGenerator::emitDelegateYield(RegisterID* argument, ThrowableExpressionData* node)
4489{
4490 RefPtr<RegisterID> value = newTemporary();
4491 {
4492 RefPtr<RegisterID> iterator = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? emitGetAsyncIterator(argument, node) : emitGetIterator(argument, node);
4493 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next);
4494
4495 Ref<Label> loopDone = newLabel();
4496 {
4497 Ref<Label> nextElement = newLabel();
4498 emitLoad(value.get(), jsUndefined());
4499
4500 emitJump(nextElement.get());
4501
4502 Ref<Label> loopStart = newLabel();
4503 emitLabel(loopStart.get());
4504 emitLoopHint();
4505
4506 Ref<Label> branchOnResult = newLabel();
4507 {
4508 emitYieldPoint(value.get(), JSAsyncGenerator::AsyncGeneratorSuspendReason::Yield);
4509
4510 Ref<Label> normalLabel = newLabel();
4511 Ref<Label> returnLabel = newLabel();
4512 {
4513 RefPtr<RegisterID> condition = newTemporary();
4514 emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::NormalMode))));
4515 emitJumpIfTrue(condition.get(), normalLabel.get());
4516
4517 emitEqualityOp<OpStricteq>(condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::ReturnMode))));
4518 emitJumpIfTrue(condition.get(), returnLabel.get());
4519
4520 // Fallthrough to ThrowMode.
4521 }
4522
4523 // Throw.
4524 {
4525 Ref<Label> throwMethodFound = newLabel();
4526 RefPtr<RegisterID> throwMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().throwKeyword);
4527 emitJumpIfFalse(emitIsUndefined(newTemporary(), throwMethod.get()), throwMethodFound.get());
4528
4529 EmitAwait emitAwaitInIteratorClose = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? EmitAwait::Yes : EmitAwait::No;
4530 emitIteratorClose(iterator.get(), node, emitAwaitInIteratorClose);
4531
4532 emitThrowTypeError("Delegated generator does not have a 'throw' method."_s);
4533
4534 emitLabel(throwMethodFound.get());
4535 CallArguments throwArguments(*this, nullptr, 1);
4536 move(throwArguments.thisRegister(), iterator.get());
4537 move(throwArguments.argumentRegister(0), generatorValueRegister());
4538 emitCall(value.get(), throwMethod.get(), NoExpectedFunction, throwArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
4539
4540 emitJump(branchOnResult.get());
4541 }
4542
4543 // Return.
4544 emitLabel(returnLabel.get());
4545 {
4546 Ref<Label> returnMethodFound = newLabel();
4547 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword);
4548 emitJumpIfFalse(emitIsUndefined(newTemporary(), returnMethod.get()), returnMethodFound.get());
4549
4550 move(value.get(), generatorValueRegister());
4551
4552 Ref<Label> returnSequence = newLabel();
4553 emitJump(returnSequence.get());
4554
4555 emitLabel(returnMethodFound.get());
4556 CallArguments returnArguments(*this, nullptr, 1);
4557 move(returnArguments.thisRegister(), iterator.get());
4558 move(returnArguments.argumentRegister(0), generatorValueRegister());
4559 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No);
4560
4561 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode)
4562 emitAwait(value.get());
4563
4564 Ref<Label> returnIteratorResultIsObject = newLabel();
4565 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), returnIteratorResultIsObject.get());
4566 emitThrowTypeError("Iterator result interface is not an object."_s);
4567
4568 emitLabel(returnIteratorResultIsObject.get());
4569
4570 Ref<Label> returnFromGenerator = newLabel();
4571 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), returnFromGenerator.get());
4572
4573 emitGetById(value.get(), value.get(), propertyNames().value);
4574 emitJump(loopStart.get());
4575
4576 emitLabel(returnFromGenerator.get());
4577 emitGetById(value.get(), value.get(), propertyNames().value);
4578
4579 emitLabel(returnSequence.get());
4580 bool hasFinally = emitReturnViaFinallyIfNeeded(value.get());
4581 if (!hasFinally)
4582 emitReturn(value.get());
4583 }
4584
4585 // Normal.
4586 emitLabel(normalLabel.get());
4587 move(value.get(), generatorValueRegister());
4588 }
4589
4590 emitLabel(nextElement.get());
4591 emitIteratorNextWithValue(value.get(), nextMethod.get(), iterator.get(), value.get(), node);
4592
4593 emitLabel(branchOnResult.get());
4594
4595 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode)
4596 emitAwait(value.get());
4597
4598 Ref<Label> iteratorValueIsObject = newLabel();
4599 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), iteratorValueIsObject.get());
4600 emitThrowTypeError("Iterator result interface is not an object."_s);
4601 emitLabel(iteratorValueIsObject.get());
4602
4603 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get());
4604 emitGetById(value.get(), value.get(), propertyNames().value);
4605
4606 emitJump(loopStart.get());
4607 }
4608 emitLabel(loopDone.get());
4609 }
4610
4611 emitGetById(value.get(), value.get(), propertyNames().value);
4612 return value.get();
4613}
4614
4615
4616void BytecodeGenerator::emitGeneratorStateChange(int32_t state)
4617{
4618 RegisterID* completedState = emitLoad(nullptr, jsNumber(state));
4619 static_assert(static_cast<unsigned>(JSGenerator::Field::State) == static_cast<unsigned>(JSAsyncGenerator::Field::State));
4620 emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::State), completedState);
4621}
4622
4623bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label& jumpTarget)
4624{
4625 ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0);
4626 size_t numberOfScopesToCheckForFinally = labelScopeDepth() - targetLabelScopeDepth;
4627 ASSERT(numberOfScopesToCheckForFinally <= m_controlFlowScopeStack.size());
4628 if (!numberOfScopesToCheckForFinally)
4629 return false;
4630
4631 FinallyContext* innermostFinallyContext = nullptr;
4632 FinallyContext* outermostFinallyContext = nullptr;
4633 size_t scopeIndex = m_controlFlowScopeStack.size() - 1;
4634 while (numberOfScopesToCheckForFinally--) {
4635 ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex--];
4636 if (scope->isFinallyScope()) {
4637 FinallyContext* finallyContext = scope->finallyContext;
4638 if (!innermostFinallyContext)
4639 innermostFinallyContext = finallyContext;
4640 outermostFinallyContext = finallyContext;
4641 finallyContext->incNumberOfBreaksOrContinues();
4642 }
4643 }
4644 if (!outermostFinallyContext)
4645 return false; // No finallys to thread through.
4646
4647 auto jumpID = bytecodeOffsetToJumpID(instructions().size());
4648 int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth);
4649 outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget);
4650
4651 emitLoad(innermostFinallyContext->completionTypeRegister(), jumpID);
4652 emitJump(*innermostFinallyContext->finallyLabel());
4653 return true; // We'll be jumping to a finally block.
4654}
4655
4656bool BytecodeGenerator::emitReturnViaFinallyIfNeeded(RegisterID* returnRegister)
4657{
4658 size_t numberOfScopesToCheckForFinally = m_controlFlowScopeStack.size();
4659 if (!numberOfScopesToCheckForFinally)
4660 return false;
4661
4662 FinallyContext* innermostFinallyContext = nullptr;
4663 while (numberOfScopesToCheckForFinally) {
4664 size_t scopeIndex = --numberOfScopesToCheckForFinally;
4665 ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex];
4666 if (scope->isFinallyScope()) {
4667 FinallyContext* finallyContext = scope->finallyContext;
4668 if (!innermostFinallyContext)
4669 innermostFinallyContext = finallyContext;
4670 finallyContext->setHandlesReturns();
4671 }
4672 }
4673 if (!innermostFinallyContext)
4674 return false; // No finallys to thread through.
4675
4676 emitLoad(innermostFinallyContext->completionTypeRegister(), CompletionType::Return);
4677 move(innermostFinallyContext->completionValueRegister(), returnRegister);
4678 emitJump(*innermostFinallyContext->finallyLabel());
4679 return true; // We'll be jumping to a finally block.
4680}
4681
4682void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, Label& normalCompletionLabel)
4683{
4684 if (context.numberOfBreaksOrContinues() || context.handlesReturns()) {
4685 emitJumpIf<OpStricteq>(context.completionTypeRegister(), CompletionType::Normal, normalCompletionLabel);
4686
4687 FinallyContext* outerContext = context.outerContext();
4688
4689 size_t numberOfJumps = context.numberOfJumps();
4690 ASSERT(outerContext || numberOfJumps == context.numberOfBreaksOrContinues());
4691
4692 // Handle Break or Continue completions that jumps into this FinallyContext.
4693 for (size_t i = 0; i < numberOfJumps; i++) {
4694 Ref<Label> nextLabel = newLabel();
4695 auto& jump = context.jumps(i);
4696 emitJumpIf<OpNstricteq>(context.completionTypeRegister(), jump.jumpID, nextLabel.get());
4697
4698 // This case is for Break / Continue completions from an inner finally context
4699 // with a jump target that is not beyond the next outer finally context:
4700 //
4701 // try {
4702 // for (... stuff ...) {
4703 // try {
4704 // continue; // Sets completionType to jumpID of top of the for loop.
4705 // } finally {
4706 // } // Jump to top of the for loop on completion.
4707 // }
4708 // } finally {
4709 // }
4710 //
4711 // Since the jumpID is targetting a label that is inside the outer finally context,
4712 // we can jump to it directly on completion of this finally context: there is no intermediate
4713 // finally blocks to run. After the Break / Continue, we will contnue execution as normal.
4714 // So, we'll set the completionType to Normal (on behalf of the target) before we jump.
4715 // We can also set the completion value to undefined, but it will never be used for normal
4716 // completion anyway. So, we'll skip setting it.
4717
4718 restoreScopeRegister(jump.targetLexicalScopeIndex);
4719 emitLoad(context.completionTypeRegister(), CompletionType::Normal);
4720 emitJump(jump.targetLabel.get());
4721
4722 emitLabel(nextLabel.get());
4723 }
4724
4725 // Handle completions that take us out of this FinallyContext.
4726 if (outerContext) {
4727 if (context.handlesReturns()) {
4728 Ref<Label> isNotReturnLabel = newLabel();
4729 emitJumpIf<OpNstricteq>(context.completionTypeRegister(), CompletionType::Return, isNotReturnLabel.get());
4730
4731 // This case is for Return completion from an inner finally context:
4732 //
4733 // try {
4734 // try {
4735 // return result; // Sets completionType to Return, and completionValue to result.
4736 // } finally {
4737 // } // Jump to outer finally on completion.
4738 // } finally {
4739 // }
4740 //
4741 // Since we know there's at least one outer finally context (beyond the current context),
4742 // we cannot actually return from here. Instead, we pass the completionType and completionValue
4743 // on to the next outer finally, and let it decide what to do next on its completion. The
4744 // outer finally may or may not actual return depending on whether it encounters an abrupt
4745 // completion in its body that overrrides this Return completion.
4746
4747 move(outerContext->completionTypeRegister(), context.completionTypeRegister());
4748 move(outerContext->completionValueRegister(), context.completionValueRegister());
4749 emitJump(*outerContext->finallyLabel());
4750
4751 emitLabel(isNotReturnLabel.get());
4752 }
4753
4754 bool hasBreaksOrContinuesThatEscapeCurrentFinally = context.numberOfBreaksOrContinues() > numberOfJumps;
4755 if (hasBreaksOrContinuesThatEscapeCurrentFinally) {
4756 Ref<Label> isThrowOrNormalLabel = newLabel();
4757 emitJumpIf<OpBeloweq>(context.completionTypeRegister(), CompletionType::Throw, isThrowOrNormalLabel.get());
4758
4759 // A completionType above Throw means we have a Break or Continue encoded as a jumpID.
4760 // We already ruled out Return above.
4761 static_assert(CompletionType::Throw < CompletionType::Return && CompletionType::Throw < CompletionType::Return, "jumpIDs are above CompletionType::Return");
4762
4763 // This case is for Break / Continue completions in an inner finally context:
4764 //
4765 // 10: label:
4766 // 11: try {
4767 // 12: try {
4768 // 13: for (... stuff ...)
4769 // 14: break label; // Sets completionType to jumpID of label.
4770 // 15: } finally {
4771 // 16: } // Jumps to outer finally on completion.
4772 // 17: } finally {
4773 // 18: }
4774 //
4775 // The break (line 14) says to continue execution at the label at line 10. Before we can
4776 // goto line 10, the inner context's finally (line 15) needs to be run, followed by the
4777 // outer context's finally (line 17). 'outerContext' being non-null above tells us that
4778 // there is at least one outer finally context that we need to run after we complete the
4779 // current finally. Note that unless the body of the outer finally abruptly completes in a
4780 // different way, that outer finally also needs to complete with a Break / Continue to
4781 // the same target label. Hence, we need to pass the jumpID in this finally's completionTypeRegister
4782 // to the outer finally. The completion value for Break and Continue according to the spec
4783 // is undefined, but it won't ever be used. So, we'll skip setting it.
4784 //
4785 // Note that all we're doing here is passing the Break / Continue completion to the next
4786 // outer finally context. We don't worry about finally contexts beyond that. It is the
4787 // responsibility of the next outer finally to determine what to do next at its completion,
4788 // and pass on to the next outer context if present and needed.
4789
4790 move(outerContext->completionTypeRegister(), context.completionTypeRegister());
4791 emitJump(*outerContext->finallyLabel());
4792
4793 emitLabel(isThrowOrNormalLabel.get());
4794 }
4795
4796 } else {
4797 // We are the outermost finally.
4798 if (context.handlesReturns()) {
4799 Ref<Label> notReturnLabel = newLabel();
4800 emitJumpIf<OpNstricteq>(context.completionTypeRegister(), CompletionType::Return, notReturnLabel.get());
4801
4802 // This case is for Return completion from the outermost finally context:
4803 //
4804 // try {
4805 // return result; // Sets completionType to Return, and completionValue to result.
4806 // } finally {
4807 // } // Executes the return of the completionValue.
4808 //
4809 // Since we know there's no outer finally context (beyond the current context) to run,
4810 // we can actually execute a return for this Return completion. The value to return
4811 // is whatever is in the completionValueRegister.
4812
4813 emitWillLeaveCallFrameDebugHook();
4814 emitReturn(context.completionValueRegister(), ReturnFrom::Finally);
4815
4816 emitLabel(notReturnLabel.get());
4817 }
4818 }
4819 }
4820
4821 // By now, we've rule out all Break / Continue / Return completions above. The only remaining
4822 // possibilities are Normal or Throw.
4823
4824 emitJumpIf<OpNstricteq>(context.completionTypeRegister(), CompletionType::Throw, normalCompletionLabel);
4825
4826 // We get here because we entered this finally context with Throw completionType (i.e. we have
4827 // an exception that we need to rethrow), and we didn't encounter a different abrupt completion
4828 // that overrides that incoming completionType. All we have to do here is re-throw the exception
4829 // captured in the completionValue.
4830 //
4831 // Note that unlike for Break / Continue / Return, we don't need to worry about outer finally
4832 // contexts. This is because any outer finally context (if present) will have its own exception
4833 // handler, which will take care of receiving the Throw completion, and re-capturing the exception
4834 // in its completionValue.
4835
4836 emitThrow(context.completionValueRegister());
4837}
4838
4839template<typename CompareOp>
4840void BytecodeGenerator::emitJumpIf(RegisterID* completionTypeRegister, CompletionType type, Label& jumpTarget)
4841{
4842 RefPtr<RegisterID> tempRegister = newTemporary();
4843 RegisterID* valueConstant = addConstantValue(jsNumber(static_cast<int>(type)));
4844 OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType());
4845
4846 auto equivalenceResult = emitBinaryOp<CompareOp>(tempRegister.get(), completionTypeRegister, valueConstant, operandTypes);
4847 emitJumpIfTrue(equivalenceResult, jumpTarget);
4848}
4849
4850void BytecodeGenerator::pushOptionalChainTarget()
4851{
4852 m_optionalChainTargetStack.append(newLabel());
4853}
4854
4855void BytecodeGenerator::popOptionalChainTarget()
4856{
4857 ASSERT(m_optionalChainTargetStack.size());
4858 emitLabel(m_optionalChainTargetStack.takeLast().get());
4859}
4860
4861void BytecodeGenerator::popOptionalChainTarget(RegisterID* dst, bool isDelete)
4862{
4863 Ref<Label> endLabel = newLabel();
4864 emitJump(endLabel.get());
4865
4866 popOptionalChainTarget();
4867 emitLoad(dst, isDelete ? jsBoolean(true) : jsUndefined());
4868
4869 emitLabel(endLabel.get());
4870}
4871
4872void BytecodeGenerator::emitOptionalCheck(RegisterID* src)
4873{
4874 ASSERT(m_optionalChainTargetStack.size());
4875 emitJumpIfTrue(emitIsUndefinedOrNull(newTemporary(), src), m_optionalChainTargetStack.last().get());
4876}
4877
4878void ForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
4879{
4880 // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if
4881 // either of the following conditions is true:
4882 //
4883 // (1) The loop iteration variable is re-assigned within the body of the loop.
4884 // (2) The loop iteration variable is captured in the lexical scope of the function.
4885 //
4886 // These two situations occur sufficiently rarely that it's okay to use this style of
4887 // "analysis" to make iteration faster. If we didn't want to do this, we would either have
4888 // to perform some flow-sensitive analysis to see if/when the loop iteration variable was
4889 // reassigned, or we'd have to resort to runtime checks to see if the variable had been
4890 // reassigned from its original value.
4891
4892 for (unsigned offset = bodyBytecodeStartOffset(); isValid() && offset < bodyBytecodeEndOffset;) {
4893 auto instruction = generator.instructions().at(offset);
4894 OpcodeID opcodeID = instruction->opcodeID();
4895
4896 ASSERT(opcodeID != op_enter);
4897 computeDefsForBytecodeIndex(codeBlock, opcodeID, instruction.ptr(), [&] (VirtualRegister operand) {
4898 if (local()->virtualRegister() == operand)
4899 invalidate();
4900 });
4901 offset += instruction->size();
4902 }
4903}
4904
4905void StructureForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
4906{
4907 Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
4908 if (isValid())
4909 return;
4910
4911 OpcodeID lastOpcodeID = generator.m_lastOpcodeID;
4912 InstructionStream::MutableRef lastInstruction = generator.m_lastInstruction;
4913 for (const auto& instTuple : m_getInsts) {
4914 unsigned instIndex = std::get<0>(instTuple);
4915 int propertyRegIndex = std::get<1>(instTuple);
4916 auto instruction = generator.m_writer.ref(instIndex);
4917 auto end = instIndex + instruction->size();
4918 ASSERT(instruction->isWide32());
4919
4920 generator.m_writer.seek(instIndex);
4921
4922 auto bytecode = instruction->as<OpGetDirectPname>();
4923
4924 // disable peephole optimizations
4925 generator.m_lastOpcodeID = op_end;
4926
4927 // Change the opcode to get_by_val.
4928 // 1. dst stays the same.
4929 // 2. base stays the same.
4930 // 3. property gets switched to the original property.
4931 OpGetByVal::emit<OpcodeSize::Wide32>(&generator, bytecode.m_dst, bytecode.m_base, VirtualRegister(propertyRegIndex));
4932
4933 // 4. nop out the remaining bytes
4934 while (generator.m_writer.position() < end)
4935 OpNop::emit<OpcodeSize::Narrow>(&generator);
4936 }
4937 generator.m_writer.seek(generator.m_writer.size());
4938 if (generator.m_lastInstruction.offset() + generator.m_lastInstruction->size() != generator.m_writer.size()) {
4939 generator.m_lastOpcodeID = lastOpcodeID;
4940 generator.m_lastInstruction = lastInstruction;
4941 }
4942}
4943
4944void IndexedForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset)
4945{
4946 Base::finalize(generator, codeBlock, bodyBytecodeEndOffset);
4947 if (isValid())
4948 return;
4949
4950 for (const auto& instPair : m_getInsts) {
4951 unsigned instIndex = instPair.first;
4952 int propertyRegIndex = instPair.second;
4953 generator.m_writer.ref(instIndex)->cast<OpGetByVal>()->setProperty(VirtualRegister(propertyRegIndex), []() {
4954 ASSERT_NOT_REACHED();
4955 return VirtualRegister();
4956 });
4957 }
4958}
4959
4960void StaticPropertyAnalysis::record()
4961{
4962 auto* instruction = m_instructionRef.ptr();
4963 auto size = m_propertyIndexes.size();
4964 switch (instruction->opcodeID()) {
4965 case OpNewObject::opcodeID:
4966 instruction->cast<OpNewObject>()->setInlineCapacity(size, []() {
4967 return 255;
4968 });
4969 return;
4970 case OpCreateThis::opcodeID:
4971 instruction->cast<OpCreateThis>()->setInlineCapacity(size, []() {
4972 return 255;
4973 });
4974 return;
4975 default:
4976 ASSERT_NOT_REACHED();
4977 }
4978}
4979
4980void BytecodeGenerator::emitToThis()
4981{
4982 OpToThis::emit(this, kill(&m_thisRegister));
4983}
4984
4985} // namespace JSC
4986
4987namespace WTF {
4988
4989void printInternal(PrintStream& out, JSC::Variable::VariableKind kind)
4990{
4991 switch (kind) {
4992 case JSC::Variable::NormalVariable:
4993 out.print("Normal");
4994 return;
4995 case JSC::Variable::SpecialVariable:
4996 out.print("Special");
4997 return;
4998 }
4999 RELEASE_ASSERT_NOT_REACHED();
5000}
5001
5002} // namespace WTF
5003
5004