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#pragma once
32
33#include "BytecodeGeneratorBase.h"
34#include "BytecodeStructs.h"
35#include "CodeBlock.h"
36#include "Instruction.h"
37#include "Interpreter.h"
38#include "JSAsyncGenerator.h"
39#include "JSBigInt.h"
40#include "JSGenerator.h"
41#include "JSTemplateObjectDescriptor.h"
42#include "Label.h"
43#include "LabelScope.h"
44#include "Nodes.h"
45#include "ParserError.h"
46#include "ProfileTypeBytecodeFlag.h"
47#include "RegisterID.h"
48#include "StaticPropertyAnalyzer.h"
49#include "SymbolTable.h"
50#include "UnlinkedCodeBlock.h"
51#include <functional>
52#include <wtf/CheckedArithmetic.h>
53#include <wtf/HashFunctions.h>
54#include <wtf/Optional.h>
55#include <wtf/SegmentedVector.h>
56#include <wtf/SetForScope.h>
57#include <wtf/Vector.h>
58
59namespace JSC {
60
61 class JSImmutableButterfly;
62 class Identifier;
63 class IndexedForInContext;
64 class StructureForInContext;
65
66 enum ExpectedFunction {
67 NoExpectedFunction,
68 ExpectObjectConstructor,
69 ExpectArrayConstructor
70 };
71
72 enum class EmitAwait { Yes, No };
73
74 enum class DebuggableCall { Yes, No };
75 enum class ThisResolutionType { Local, Scoped };
76 enum class LinkTimeConstant : int32_t;
77
78 class CallArguments {
79 public:
80 CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
81
82 RegisterID* thisRegister() { return m_argv[0].get(); }
83 RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
84 unsigned stackOffset() { return -m_argv[0]->index() + CallFrame::headerSizeInRegisters; }
85 unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
86 ArgumentsNode* argumentsNode() { return m_argumentsNode; }
87
88 private:
89 ArgumentsNode* m_argumentsNode;
90 Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
91 unsigned m_padding;
92 };
93
94 // https://tc39.github.io/ecma262/#sec-completion-record-specification-type
95 //
96 // For the Break and Continue cases, instead of using the Break and Continue enum values
97 // below, we use the unique jumpID of the break and continue statement as the encoding
98 // for the CompletionType value. emitFinallyCompletion() uses this jumpID value later
99 // to determine the appropriate jump target to jump to after executing the relevant finally
100 // blocks. The jumpID is computed as:
101 // jumpID = bytecodeOffset (of the break/continue node) + CompletionType::NumberOfTypes.
102 // Hence, there won't be any collision between jumpIDs and CompletionType enums.
103 enum class CompletionType : int {
104 Normal,
105 Throw,
106 Return,
107 NumberOfTypes
108 };
109
110 inline CompletionType bytecodeOffsetToJumpID(unsigned offset)
111 {
112 int jumpIDAsInt = offset + static_cast<int>(CompletionType::NumberOfTypes);
113 ASSERT(jumpIDAsInt >= static_cast<int>(CompletionType::NumberOfTypes));
114 return static_cast<CompletionType>(jumpIDAsInt);
115 }
116
117 struct FinallyJump {
118 FinallyJump(CompletionType jumpID, int targetLexicalScopeIndex, Label& targetLabel)
119 : jumpID(jumpID)
120 , targetLexicalScopeIndex(targetLexicalScopeIndex)
121 , targetLabel(targetLabel)
122 { }
123
124 CompletionType jumpID;
125 int targetLexicalScopeIndex;
126 Ref<Label> targetLabel;
127 };
128
129 class FinallyContext {
130 public:
131 FinallyContext() { }
132 FinallyContext(BytecodeGenerator&, Label& finallyLabel);
133
134 FinallyContext* outerContext() const { return m_outerContext; }
135 Label* finallyLabel() const { return m_finallyLabel; }
136
137 RegisterID* completionTypeRegister() const { return m_completionRecord.typeRegister.get(); }
138 RegisterID* completionValueRegister() const { return m_completionRecord.valueRegister.get(); }
139
140 uint32_t numberOfBreaksOrContinues() const { return m_numberOfBreaksOrContinues.unsafeGet(); }
141 void incNumberOfBreaksOrContinues() { m_numberOfBreaksOrContinues++; }
142
143 bool handlesReturns() const { return m_handlesReturns; }
144 void setHandlesReturns() { m_handlesReturns = true; }
145
146 void registerJump(CompletionType jumpID, int lexicalScopeIndex, Label& targetLabel)
147 {
148 m_jumps.append(FinallyJump(jumpID, lexicalScopeIndex, targetLabel));
149 }
150
151 size_t numberOfJumps() const { return m_jumps.size(); }
152 FinallyJump& jumps(size_t i) { return m_jumps[i]; }
153
154 private:
155 FinallyContext* m_outerContext { nullptr };
156 Label* m_finallyLabel { nullptr };
157 Checked<uint32_t, WTF::CrashOnOverflow> m_numberOfBreaksOrContinues;
158 bool m_handlesReturns { false };
159 Vector<FinallyJump> m_jumps;
160 struct {
161 RefPtr<RegisterID> typeRegister;
162 RefPtr<RegisterID> valueRegister;
163 } m_completionRecord;
164 };
165
166 struct ControlFlowScope {
167 typedef uint8_t Type;
168 enum {
169 Label,
170 Finally
171 };
172 ControlFlowScope(Type type, int lexicalScopeIndex, FinallyContext* finallyContext = nullptr)
173 : type(type)
174 , lexicalScopeIndex(lexicalScopeIndex)
175 , finallyContext(finallyContext)
176 { }
177
178 bool isLabelScope() const { return type == Label; }
179 bool isFinallyScope() const { return type == Finally; }
180
181 Type type;
182 int lexicalScopeIndex;
183 FinallyContext* finallyContext;
184 };
185
186 class ForInContext : public RefCounted<ForInContext> {
187 WTF_MAKE_FAST_ALLOCATED;
188 WTF_MAKE_NONCOPYABLE(ForInContext);
189 public:
190 virtual ~ForInContext() = default;
191
192 bool isValid() const { return m_isValid; }
193 void invalidate() { m_isValid = false; }
194
195 enum class Type : uint8_t {
196 IndexedForIn,
197 StructureForIn
198 };
199
200 Type type() const { return m_type; }
201 bool isIndexedForInContext() const { return m_type == Type::IndexedForIn; }
202 bool isStructureForInContext() const { return m_type == Type::StructureForIn; }
203
204 IndexedForInContext& asIndexedForInContext()
205 {
206 ASSERT(isIndexedForInContext());
207 return *reinterpret_cast<IndexedForInContext*>(this);
208 }
209
210 StructureForInContext& asStructureForInContext()
211 {
212 ASSERT(isStructureForInContext());
213 return *reinterpret_cast<StructureForInContext*>(this);
214 }
215
216 RegisterID* local() const { return m_localRegister.get(); }
217
218 protected:
219 ForInContext(RegisterID* localRegister, Type type, unsigned bodyBytecodeStartOffset)
220 : m_localRegister(localRegister)
221 , m_type(type)
222 , m_bodyBytecodeStartOffset(bodyBytecodeStartOffset)
223 { }
224
225 unsigned bodyBytecodeStartOffset() const { return m_bodyBytecodeStartOffset; }
226
227 void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset);
228
229 private:
230 RefPtr<RegisterID> m_localRegister;
231 bool m_isValid { true };
232 Type m_type;
233 unsigned m_bodyBytecodeStartOffset;
234 };
235
236 class StructureForInContext : public ForInContext {
237 using Base = ForInContext;
238 public:
239 using GetInst = std::tuple<unsigned, int>;
240
241 StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister, unsigned bodyBytecodeStartOffset)
242 : ForInContext(localRegister, Type::StructureForIn, bodyBytecodeStartOffset)
243 , m_indexRegister(indexRegister)
244 , m_propertyRegister(propertyRegister)
245 , m_enumeratorRegister(enumeratorRegister)
246 {
247 }
248
249 RegisterID* index() const { return m_indexRegister.get(); }
250 RegisterID* property() const { return m_propertyRegister.get(); }
251 RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
252
253 void addGetInst(unsigned instIndex, int propertyRegIndex)
254 {
255 m_getInsts.append(GetInst { instIndex, propertyRegIndex });
256 }
257
258 void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset);
259
260 private:
261 RefPtr<RegisterID> m_indexRegister;
262 RefPtr<RegisterID> m_propertyRegister;
263 RefPtr<RegisterID> m_enumeratorRegister;
264 Vector<GetInst> m_getInsts;
265 };
266
267 class IndexedForInContext : public ForInContext {
268 using Base = ForInContext;
269 public:
270 IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister, unsigned bodyBytecodeStartOffset)
271 : ForInContext(localRegister, Type::IndexedForIn, bodyBytecodeStartOffset)
272 , m_indexRegister(indexRegister)
273 {
274 }
275
276 RegisterID* index() const { return m_indexRegister.get(); }
277
278 void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset);
279 void addGetInst(unsigned instIndex, int propertyIndex) { m_getInsts.append({ instIndex, propertyIndex }); }
280
281 private:
282 RefPtr<RegisterID> m_indexRegister;
283 Vector<std::pair<unsigned, int>> m_getInsts;
284 };
285
286 struct TryData {
287 Ref<Label> target;
288 HandlerType handlerType;
289 };
290
291 struct TryContext {
292 Ref<Label> start;
293 TryData* tryData;
294 };
295
296 class Variable {
297 public:
298 enum VariableKind { NormalVariable, SpecialVariable };
299
300 Variable()
301 : m_offset()
302 , m_local(nullptr)
303 , m_attributes(0)
304 , m_kind(NormalVariable)
305 , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
306 , m_isLexicallyScoped(false)
307 {
308 }
309
310 Variable(const Identifier& ident)
311 : m_ident(ident)
312 , m_local(nullptr)
313 , m_attributes(0)
314 , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable.
315 , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
316 , m_isLexicallyScoped(false)
317 {
318 }
319
320 Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind, int symbolTableConstantIndex, bool isLexicallyScoped)
321 : m_ident(ident)
322 , m_offset(offset)
323 , m_local(local)
324 , m_attributes(attributes)
325 , m_kind(kind)
326 , m_symbolTableConstantIndex(symbolTableConstantIndex)
327 , m_isLexicallyScoped(isLexicallyScoped)
328 {
329 }
330
331 // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be
332 // a stack variable, a scoped variable in a local scope, or a variable captured in the
333 // direct arguments object.
334 bool isResolved() const { return !!m_offset; }
335 int symbolTableConstantIndex() const { ASSERT(isResolved() && !isSpecial()); return m_symbolTableConstantIndex; }
336
337 const Identifier& ident() const { return m_ident; }
338
339 VarOffset offset() const { return m_offset; }
340 bool isLocal() const { return m_offset.isStack(); }
341 RegisterID* local() const { return m_local; }
342
343 bool isReadOnly() const { return m_attributes & PropertyAttribute::ReadOnly; }
344 bool isSpecial() const { return m_kind != NormalVariable; }
345 bool isConst() const { return isReadOnly() && m_isLexicallyScoped; }
346 void setIsReadOnly() { m_attributes |= PropertyAttribute::ReadOnly; }
347
348 void dump(PrintStream&) const;
349
350 private:
351 Identifier m_ident;
352 VarOffset m_offset;
353 RegisterID* m_local;
354 unsigned m_attributes;
355 VariableKind m_kind;
356 int m_symbolTableConstantIndex;
357 bool m_isLexicallyScoped;
358 };
359
360 struct TryRange {
361 Ref<Label> start;
362 Ref<Label> end;
363 TryData* tryData;
364 };
365
366
367 struct JSGeneratorTraits {
368 using OpcodeTraits = JSOpcodeTraits;
369 using OpcodeID = ::JSC::OpcodeID;
370 using OpNop = ::JSC::OpNop;
371 using CodeBlock = Strong<UnlinkedCodeBlock>;
372 static constexpr OpcodeID opcodeForDisablingOptimizations = op_end;
373 };
374
375 class BytecodeGenerator : public BytecodeGeneratorBase<JSGeneratorTraits> {
376 WTF_MAKE_FAST_ALLOCATED;
377 WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
378
379 friend class FinallyContext;
380 friend class IndexedForInContext;
381 friend class StructureForInContext;
382 public:
383 typedef DeclarationStacks::FunctionStack FunctionStack;
384
385 BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*);
386 BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*);
387 BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*);
388 BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*);
389
390 ~BytecodeGenerator();
391
392 VM& vm() const { return m_vm; }
393 ParserArena& parserArena() const { return m_scopeNode->parserArena(); }
394 const CommonIdentifiers& propertyNames() const { return *m_vm.propertyNames; }
395
396 bool isConstructor() const { return m_codeBlock->isConstructor(); }
397 DerivedContextType derivedContextType() const { return m_derivedContextType; }
398 bool usesArrowFunction() const { return m_scopeNode->usesArrowFunction(); }
399 bool needsToUpdateArrowFunctionContext() const { return m_needsToUpdateArrowFunctionContext; }
400 bool usesEval() const { return m_scopeNode->usesEval(); }
401 bool usesThis() const { return m_scopeNode->usesThis(); }
402 ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
403 SuperBinding superBinding() const { return m_codeBlock->superBinding(); }
404 JSParserScriptMode scriptMode() const { return m_codeBlock->scriptMode(); }
405
406 template<typename Node, typename UnlinkedCodeBlock>
407 static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* environment)
408 {
409 MonotonicTime before;
410 if (UNLIKELY(Options::reportBytecodeCompileTimes()))
411 before = MonotonicTime::now();
412
413 DeferGC deferGC(vm.heap);
414 auto bytecodeGenerator = makeUnique<BytecodeGenerator>(vm, node, unlinkedCodeBlock, codeGenerationMode, environment);
415 auto result = bytecodeGenerator->generate();
416
417 if (UNLIKELY(Options::reportBytecodeCompileTimes())) {
418 MonotonicTime after = MonotonicTime::now();
419 dataLogLn(result.isValid() ? "Failed to compile #" : "Compiled #", CodeBlockHash(sourceCode, unlinkedCodeBlock->isConstructor() ? CodeForConstruct : CodeForCall), " into bytecode ", bytecodeGenerator->instructions().size(), " instructions in ", (after - before).milliseconds(), " ms.");
420 }
421 return result;
422 }
423
424 bool isArgumentNumber(const Identifier&, int);
425
426 Variable variable(const Identifier&, ThisResolutionType = ThisResolutionType::Local);
427
428 enum ExistingVariableMode { VerifyExisting, IgnoreExisting };
429 void createVariable(const Identifier&, VarKind, SymbolTable*, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible.
430
431 // Returns the register storing "this"
432 RegisterID* thisRegister() { return &m_thisRegister; }
433 RegisterID* argumentsRegister() { return m_argumentsRegister; }
434 RegisterID* newTarget()
435 {
436 ASSERT(m_newTargetRegister);
437 return m_newTargetRegister;
438 }
439
440 RegisterID* scopeRegister() { return m_scopeRegister; }
441
442 RegisterID* generatorRegister() { return m_generatorRegister; }
443
444 RegisterID* promiseRegister() { return m_promiseRegister; }
445
446 // The same as newTemporary(), but this function returns "suggestion" if
447 // "suggestion" is a temporary. This function is helpful in situations
448 // where you've put "suggestion" in a RefPtr, but you'd like to allow
449 // the next instruction to overwrite it anyway.
450 RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
451
452 // Functions for handling of dst register
453
454 RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
455
456 // This will be allocated in the temporary region of registers, but it will
457 // not be marked as a temporary. This will ensure that finalDestination() does
458 // not overwrite a block scope variable that it mistakes as a temporary. These
459 // registers can be (and are) reclaimed when the lexical scope they belong to
460 // is no longer on the symbol table stack.
461 RegisterID* newBlockScopeVariable();
462
463 // Returns a place to write intermediate values of an operation
464 // which reuses dst if it is safe to do so.
465 RegisterID* tempDestination(RegisterID* dst)
466 {
467 return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
468 }
469
470 // Returns the place to write the final output of an operation.
471 RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
472 {
473 if (originalDst && originalDst != ignoredResult())
474 return originalDst;
475 ASSERT(tempDst != ignoredResult());
476 if (tempDst && tempDst->isTemporary())
477 return tempDst;
478 return newTemporary();
479 }
480
481 RegisterID* destinationForAssignResult(RegisterID* dst)
482 {
483 if (dst && dst != ignoredResult())
484 return dst->isTemporary() ? dst : newTemporary();
485 return 0;
486 }
487
488 // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
489 RegisterID* move(RegisterID* dst, RegisterID* src)
490 {
491 return dst == ignoredResult() ? nullptr : (dst && dst != src) ? emitMove(dst, src) : src;
492 }
493
494 Ref<LabelScope> newLabelScope(LabelScope::Type, const Identifier* = 0);
495
496 void emitNode(RegisterID* dst, StatementNode* n)
497 {
498 SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
499 return emitNodeInTailPosition(dst, n);
500 }
501
502 void emitNodeInTailPosition(RegisterID* dst, StatementNode* n)
503 {
504 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
505 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
506 if (UNLIKELY(!m_vm.isSafeToRecurse())) {
507 emitThrowExpressionTooDeepException();
508 return;
509 }
510 if (UNLIKELY(n->needsDebugHook()))
511 emitDebugHook(n);
512 n->emitBytecode(*this, dst);
513 }
514
515 ALWAYS_INLINE unsigned addMetadataFor(OpcodeID opcodeID)
516 {
517 return m_codeBlock->metadata().addEntry(opcodeID);
518 }
519
520 void emitNode(StatementNode* n)
521 {
522 emitNode(nullptr, n);
523 }
524
525 void emitNodeInTailPosition(StatementNode* n)
526 {
527 emitNodeInTailPosition(nullptr, n);
528 }
529
530 RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
531 {
532 SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
533 return emitNodeInTailPosition(dst, n);
534 }
535
536 RegisterID* emitNodeInTailPosition(RegisterID* dst, ExpressionNode* n)
537 {
538 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
539 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
540 if (UNLIKELY(!m_vm.isSafeToRecurse()))
541 return emitThrowExpressionTooDeepException();
542 if (UNLIKELY(n->needsDebugHook()))
543 emitDebugHook(n);
544 return n->emitBytecode(*this, dst);
545 }
546
547 RegisterID* emitNode(ExpressionNode* n)
548 {
549 return emitNode(nullptr, n);
550 }
551
552 RegisterID* emitNodeInTailPosition(ExpressionNode* n)
553 {
554 return emitNodeInTailPosition(nullptr, n);
555 }
556
557 RegisterID* emitDefineClassElements(PropertyListNode* n, RegisterID* constructor, RegisterID* prototype)
558 {
559 ASSERT(constructor->refCount() && prototype->refCount());
560 if (UNLIKELY(!m_vm.isSafeToRecurse()))
561 return emitThrowExpressionTooDeepException();
562 if (UNLIKELY(n->needsDebugHook()))
563 emitDebugHook(n);
564 return n->emitBytecode(*this, constructor, prototype);
565 }
566
567 RegisterID* emitNodeForProperty(RegisterID* dst, ExpressionNode* node)
568 {
569 if (node->isString()) {
570 if (Optional<uint32_t> index = parseIndex(static_cast<StringNode*>(node)->value()))
571 return emitLoad(dst, jsNumber(index.value()));
572 }
573 return emitNode(dst, node);
574 }
575
576 RegisterID* emitNodeForProperty(ExpressionNode* n)
577 {
578 return emitNodeForProperty(nullptr, n);
579 }
580
581 void emitNodeInConditionContext(ExpressionNode* n, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
582 {
583 if (UNLIKELY(!m_vm.isSafeToRecurse())) {
584 emitThrowExpressionTooDeepException();
585 return;
586 }
587 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
588 }
589
590 void emitExpressionInfo(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
591 {
592 ASSERT(divot.offset >= divotStart.offset);
593 ASSERT(divotEnd.offset >= divot.offset);
594
595 int sourceOffset = m_scopeNode->source().startOffset();
596 unsigned firstLine = m_scopeNode->source().firstLine().oneBasedInt();
597
598 int divotOffset = divot.offset - sourceOffset;
599 int startOffset = divot.offset - divotStart.offset;
600 int endOffset = divotEnd.offset - divot.offset;
601
602 unsigned line = divot.line;
603 ASSERT(line >= firstLine);
604 line -= firstLine;
605
606 int lineStart = divot.lineStartOffset;
607 if (lineStart > sourceOffset)
608 lineStart -= sourceOffset;
609 else
610 lineStart = 0;
611
612 if (divotOffset < lineStart)
613 return;
614
615 unsigned column = divotOffset - lineStart;
616
617 unsigned instructionOffset = instructions().size();
618 if (!m_isBuiltinFunction)
619 m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
620 }
621
622
623 ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
624 {
625 return (m_codeType != FunctionCode || rightHasAssignments) && !rightIsPure;
626 }
627
628 ALWAYS_INLINE RefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
629 {
630 if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
631 RefPtr<RegisterID> dst = newTemporary();
632 emitNode(dst.get(), n);
633 return dst;
634 }
635
636 return emitNode(n);
637 }
638
639 ALWAYS_INLINE RefPtr<RegisterID> emitNodeForLeftHandSideForProperty(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
640 {
641 if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
642 RefPtr<RegisterID> dst = newTemporary();
643 emitNodeForProperty(dst.get(), n);
644 return dst;
645 }
646
647 return emitNodeForProperty(n);
648 }
649
650 void hoistSloppyModeFunctionIfNecessary(const Identifier& functionName);
651
652 private:
653 void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
654 public:
655
656 // This doesn't emit expression info. If using this, make sure you shouldn't be emitting text offset.
657 void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag);
658 // These variables are associated with variables in a program. They could be Locals, LocalClosureVar, or ClosureVar.
659 void emitProfileType(RegisterID* registerToProfile, const Variable&, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
660
661 void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
662 // These are not associated with variables and don't have a global id.
663 void emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
664
665 void emitProfileControlFlow(int);
666
667 RegisterID* emitLoadArrowFunctionLexicalEnvironment(const Identifier&);
668 RegisterID* ensureThis();
669 void emitLoadThisFromArrowFunctionLexicalEnvironment();
670 RegisterID* emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
671
672 unsigned addConstantIndex();
673 RegisterID* emitLoad(RegisterID* dst, bool);
674 RegisterID* emitLoad(RegisterID* dst, const Identifier&);
675 RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
676 RegisterID* emitLoad(RegisterID* dst, IdentifierSet& excludedList);
677
678 template<typename UnaryOp, typename = std::enable_if_t<UnaryOp::opcodeID != op_negate>>
679 RegisterID* emitUnaryOp(RegisterID* dst, RegisterID* src)
680 {
681 UnaryOp::emit(this, dst, src);
682 return dst;
683 }
684
685 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src, ResultType);
686
687 template<typename BinaryOp>
688 std::enable_if_t<
689 BinaryOp::opcodeID != op_add
690 && BinaryOp::opcodeID != op_mul
691 && BinaryOp::opcodeID != op_sub
692 && BinaryOp::opcodeID != op_div,
693 RegisterID*>
694 emitBinaryOp(RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes)
695 {
696 BinaryOp::emit(this, dst, src1, src2);
697 return dst;
698 }
699
700 template<typename BinaryOp>
701 std::enable_if_t<
702 BinaryOp::opcodeID == op_add
703 || BinaryOp::opcodeID == op_mul
704 || BinaryOp::opcodeID == op_sub
705 || BinaryOp::opcodeID == op_div,
706 RegisterID*>
707 emitBinaryOp(RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
708 {
709 BinaryOp::emit(this, dst, src1, src2, types);
710 return dst;
711 }
712
713 RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
714
715 template<typename EqOp>
716 RegisterID* emitEqualityOp(RegisterID* dst, RegisterID* src1, RegisterID* src2)
717 {
718 if (!emitEqualityOpImpl(dst, src1, src2))
719 EqOp::emit(this, dst, src1, src2);
720 return dst;
721 }
722
723 bool emitEqualityOpImpl(RegisterID* dst, RegisterID* src1, RegisterID* src2);
724
725 RegisterID* emitCreateThis(RegisterID* dst);
726 RegisterID* emitCreatePromise(RegisterID* dst, RegisterID* newTarget, bool isInternalPromise);
727 RegisterID* emitCreateGenerator(RegisterID* dst, RegisterID* newTarget);
728 RegisterID* emitCreateAsyncGenerator(RegisterID* dst, RegisterID* newTarget);
729 void emitTDZCheck(RegisterID* target);
730 bool needsTDZCheck(const Variable&);
731 void emitTDZCheckIfNecessary(const Variable&, RegisterID* target, RegisterID* scope);
732 void liftTDZCheckIfPossible(const Variable&);
733 RegisterID* emitNewObject(RegisterID* dst);
734 RegisterID* emitNewPromise(RegisterID* dst, bool isInternalPromise);
735 RegisterID* emitNewGenerator(RegisterID* dst);
736 RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length, IndexingType recommendedIndexingType); // stops at first elision
737 RegisterID* emitNewArrayBuffer(RegisterID* dst, JSImmutableButterfly*, IndexingType recommendedIndexingType);
738 // FIXME: new_array_with_spread should use an array allocation profile and take a recommendedIndexingType
739 RegisterID* emitNewArrayWithSpread(RegisterID* dst, ElementNode*);
740 RegisterID* emitNewArrayWithSize(RegisterID* dst, RegisterID* length);
741
742 RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*);
743 RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode*);
744 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource);
745 RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*);
746 RegisterID* emitNewMethodDefinition(RegisterID* dst, MethodDefinitionNode*);
747 RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
748
749 void emitSetFunctionNameIfNeeded(ExpressionNode* valueNode, RegisterID* value, RegisterID* name);
750
751 RegisterID* moveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
752 RegisterID* moveEmptyValue(RegisterID* dst);
753
754 RegisterID* emitToNumber(RegisterID* dst, RegisterID* src);
755 RegisterID* emitToNumeric(RegisterID* dst, RegisterID* src);
756 RegisterID* emitToString(RegisterID* dst, RegisterID* src);
757 RegisterID* emitToObject(RegisterID* dst, RegisterID* src, const Identifier& message);
758 RegisterID* emitInc(RegisterID* srcDst);
759 RegisterID* emitDec(RegisterID* srcDst);
760
761 RegisterID* emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue);
762 RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
763 RegisterID* emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue);
764 RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src);
765 RegisterID* emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base);
766 RegisterID* emitInById(RegisterID* dst, RegisterID* base, const Identifier& property);
767
768 RegisterID* emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
769 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
770 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, RegisterID* thisVal, const Identifier& property);
771 RegisterID* emitDirectGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
772 RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
773 RegisterID* emitPutById(RegisterID* base, RegisterID* thisValue, const Identifier& property, RegisterID* value);
774 RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);
775 RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
776 RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
777 RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* thisValue, RegisterID* property);
778 RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
779 RegisterID* emitPutByVal(RegisterID* base, RegisterID* thisValue, RegisterID* property, RegisterID* value);
780 RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
781 RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
782
783 RegisterID* emitGetInternalField(RegisterID* dst, RegisterID* base, unsigned index);
784 RegisterID* emitPutInternalField(RegisterID* base, unsigned index, RegisterID* value);
785
786 void emitSuperSamplerBegin();
787 void emitSuperSamplerEnd();
788
789 RegisterID* emitIdWithProfile(RegisterID* src, SpeculatedType profile);
790 void emitUnreachable();
791
792 void emitPutGetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* getter);
793 void emitPutSetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* setter);
794 void emitPutGetterSetter(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter, RegisterID* setter);
795 void emitPutGetterByVal(RegisterID* base, RegisterID* property, unsigned propertyDescriptorOptions, RegisterID* getter);
796 void emitPutSetterByVal(RegisterID* base, RegisterID* property, unsigned propertyDescriptorOptions, RegisterID* setter);
797
798 RegisterID* emitGetArgument(RegisterID* dst, int32_t index);
799
800 // Initialize object with generator fields (@generatorThis, @generatorNext, @generatorState, @generatorFrame)
801 void emitPutGeneratorFields(RegisterID* nextFunction);
802
803 void emitPutAsyncGeneratorFields(RegisterID* nextFunction);
804
805 ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
806 RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
807 RegisterID* emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
808 RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
809 RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
810 RegisterID* emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
811 RegisterID* emitCallForwardArgumentsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
812
813 enum PropertyDescriptorOption {
814 PropertyConfigurable = 1,
815 PropertyWritable = 1 << 1,
816 PropertyEnumerable = 1 << 2,
817 };
818 void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
819 RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
820
821 void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const ScopedLambda<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
822
823 RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
824 RegisterID* emitGetGlobalPrivate(RegisterID* dst, const Identifier& property);
825
826 enum class ReturnFrom { Normal, Finally };
827 RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal);
828 RegisterID* emitEnd(RegisterID* src);
829
830 RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, RegisterID* lazyThis, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
831 RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
832 void emitToPrimitive(RegisterID* dst, RegisterID* src);
833
834 ResolveType resolveType();
835 RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&);
836 RegisterID* emitResolveScope(RegisterID* dst, const Variable&);
837 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable&, ResolveMode);
838 RegisterID* emitPutToScope(RegisterID* scope, const Variable&, RegisterID* value, ResolveMode, InitializationMode);
839
840 RegisterID* emitResolveScopeForHoistingFuncDeclInEval(RegisterID* dst, const Identifier&);
841
842 RegisterID* initializeVariable(const Variable&, RegisterID* value);
843
844 void emitLoopHint();
845 void emitJump(Label& target);
846 void emitJumpIfTrue(RegisterID* cond, Label& target);
847 void emitJumpIfFalse(RegisterID* cond, Label& target);
848 void emitJumpIfNotFunctionCall(RegisterID* cond, Label& target);
849 void emitJumpIfNotFunctionApply(RegisterID* cond, Label& target);
850
851 template<typename BinOp, typename JmpOp>
852 bool fuseCompareAndJump(RegisterID* cond, Label& target, bool swapOperands = false);
853
854 template<typename UnaryOp, typename JmpOp>
855 bool fuseTestAndJmp(RegisterID* cond, Label& target);
856
857 void emitEnter();
858 void emitCheckTraps();
859
860 RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
861 RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
862 RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
863 RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
864 RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
865 RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
866 RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
867 RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
868 RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
869 RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
870
871 RegisterID* emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType);
872 RegisterID* emitIsGenerator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSGeneratorType); }
873 RegisterID* emitIsAsyncGenerator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSAsyncGeneratorType); }
874 RegisterID* emitIsJSArray(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, ArrayType); }
875 RegisterID* emitIsPromise(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSPromiseType); }
876 RegisterID* emitIsProxyObject(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, ProxyObjectType); }
877 RegisterID* emitIsRegExpObject(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, RegExpObjectType); }
878 RegisterID* emitIsMap(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSMapType); }
879 RegisterID* emitIsSet(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetType); }
880 RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
881 RegisterID* emitIsNumber(RegisterID* dst, RegisterID* src);
882 RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
883 RegisterID* emitIsUndefinedOrNull(RegisterID* dst, RegisterID* src);
884 RegisterID* emitIsEmpty(RegisterID* dst, RegisterID* src);
885 RegisterID* emitIsDerivedArray(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, DerivedArrayType); }
886 void emitRequireObjectCoercible(RegisterID* value, const String& error);
887
888 RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, const ThrowableExpressionData* node, JSC::EmitAwait = JSC::EmitAwait::No);
889 RegisterID* emitIteratorNextWithValue(RegisterID* dst, RegisterID* nextMethod, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node);
890 void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node, EmitAwait = EmitAwait::No);
891
892 RegisterID* emitRestParameter(RegisterID* result, unsigned numParametersToSkip);
893
894 bool emitReadOnlyExceptionIfNeeded(const Variable&);
895
896 // Start a try block. 'start' must have been emitted.
897 TryData* pushTry(Label& start, Label& handlerLabel, HandlerType);
898 // End a try block. 'end' must have been emitted.
899 void popTry(TryData*, Label& end);
900
901 void emitOutOfLineCatchHandler(RegisterID* thrownValueRegister, RegisterID* completionTypeRegister, TryData*);
902 void emitOutOfLineFinallyHandler(RegisterID* exceptionRegister, RegisterID* completionTypeRegister, TryData*);
903
904 private:
905 static constexpr int CurrentLexicalScopeIndex = -2;
906 static constexpr int OutermostLexicalScopeIndex = -1;
907
908 int currentLexicalScopeIndex() const
909 {
910 int size = static_cast<int>(m_lexicalScopeStack.size());
911 ASSERT(static_cast<size_t>(size) == m_lexicalScopeStack.size());
912 ASSERT(size >= 0);
913 if (!size)
914 return OutermostLexicalScopeIndex;
915 return size - 1;
916 }
917
918 void emitOutOfLineExceptionHandler(RegisterID* exceptionRegister, RegisterID* thrownValueRegister, RegisterID* completionTypeRegister, TryData*);
919
920 public:
921 void restoreScopeRegister();
922 void restoreScopeRegister(int lexicalScopeIndex);
923
924 int labelScopeDepthToLexicalScopeIndex(int labelScopeDepth);
925
926 void emitThrow(RegisterID*);
927 RegisterID* emitArgumentCount(RegisterID*);
928
929 void emitThrowStaticError(ErrorType, RegisterID*);
930 void emitThrowStaticError(ErrorType, const Identifier& message);
931 void emitThrowReferenceError(const String& message);
932 void emitThrowTypeError(const String& message);
933 void emitThrowTypeError(const Identifier& message);
934 void emitThrowRangeError(const Identifier& message);
935 void emitThrowOutOfMemoryError();
936
937 void emitPushCatchScope(VariableEnvironment&);
938 void emitPopCatchScope(VariableEnvironment&);
939
940 RegisterID* emitGetIterator(RegisterID*, ThrowableExpressionData*);
941 RegisterID* emitGetAsyncIterator(RegisterID*, ThrowableExpressionData*);
942
943 void emitAwait(RegisterID*);
944 void emitGetScope();
945 RegisterID* emitPushWithScope(RegisterID* objectScope);
946 void emitPopWithScope();
947 void emitPutThisToArrowFunctionContextScope();
948 void emitPutNewTargetToArrowFunctionContextScope();
949 void emitPutDerivedConstructorToArrowFunctionContextScope();
950 RegisterID* emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
951
952 void emitDebugHook(DebugHookType, const JSTextPosition&);
953 void emitDebugHook(DebugHookType, unsigned line, unsigned charOffset, unsigned lineStart);
954 void emitDebugHook(StatementNode*);
955 void emitDebugHook(ExpressionNode*);
956 void emitWillLeaveCallFrameDebugHook();
957
958 void emitLoad(RegisterID* completionTypeRegister, CompletionType type)
959 {
960 emitLoad(completionTypeRegister, JSValue(static_cast<int>(type)));
961 }
962
963 template<typename CompareOp>
964 void emitJumpIf(RegisterID* completionTypeRegister, CompletionType, Label& jumpTarget);
965
966 bool emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label& jumpTarget);
967 bool emitReturnViaFinallyIfNeeded(RegisterID* returnRegister);
968 void emitFinallyCompletion(FinallyContext&, Label& normalCompletionLabel);
969
970 public:
971 void pushFinallyControlFlowScope(FinallyContext&);
972 void popFinallyControlFlowScope();
973
974 void pushOptionalChainTarget();
975 void popOptionalChainTarget();
976 void popOptionalChainTarget(RegisterID* dst, bool isDelete);
977 void emitOptionalCheck(RegisterID* src);
978
979 void pushIndexedForInScope(RegisterID* local, RegisterID* index);
980 void popIndexedForInScope(RegisterID* local);
981 void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
982 void popStructureForInScope(RegisterID* local);
983
984 LabelScope* breakTarget(const Identifier&);
985 LabelScope* continueTarget(const Identifier&);
986
987 void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
988 void endSwitch(uint32_t clauseCount, const Vector<Ref<Label>, 8>&, ExpressionNode**, Label& defaultLabel, int32_t min, int32_t range);
989
990 void emitYieldPoint(RegisterID*, JSAsyncGenerator::AsyncGeneratorSuspendReason);
991
992 void emitGeneratorStateLabel();
993 void emitGeneratorStateChange(int32_t state);
994 RegisterID* emitYield(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason = JSAsyncGenerator::AsyncGeneratorSuspendReason::Yield);
995 RegisterID* emitDelegateYield(RegisterID* argument, ThrowableExpressionData*);
996 RegisterID* generatorStateRegister() { return &m_parameters[static_cast<int32_t>(JSGenerator::GeneratorArgument::State)]; }
997 RegisterID* generatorValueRegister() { return &m_parameters[static_cast<int32_t>(JSGenerator::GeneratorArgument::Value)]; }
998 RegisterID* generatorResumeModeRegister() { return &m_parameters[static_cast<int32_t>(JSGenerator::GeneratorArgument::ResumeMode)]; }
999 RegisterID* generatorFrameRegister() { return &m_parameters[static_cast<int32_t>(JSGenerator::GeneratorArgument::Frame)]; }
1000
1001 CodeType codeType() const { return m_codeType; }
1002
1003 bool shouldBeConcernedWithCompletionValue() const { return m_codeType != FunctionCode; }
1004
1005 bool shouldEmitDebugHooks() const { return m_codeGenerationMode.contains(CodeGenerationMode::Debugger) && !m_isBuiltinFunction; }
1006 bool shouldEmitTypeProfilerHooks() const { return m_codeGenerationMode.contains(CodeGenerationMode::TypeProfiler); }
1007 bool shouldEmitControlFlowProfilerHooks() const { return m_codeGenerationMode.contains(CodeGenerationMode::ControlFlowProfiler); }
1008
1009 bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
1010
1011 SourceParseMode parseMode() const { return m_codeBlock->parseMode(); }
1012
1013 bool isBuiltinFunction() const { return m_isBuiltinFunction; }
1014
1015 OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
1016
1017 bool isDerivedConstructorContext() { return m_derivedContextType == DerivedContextType::DerivedConstructorContext; }
1018 bool isDerivedClassContext() { return m_derivedContextType == DerivedContextType::DerivedMethodContext; }
1019 bool isArrowFunction() { return m_codeBlock->isArrowFunction(); }
1020
1021 enum class TDZCheckOptimization { Optimize, DoNotOptimize };
1022 enum class NestedScopeType { IsNested, IsNotNested };
1023 private:
1024 enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
1025 enum class ScopeType { CatchScope, LetConstScope, FunctionNameScope };
1026 enum class ScopeRegisterType { Var, Block };
1027 void pushLexicalScopeInternal(VariableEnvironment&, TDZCheckOptimization, NestedScopeType, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
1028 void initializeBlockScopedFunctions(VariableEnvironment&, FunctionStack&, RegisterID* constantSymbolTable);
1029 void popLexicalScopeInternal(VariableEnvironment&);
1030 template<typename LookUpVarKindFunctor>
1031 bool instantiateLexicalVariables(const VariableEnvironment&, SymbolTable*, ScopeRegisterType, LookUpVarKindFunctor);
1032 void emitPrefillStackTDZVariables(const VariableEnvironment&, SymbolTable*);
1033 RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
1034 void emitPushFunctionNameScope(const Identifier& property, RegisterID* value, bool isCaptured);
1035 void emitNewFunctionExpressionCommon(RegisterID*, FunctionMetadataNode*);
1036
1037 bool isNewTargetUsedInInnerArrowFunction();
1038 bool isArgumentsUsedInInnerArrowFunction();
1039
1040 void emitToThis();
1041
1042 RegisterID* emitMove(RegisterID* dst, RegisterID* src);
1043
1044 bool canDoPeepholeOptimization() const { return m_lastOpcodeID != op_end; }
1045
1046 public:
1047 bool isSuperUsedInInnerArrowFunction();
1048 bool isSuperCallUsedInInnerArrowFunction();
1049 bool isThisUsedInInnerArrowFunction();
1050 void pushLexicalScope(VariableEnvironmentNode*, TDZCheckOptimization, NestedScopeType = NestedScopeType::IsNotNested, RegisterID** constantSymbolTableResult = nullptr, bool shouldInitializeBlockScopedFunctions = true);
1051 void popLexicalScope(VariableEnvironmentNode*);
1052 void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
1053 int labelScopeDepth() const;
1054 UnlinkedArrayProfile newArrayProfile();
1055
1056 private:
1057 ParserError generate();
1058 Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&, int symbolTableConstantIndex, bool isLexicallyScoped);
1059
1060 RegisterID* kill(RegisterID* dst)
1061 {
1062 m_staticPropertyAnalyzer.kill(dst);
1063 return dst;
1064 }
1065
1066 void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
1067 ALWAYS_INLINE void rewind();
1068
1069 void allocateAndEmitScope();
1070
1071 template<typename JumpOp>
1072 void setTargetForJumpInstruction(InstructionStream::MutableRef&, int target);
1073
1074 using BigIntMapEntry = std::tuple<UniquedStringImpl*, uint8_t, bool>;
1075
1076 using NumberMap = HashMap<double, JSValue>;
1077 using IdentifierStringMap = HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash>;
1078 using IdentifierBigIntMap = HashMap<BigIntMapEntry, JSBigInt*>;
1079 using TemplateObjectDescriptorSet = HashSet<Ref<TemplateObjectDescriptor>>;
1080 using TemplateDescriptorMap = HashMap<uint64_t, JSTemplateObjectDescriptor*, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>;
1081
1082 // Helper for emitCall() and emitConstruct(). This works because the set of
1083 // expected functions have identical behavior for both call and construct
1084 // (i.e. "Object()" is identical to "new Object()").
1085 ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label& done);
1086
1087 template<typename CallOp>
1088 RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
1089
1090 RegisterID* emitCallIterator(RegisterID* iterator, RegisterID* argument, ThrowableExpressionData*);
1091
1092 // Initializes the stack form the parameter; does nothing for the symbol table.
1093 RegisterID* initializeNextParameter();
1094 UniquedStringImpl* visibleNameForParameter(DestructuringPatternNode*);
1095
1096 RegisterID& registerFor(VirtualRegister reg)
1097 {
1098 if (reg.isLocal())
1099 return m_calleeLocals[reg.toLocal()];
1100
1101 if (reg.offset() == CallFrameSlot::callee)
1102 return m_calleeRegister;
1103
1104 ASSERT(m_parameters.size());
1105 return m_parameters[reg.toArgument()];
1106 }
1107
1108 bool hasConstant(const Identifier&) const;
1109 unsigned addConstant(const Identifier&);
1110 RegisterID* addConstantValue(JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
1111 RegisterID* addConstantEmptyValue();
1112
1113 UnlinkedFunctionExecutable* makeFunction(FunctionMetadataNode* metadata)
1114 {
1115 DerivedContextType newDerivedContextType = DerivedContextType::None;
1116
1117 if (SourceParseModeSet(SourceParseMode::ArrowFunctionMode, SourceParseMode::AsyncArrowFunctionMode, SourceParseMode::AsyncArrowFunctionBodyMode).contains(metadata->parseMode())) {
1118 if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext())
1119 newDerivedContextType = DerivedContextType::DerivedConstructorContext;
1120 else if (m_codeBlock->isClassContext() || isDerivedClassContext())
1121 newDerivedContextType = DerivedContextType::DerivedMethodContext;
1122 }
1123
1124 Optional<CompactVariableMap::Handle> optionalVariablesUnderTDZ = getVariablesUnderTDZ();
1125
1126 // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized.
1127 // https://bugs.webkit.org/show_bug.cgi?id=151547
1128 SourceParseMode parseMode = metadata->parseMode();
1129 ConstructAbility constructAbility = constructAbilityForParseMode(parseMode);
1130 if (parseMode == SourceParseMode::MethodMode && metadata->constructorKind() != ConstructorKind::None)
1131 constructAbility = ConstructAbility::CanConstruct;
1132
1133 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), newDerivedContextType);
1134 }
1135
1136 Optional<CompactVariableMap::Handle> getVariablesUnderTDZ();
1137
1138 RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
1139 template<typename CallOp>
1140 RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
1141
1142 void emitLogShadowChickenPrologueIfNecessary();
1143 void emitLogShadowChickenTailIfNecessary();
1144
1145 void initializeParameters(FunctionParameters&);
1146 void initializeVarLexicalEnvironment(int symbolTableConstantIndex, SymbolTable* functionSymbolTable, bool hasCapturedVariables);
1147 void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&, bool isSimpleParameterList, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const ScopedLambda<bool (UniquedStringImpl*)>& captures, bool shouldCreateArgumentsVariableInParameterScope);
1148 void initializeArrowFunctionContextScopeIfNeeded(SymbolTable* functionSymbolTable = nullptr, bool canReuseLexicalEnvironment = false);
1149 bool needsDerivedConstructorInArrowFunctionLexicalEnvironment();
1150
1151 enum class TDZNecessityLevel {
1152 NotNeeded,
1153 Optimize,
1154 DoNotOptimize
1155 };
1156 typedef HashMap<RefPtr<UniquedStringImpl>, TDZNecessityLevel, IdentifierRepHash> TDZMap;
1157
1158 public:
1159 JSString* addStringConstant(const Identifier&);
1160 JSValue addBigIntConstant(const Identifier&, uint8_t radix, bool sign);
1161 RegisterID* addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&&, int);
1162
1163 const InstructionStream& instructions() const { return m_writer; }
1164
1165 RegisterID* emitThrowExpressionTooDeepException();
1166
1167 class PreservedTDZStack {
1168 private:
1169 Vector<TDZMap> m_preservedTDZStack;
1170 friend class BytecodeGenerator;
1171 };
1172
1173 void preserveTDZStack(PreservedTDZStack&);
1174 void restoreTDZStack(const PreservedTDZStack&);
1175
1176 template<typename Func>
1177 void withWriter(InstructionStreamWriter& writer, const Func& fn)
1178 {
1179 auto prevLastOpcodeID = m_lastOpcodeID;
1180 auto prevLastInstruction = m_lastInstruction;
1181 m_writer.swap(writer);
1182 m_lastOpcodeID = op_end;
1183 m_lastInstruction = m_writer.ref();
1184 fn();
1185 m_writer.swap(writer);
1186 m_lastOpcodeID = prevLastOpcodeID;
1187 m_lastInstruction = prevLastInstruction;
1188 }
1189
1190 private:
1191 OptionSet<CodeGenerationMode> m_codeGenerationMode;
1192
1193 struct LexicalScopeStackEntry {
1194 SymbolTable* m_symbolTable;
1195 RegisterID* m_scope;
1196 bool m_isWithScope;
1197 int m_symbolTableConstantIndex;
1198 };
1199 Vector<LexicalScopeStackEntry> m_lexicalScopeStack;
1200
1201 Vector<TDZMap> m_TDZStack;
1202 Optional<size_t> m_varScopeLexicalScopeStackIndex;
1203 void pushTDZVariables(const VariableEnvironment&, TDZCheckOptimization, TDZRequirement);
1204
1205 ScopeNode* const m_scopeNode;
1206
1207 // Some of these objects keep pointers to one another. They are arranged
1208 // to ensure a sane destruction order that avoids references to freed memory.
1209 HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> m_functions;
1210 RegisterID m_ignoredResultRegister;
1211 RegisterID m_thisRegister;
1212 RegisterID m_calleeRegister;
1213 RegisterID* m_scopeRegister { nullptr };
1214 RegisterID* m_topMostScope { nullptr };
1215 RegisterID* m_argumentsRegister { nullptr };
1216 RegisterID* m_lexicalEnvironmentRegister { nullptr };
1217 RegisterID* m_generatorRegister { nullptr };
1218 RegisterID* m_emptyValueRegister { nullptr };
1219 RegisterID* m_newTargetRegister { nullptr };
1220 RegisterID* m_isDerivedConstuctor { nullptr };
1221 HashMap<LinkTimeConstant, RegisterID*, WTF::IntHash<LinkTimeConstant>, WTF::StrongEnumHashTraits<LinkTimeConstant>> m_linkTimeConstantRegisters;
1222 RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
1223 RegisterID* m_promiseRegister { nullptr };
1224
1225 FinallyContext* m_currentFinallyContext { nullptr };
1226
1227 SegmentedVector<RegisterID, 32> m_parameters;
1228 SegmentedVector<LabelScope, 32> m_labelScopes;
1229 SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
1230 unsigned m_finallyDepth { 0 };
1231 unsigned m_localScopeDepth { 0 };
1232 const CodeType m_codeType;
1233
1234 unsigned localScopeDepth() const;
1235 void pushLocalControlFlowScope();
1236 void popLocalControlFlowScope();
1237
1238 // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it.
1239 // https://bugs.webkit.org/show_bug.cgi?id=165980
1240 SegmentedVector<ControlFlowScope, 16> m_controlFlowScopeStack;
1241 Vector<SwitchInfo> m_switchContextStack;
1242 Vector<Ref<ForInContext>> m_forInContextStack;
1243 Vector<TryContext> m_tryContextStack;
1244 unsigned m_yieldPoints { 0 };
1245
1246 Strong<SymbolTable> m_generatorFrameSymbolTable;
1247 int m_generatorFrameSymbolTableIndex { 0 };
1248
1249 enum FunctionVariableType : uint8_t { NormalFunctionVariable, TopLevelFunctionVariable };
1250 Vector<std::pair<FunctionMetadataNode*, FunctionVariableType>> m_functionsToInitialize;
1251 bool m_needToInitializeArguments { false };
1252 RestParameterNode* m_restParameter { nullptr };
1253
1254 Vector<TryRange> m_tryRanges;
1255 SegmentedVector<TryData, 8> m_tryData;
1256
1257 Vector<Ref<Label>> m_optionalChainTargetStack;
1258
1259 int m_nextConstantOffset { 0 };
1260
1261 typedef HashMap<FunctionMetadataNode*, unsigned> FunctionOffsetMap;
1262 FunctionOffsetMap m_functionOffsets;
1263
1264 // Constant pool
1265 IdentifierMap m_identifierMap;
1266
1267 typedef HashMap<EncodedJSValueWithRepresentation, unsigned, EncodedJSValueWithRepresentationHash, EncodedJSValueWithRepresentationHashTraits> JSValueMap;
1268 JSValueMap m_jsValueMap;
1269 IdentifierStringMap m_stringMap;
1270 IdentifierBigIntMap m_bigIntMap;
1271 TemplateObjectDescriptorSet m_templateObjectDescriptorSet;
1272 TemplateDescriptorMap m_templateDescriptorMap;
1273
1274 StaticPropertyAnalyzer m_staticPropertyAnalyzer;
1275
1276 VM& m_vm;
1277
1278 bool m_usesExceptions { false };
1279 bool m_expressionTooDeep { false };
1280 bool m_isBuiltinFunction { false };
1281 bool m_usesNonStrictEval { false };
1282 bool m_inTailPosition { false };
1283 bool m_needsToUpdateArrowFunctionContext;
1284 bool m_hasCachedVariablesUnderTDZ { false };
1285 DerivedContextType m_derivedContextType { DerivedContextType::None };
1286
1287 CompactVariableMap::Handle m_cachedVariablesUnderTDZ;
1288
1289 struct CatchEntry {
1290 TryData* tryData;
1291 VirtualRegister exceptionRegister;
1292 VirtualRegister thrownValueRegister;
1293 VirtualRegister completionTypeRegister;
1294 };
1295 Vector<CatchEntry> m_exceptionHandlersToEmit;
1296 };
1297
1298} // namespace JSC
1299
1300namespace WTF {
1301
1302void printInternal(PrintStream&, JSC::Variable::VariableKind);
1303
1304} // namespace WTF
1305