2 * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 * Copyright (C) 2012 Igalia, S.L.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef BytecodeGenerator_h
32 #define BytecodeGenerator_h
34 #include "CodeBlock.h"
35 #include "GeneratorThisMode.h"
36 #include <wtf/HashTraits.h>
37 #include "Instruction.h"
39 #include "LabelScope.h"
40 #include "Interpreter.h"
41 #include "ParserError.h"
42 #include "RegisterID.h"
43 #include "SetForScope.h"
44 #include "SymbolTable.h"
47 #include "StaticPropertyAnalyzer.h"
48 #include "TemplateRegistryKey.h"
49 #include "UnlinkedCodeBlock.h"
53 #include <wtf/PassRefPtr.h>
54 #include <wtf/SegmentedVector.h>
55 #include <wtf/Vector.h>
61 class JSTemplateRegistryKey;
63 enum ExpectedFunction {
65 ExpectObjectConstructor,
66 ExpectArrayConstructor
69 enum class ThisResolutionType { Local, Scoped };
73 CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
75 RegisterID* thisRegister() { return m_argv[0].get(); }
76 RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
77 unsigned stackOffset() { return -m_argv[0]->index() + JSStack::CallFrameHeaderSize; }
78 unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
79 RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
80 ArgumentsNode* argumentsNode() { return m_argumentsNode; }
83 RefPtr<RegisterID> m_profileHookRegister;
84 ArgumentsNode* m_argumentsNode;
85 Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
89 struct FinallyContext {
90 StatementNode* finallyBlock;
92 ThrowableExpressionData* enumerationNode;
93 unsigned scopeContextStackSize;
94 unsigned switchContextStackSize;
95 unsigned forInContextStackSize;
96 unsigned tryContextStackSize;
97 unsigned labelScopesSize;
98 unsigned symbolTableStackSize;
100 int dynamicScopeDepth;
103 struct ControlFlowContext {
105 FinallyContext finallyContext;
109 WTF_MAKE_FAST_ALLOCATED;
111 ForInContext(RegisterID* localRegister)
112 : m_localRegister(localRegister)
117 virtual ~ForInContext()
121 bool isValid() const { return m_isValid; }
122 void invalidate() { m_isValid = false; }
124 enum ForInContextType {
125 StructureForInContextType,
126 IndexedForInContextType
128 virtual ForInContextType type() const = 0;
130 RegisterID* local() const { return m_localRegister.get(); }
133 RefPtr<RegisterID> m_localRegister;
137 class StructureForInContext : public ForInContext {
139 StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
140 : ForInContext(localRegister)
141 , m_indexRegister(indexRegister)
142 , m_propertyRegister(propertyRegister)
143 , m_enumeratorRegister(enumeratorRegister)
147 virtual ForInContextType type() const
149 return StructureForInContextType;
152 RegisterID* index() const { return m_indexRegister.get(); }
153 RegisterID* property() const { return m_propertyRegister.get(); }
154 RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
157 RefPtr<RegisterID> m_indexRegister;
158 RefPtr<RegisterID> m_propertyRegister;
159 RefPtr<RegisterID> m_enumeratorRegister;
162 class IndexedForInContext : public ForInContext {
164 IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
165 : ForInContext(localRegister)
166 , m_indexRegister(indexRegister)
170 virtual ForInContextType type() const
172 return IndexedForInContextType;
175 RegisterID* index() const { return m_indexRegister.get(); }
178 RefPtr<RegisterID> m_indexRegister;
182 RefPtr<Label> target;
183 HandlerType handlerType;
193 enum VariableKind { NormalVariable, SpecialVariable };
199 , m_kind(NormalVariable)
200 , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
201 , m_isLexicallyScoped(false)
205 Variable(const Identifier& ident)
209 , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable.
210 , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
211 , m_isLexicallyScoped(false)
215 Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind, int symbolTableConstantIndex, bool isLexicallyScoped)
219 , m_attributes(attributes)
221 , m_symbolTableConstantIndex(symbolTableConstantIndex)
222 , m_isLexicallyScoped(isLexicallyScoped)
226 // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be
227 // a stack variable, a scoped variable in a local scope, or a variable captured in the
228 // direct arguments object.
229 bool isResolved() const { return !!m_offset; }
230 int symbolTableConstantIndex() const { ASSERT(isResolved() && !isSpecial()); return m_symbolTableConstantIndex; }
232 const Identifier& ident() const { return m_ident; }
234 VarOffset offset() const { return m_offset; }
235 bool isLocal() const { return m_offset.isStack(); }
236 RegisterID* local() const { return m_local; }
238 bool isReadOnly() const { return m_attributes & ReadOnly; }
239 bool isSpecial() const { return m_kind != NormalVariable; }
240 bool isConst() const { return isReadOnly() && m_isLexicallyScoped; }
241 void setIsReadOnly() { m_attributes |= ReadOnly; }
247 unsigned m_attributes;
249 int m_symbolTableConstantIndex;
250 bool m_isLexicallyScoped;
259 enum ProfileTypeBytecodeFlag {
260 ProfileTypeBytecodeClosureVar,
261 ProfileTypeBytecodeLocallyResolved,
262 ProfileTypeBytecodeDoesNotHaveGlobalID,
263 ProfileTypeBytecodeFunctionArgument,
264 ProfileTypeBytecodeFunctionReturnStatement
267 class BytecodeGenerator {
268 WTF_MAKE_FAST_ALLOCATED;
269 WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
271 typedef DeclarationStacks::FunctionStack FunctionStack;
273 BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
274 BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
275 BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
276 BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
278 ~BytecodeGenerator();
280 VM* vm() const { return m_vm; }
281 ParserArena& parserArena() const { return m_scopeNode->parserArena(); }
282 const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
284 bool isConstructor() const { return m_codeBlock->isConstructor(); }
285 bool isDerivedConstructorContext() const { return m_codeBlock->isDerivedConstructorContext(); }
286 bool usesArrowFunction() const { return m_scopeNode->usesArrowFunction(); }
287 bool needsToUpdateArrowFunctionContext() const { return m_needsToUpdateArrowFunctionContext; }
288 bool usesEval() const { return m_scopeNode->usesEval(); }
289 bool usesThis() const { return m_scopeNode->usesThis(); }
290 ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
291 GeneratorThisMode generatorThisMode() const { return m_codeBlock->generatorThisMode(); }
292 SuperBinding superBinding() const { return m_codeBlock->superBinding(); }
294 ParserError generate();
296 bool isArgumentNumber(const Identifier&, int);
298 Variable variable(const Identifier&, ThisResolutionType = ThisResolutionType::Local);
300 enum ExistingVariableMode { VerifyExisting, IgnoreExisting };
301 void createVariable(const Identifier&, VarKind, SymbolTable*, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible.
303 // Returns the register storing "this"
304 RegisterID* thisRegister() { return &m_thisRegister; }
305 RegisterID* argumentsRegister() { return m_argumentsRegister; }
306 RegisterID* newTarget()
308 return !m_codeBlock->isArrowFunction() || m_isNewTargetLoadedInArrowFunction
309 ? m_newTargetRegister : emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
312 RegisterID* scopeRegister() { return m_scopeRegister; }
314 RegisterID* generatorRegister() { return m_generatorRegister; }
316 // Returns the next available temporary register. Registers returned by
317 // newTemporary require a modified form of reference counting: any
318 // register with a refcount of 0 is considered "available", meaning that
319 // the next instruction may overwrite it.
320 RegisterID* newTemporary();
322 // The same as newTemporary(), but this function returns "suggestion" if
323 // "suggestion" is a temporary. This function is helpful in situations
324 // where you've put "suggestion" in a RefPtr, but you'd like to allow
325 // the next instruction to overwrite it anyway.
326 RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
328 // Functions for handling of dst register
330 RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
332 // This will be allocated in the temporary region of registers, but it will
333 // not be marked as a temporary. This will ensure that finalDestination() does
334 // not overwrite a block scope variable that it mistakes as a temporary. These
335 // registers can be (and are) reclaimed when the lexical scope they belong to
336 // is no longer on the symbol table stack.
337 RegisterID* newBlockScopeVariable();
339 // Returns a place to write intermediate values of an operation
340 // which reuses dst if it is safe to do so.
341 RegisterID* tempDestination(RegisterID* dst)
343 return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
346 // Returns the place to write the final output of an operation.
347 RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
349 if (originalDst && originalDst != ignoredResult())
351 ASSERT(tempDst != ignoredResult());
352 if (tempDst && tempDst->isTemporary())
354 return newTemporary();
357 RegisterID* destinationForAssignResult(RegisterID* dst)
359 if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
360 return dst->isTemporary() ? dst : newTemporary();
364 // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
365 RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
367 return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
370 LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
371 PassRefPtr<Label> newLabel();
373 void emitNode(RegisterID* dst, StatementNode* n)
375 SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
376 return emitNodeInTailPosition(dst, n);
379 void emitNodeInTailPosition(RegisterID* dst, StatementNode* n)
381 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
382 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
383 if (!m_vm->isSafeToRecurse()) {
384 emitThrowExpressionTooDeepException();
387 n->emitBytecode(*this, dst);
390 void emitNode(StatementNode* n)
392 emitNode(nullptr, n);
395 void emitNodeInTailPosition(StatementNode* n)
397 emitNodeInTailPosition(nullptr, n);
400 RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
402 SetForScope<bool> tailPositionPoisoner(m_inTailPosition, false);
403 return emitNodeInTailPosition(dst, n);
406 RegisterID* emitNodeInTailPosition(RegisterID* dst, ExpressionNode* n)
408 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
409 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
410 if (!m_vm->isSafeToRecurse())
411 return emitThrowExpressionTooDeepException();
412 return n->emitBytecode(*this, dst);
415 RegisterID* emitNode(ExpressionNode* n)
417 return emitNode(nullptr, n);
420 RegisterID* emitNodeInTailPosition(ExpressionNode* n)
422 return emitNodeInTailPosition(nullptr, n);
425 void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
427 if (!m_vm->isSafeToRecurse()) {
428 emitThrowExpressionTooDeepException();
432 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
435 void emitExpressionInfo(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
437 ASSERT(divot.offset >= divotStart.offset);
438 ASSERT(divotEnd.offset >= divot.offset);
440 int sourceOffset = m_scopeNode->source().startOffset();
441 unsigned firstLine = m_scopeNode->source().firstLine();
443 int divotOffset = divot.offset - sourceOffset;
444 int startOffset = divot.offset - divotStart.offset;
445 int endOffset = divotEnd.offset - divot.offset;
447 unsigned line = divot.line;
448 ASSERT(line >= firstLine);
451 int lineStart = divot.lineStartOffset;
452 if (lineStart > sourceOffset)
453 lineStart -= sourceOffset;
457 if (divotOffset < lineStart)
460 unsigned column = divotOffset - lineStart;
462 unsigned instructionOffset = instructions().size();
463 if (!m_isBuiltinFunction)
464 m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
468 ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
470 return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
473 ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
475 if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
476 PassRefPtr<RegisterID> dst = newTemporary();
477 emitNode(dst.get(), n);
485 void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
488 // This doesn't emit expression info. If using this, make sure you shouldn't be emitting text offset.
489 void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag);
490 // These variables are associated with variables in a program. They could be Locals, LocalClosureVar, or ClosureVar.
491 void emitProfileType(RegisterID* registerToProfile, const Variable&, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
493 void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
494 // These are not associated with variables and don't have a global id.
495 void emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
497 void emitProfileControlFlow(int);
499 RegisterID* emitLoadArrowFunctionLexicalEnvironment();
500 void emitLoadThisFromArrowFunctionLexicalEnvironment();
501 RegisterID* emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
503 RegisterID* emitLoad(RegisterID* dst, bool);
504 RegisterID* emitLoad(RegisterID* dst, const Identifier&);
505 RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
506 RegisterID* emitLoadGlobalObject(RegisterID* dst);
508 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
509 RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
510 RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
511 RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
513 RegisterID* emitCreateThis(RegisterID* dst);
514 void emitTDZCheck(RegisterID* target);
515 bool needsTDZCheck(const Variable&);
516 void emitTDZCheckIfNecessary(const Variable&, RegisterID* target, RegisterID* scope);
517 void liftTDZCheckIfPossible(const Variable&);
518 RegisterID* emitNewObject(RegisterID* dst);
519 RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
520 RegisterID* emitNewArrayWithSize(RegisterID* dst, RegisterID* length);
522 RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*);
523 RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
524 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name);
525 RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*);
526 RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
528 RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
529 RegisterID* emitMoveEmptyValue(RegisterID* dst);
530 RegisterID* emitMove(RegisterID* dst, RegisterID* src);
532 RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); }
533 RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); }
534 RegisterID* emitInc(RegisterID* srcDst);
535 RegisterID* emitDec(RegisterID* srcDst);
537 RegisterID* emitOverridesHasInstance(RegisterID* dst, RegisterID* constructor, RegisterID* hasInstanceValue);
538 RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
539 RegisterID* emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue);
540 RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
541 RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
543 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
544 RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
545 RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);
546 RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
547 RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
548 RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
549 RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
550 RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
551 RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
552 RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
554 RegisterID* emitAssert(RegisterID* condition, int line);
556 void emitPutGetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* getter);
557 void emitPutSetterById(RegisterID* base, const Identifier& property, unsigned propertyDescriptorOptions, RegisterID* setter);
558 void emitPutGetterSetter(RegisterID* base, const Identifier& property, unsigned attributes, RegisterID* getter, RegisterID* setter);
559 void emitPutGetterByVal(RegisterID* base, RegisterID* property, unsigned propertyDescriptorOptions, RegisterID* getter);
560 void emitPutSetterByVal(RegisterID* base, RegisterID* property, unsigned propertyDescriptorOptions, RegisterID* setter);
562 ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
563 RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
564 RegisterID* emitCallInTailPosition(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
565 RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
566 RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
567 RegisterID* emitCallVarargsInTailPosition(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
569 enum PropertyDescriptorOption {
570 PropertyConfigurable = 1,
571 PropertyWritable = 1 << 1,
572 PropertyEnumerable = 1 << 2,
574 void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
575 RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
577 void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, VariableEnvironmentNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
579 RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
581 RegisterID* emitReturn(RegisterID* src);
582 RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
584 RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
585 RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
586 void emitToPrimitive(RegisterID* dst, RegisterID* src);
588 ResolveType resolveType();
589 RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&);
590 RegisterID* emitResolveScope(RegisterID* dst, const Variable&);
591 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable&, ResolveMode);
592 RegisterID* emitPutToScope(RegisterID* scope, const Variable&, RegisterID* value, ResolveMode, InitializationMode);
593 RegisterID* initializeVariable(const Variable&, RegisterID* value);
595 PassRefPtr<Label> emitLabel(Label*);
597 PassRefPtr<Label> emitJump(Label* target);
598 PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
599 PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
600 PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
601 PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
602 void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
607 RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
608 RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
609 RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
610 RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
611 RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
612 RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
613 RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
614 RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
615 RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
616 RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
618 RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
619 RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
620 void emitRequireObjectCoercible(RegisterID* value, const String& error);
622 RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node);
623 RegisterID* emitIteratorNextWithValue(RegisterID* dst, RegisterID* iterator, RegisterID* value, const ThrowableExpressionData* node);
624 void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node);
626 RegisterID* emitRestParameter(RegisterID* result, unsigned numParametersToSkip);
628 bool emitReadOnlyExceptionIfNeeded(const Variable&);
630 // Start a try block. 'start' must have been emitted.
631 TryData* pushTry(Label* start);
632 // End a try block. 'end' must have been emitted.
633 void popTryAndEmitCatch(TryData*, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType);
635 void emitThrow(RegisterID* exc)
637 m_usesExceptions = true;
638 emitUnaryNoDstOp(op_throw, exc);
641 void emitThrowReferenceError(const String& message);
642 void emitThrowTypeError(const String& message);
644 void emitPushCatchScope(const Identifier& property, RegisterID* exceptionValue, VariableEnvironment&);
645 void emitPopCatchScope(VariableEnvironment&);
648 RegisterID* emitPushWithScope(RegisterID* objectScope);
649 void emitPopWithScope();
650 void emitPutThisToArrowFunctionContextScope();
651 void emitPutNewTargetToArrowFunctionContextScope();
652 void emitPutDerivedConstructorToArrowFunctionContextScope();
653 RegisterID* emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
655 void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
657 bool isInFinallyBlock() { return m_finallyDepth > 0; }
659 void pushFinallyContext(StatementNode* finallyBlock);
660 void popFinallyContext();
661 void pushIteratorCloseContext(RegisterID* iterator, ThrowableExpressionData* enumerationNode);
662 void popIteratorCloseContext();
664 void pushIndexedForInScope(RegisterID* local, RegisterID* index);
665 void popIndexedForInScope(RegisterID* local);
666 void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
667 void popStructureForInScope(RegisterID* local);
668 void invalidateForInContextForLocal(RegisterID* local);
670 LabelScopePtr breakTarget(const Identifier&);
671 LabelScopePtr continueTarget(const Identifier&);
673 void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
674 void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
676 void emitYieldPoint(RegisterID*);
677 void emitSave(Label* mergePoint, unsigned liveCalleeLocalsIndex);
678 void emitResume(Label* mergePoint, unsigned liveCalleeLocalsIndex);
680 void emitGeneratorStateLabel();
681 void emitGeneratorStateChange(int32_t state);
682 RegisterID* emitYield(RegisterID* argument);
683 RegisterID* emitDelegateYield(RegisterID* argument, ThrowableExpressionData*);
684 void beginGenerator(RegisterID*);
685 void endGenerator(Label* defaultLabel);
686 RegisterID* generatorStateRegister() { return &m_parameters[2]; }
687 RegisterID* generatorValueRegister() { return &m_parameters[3]; }
688 RegisterID* generatorResumeModeRegister() { return &m_parameters[4]; }
690 CodeType codeType() const { return m_codeType; }
692 bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
693 bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
695 bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
697 SourceParseMode parseMode() const { return m_codeBlock->parseMode(); }
699 bool isBuiltinFunction() const { return m_isBuiltinFunction; }
701 OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
703 enum class TDZCheckOptimization { Optimize, DoNotOptimize };
704 enum class NestedScopeType { IsNested, IsNotNested };
706 enum class TDZRequirement { UnderTDZ, NotUnderTDZ };
707 enum class ScopeType { CatchScope, LetConstScope, FunctionNameScope };
708 enum class ScopeRegisterType { Var, Block };
709 void pushLexicalScopeInternal(VariableEnvironment&, TDZCheckOptimization, NestedScopeType, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
710 void popLexicalScopeInternal(VariableEnvironment&, TDZRequirement);
711 template<typename LookUpVarKindFunctor>
712 bool instantiateLexicalVariables(const VariableEnvironment&, SymbolTable*, ScopeRegisterType, LookUpVarKindFunctor);
713 void emitPrefillStackTDZVariables(const VariableEnvironment&, SymbolTable*);
714 void emitPopScope(RegisterID* dst, RegisterID* scope);
715 RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
716 void emitPushFunctionNameScope(const Identifier& property, RegisterID* value, bool isCaptured);
717 void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*);
720 void pushLexicalScope(VariableEnvironmentNode*, TDZCheckOptimization, NestedScopeType = NestedScopeType::IsNotNested, RegisterID** constantSymbolTableResult = nullptr);
721 void popLexicalScope(VariableEnvironmentNode*);
722 void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
723 int labelScopeDepth() const;
726 void reclaimFreeRegisters();
727 Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&, int symbolTableConstantIndex, bool isLexicallyScoped);
729 void emitOpcode(OpcodeID);
730 UnlinkedArrayAllocationProfile newArrayAllocationProfile();
731 UnlinkedObjectAllocationProfile newObjectAllocationProfile();
732 UnlinkedArrayProfile newArrayProfile();
733 UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
734 int kill(RegisterID* dst)
736 int index = dst->index();
737 m_staticPropertyAnalyzer.kill(index);
741 void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
742 void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
743 ALWAYS_INLINE void rewindBinaryOp();
744 ALWAYS_INLINE void rewindUnaryOp();
746 void allocateCalleeSaveSpace();
747 void allocateAndEmitScope();
748 void emitComplexPopScopes(RegisterID*, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
750 typedef HashMap<double, JSValue> NumberMap;
751 typedef HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
752 typedef HashMap<TemplateRegistryKey, JSTemplateRegistryKey*> TemplateRegistryKeyMap;
754 // Helper for emitCall() and emitConstruct(). This works because the set of
755 // expected functions have identical behavior for both call and construct
756 // (i.e. "Object()" is identical to "new Object()").
757 ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
759 RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
761 RegisterID* newRegister();
763 // Adds an anonymous local var slot. To give this slot a name, add it to symbolTable().
766 ++m_codeBlock->m_numVars;
767 RegisterID* result = newRegister();
768 ASSERT(VirtualRegister(result->index()).toLocal() == m_codeBlock->m_numVars - 1);
769 result->ref(); // We should never free this slot.
773 // Initializes the stack form the parameter; does nothing for the symbol table.
774 RegisterID* initializeNextParameter();
775 UniquedStringImpl* visibleNameForParameter(DestructuringPatternNode*);
777 RegisterID& registerFor(VirtualRegister reg)
780 return m_calleeLocals[reg.toLocal()];
782 if (reg.offset() == JSStack::Callee)
783 return m_calleeRegister;
785 ASSERT(m_parameters.size());
786 return m_parameters[reg.toArgument()];
789 bool hasConstant(const Identifier&) const;
790 unsigned addConstant(const Identifier&);
791 RegisterID* addConstantValue(JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
792 RegisterID* addConstantEmptyValue();
793 unsigned addRegExp(RegExp*);
795 unsigned addConstantBuffer(unsigned length);
797 UnlinkedFunctionExecutable* makeFunction(FunctionMetadataNode* metadata)
799 bool newisDerivedConstructorContext = constructorKind() == ConstructorKind::Derived || (m_isDerivedConstructorContext && metadata->parseMode() == SourceParseMode::ArrowFunctionMode);
801 VariableEnvironment variablesUnderTDZ;
802 getVariablesUnderTDZ(variablesUnderTDZ);
804 // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized.
805 // https://bugs.webkit.org/show_bug.cgi?id=151547
806 SourceParseMode parseMode = metadata->parseMode();
807 ConstructAbility constructAbility = ConstructAbility::CanConstruct;
808 if (parseMode == SourceParseMode::GetterMode || parseMode == SourceParseMode::SetterMode || parseMode == SourceParseMode::ArrowFunctionMode)
809 constructAbility = ConstructAbility::CannotConstruct;
810 else if (parseMode == SourceParseMode::MethodMode && metadata->constructorKind() == ConstructorKind::None)
811 constructAbility = ConstructAbility::CannotConstruct;
812 else if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode && metadata->superBinding() == SuperBinding::Needed)
813 constructAbility = ConstructAbility::CannotConstruct;
815 GeneratorThisMode generatorThisMode = GeneratorThisMode::NonEmpty;
816 if (parseMode == SourceParseMode::GeneratorBodyMode && isConstructor())
817 generatorThisMode = GeneratorThisMode::Empty;
819 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, generatorThisMode, variablesUnderTDZ, newisDerivedConstructorContext);
822 void getVariablesUnderTDZ(VariableEnvironment&);
824 RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
825 RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
827 void initializeParameters(FunctionParameters&);
828 void initializeVarLexicalEnvironment(int symbolTableConstantIndex);
829 void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const std::function<bool (UniquedStringImpl*)>& captures);
830 void initializeArrowFunctionContextScopeIfNeeded(SymbolTable* = nullptr);
833 JSString* addStringConstant(const Identifier&);
834 JSTemplateRegistryKey* addTemplateRegistryKeyConstant(const TemplateRegistryKey&);
836 Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
838 RegisterID* emitThrowExpressionTooDeepException();
841 Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
843 bool m_shouldEmitDebugHooks;
844 bool m_shouldEmitProfileHooks;
846 struct SymbolTableStackEntry {
847 Strong<SymbolTable> m_symbolTable;
850 int m_symbolTableConstantIndex;
852 Vector<SymbolTableStackEntry> m_symbolTableStack;
853 Vector<std::pair<VariableEnvironment, bool>> m_TDZStack;
855 ScopeNode* const m_scopeNode;
856 Strong<UnlinkedCodeBlock> m_codeBlock;
858 // Some of these objects keep pointers to one another. They are arranged
859 // to ensure a sane destruction order that avoids references to freed memory.
860 HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> m_functions;
861 RegisterID m_ignoredResultRegister;
862 RegisterID m_thisRegister;
863 RegisterID m_calleeRegister;
864 RegisterID* m_scopeRegister { nullptr };
865 RegisterID* m_topMostScope { nullptr };
866 RegisterID* m_argumentsRegister { nullptr };
867 RegisterID* m_lexicalEnvironmentRegister { nullptr };
868 RegisterID* m_generatorRegister { nullptr };
869 RegisterID* m_emptyValueRegister { nullptr };
870 RegisterID* m_globalObjectRegister { nullptr };
871 RegisterID* m_newTargetRegister { nullptr };
872 RegisterID* m_linkTimeConstantRegisters[LinkTimeConstantCount];
873 RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
875 SegmentedVector<RegisterID*, 16> m_localRegistersForCalleeSaveRegisters;
876 SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
877 SegmentedVector<RegisterID, 32> m_calleeLocals;
878 SegmentedVector<RegisterID, 32> m_parameters;
879 SegmentedVector<Label, 32> m_labels;
880 LabelScopeStore m_labelScopes;
881 int m_finallyDepth { 0 };
882 int m_localScopeDepth { 0 };
883 const CodeType m_codeType;
885 int localScopeDepth() const;
886 void pushScopedControlFlowContext();
887 void popScopedControlFlowContext();
889 Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
890 Vector<SwitchInfo> m_switchContextStack;
891 Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
892 Vector<TryContext> m_tryContextStack;
893 Vector<RefPtr<Label>> m_generatorResumeLabels;
894 enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
895 Vector<std::pair<FunctionMetadataNode*, FunctionVariableType>> m_functionsToInitialize;
896 bool m_needToInitializeArguments { false };
897 RestParameterNode* m_restParameter { nullptr };
899 Vector<TryRange> m_tryRanges;
900 SegmentedVector<TryData, 8> m_tryData;
902 int m_nextConstantOffset { 0 };
904 typedef HashMap<FunctionMetadataNode*, unsigned> FunctionOffsetMap;
905 FunctionOffsetMap m_functionOffsets;
908 IdentifierMap m_identifierMap;
910 typedef HashMap<EncodedJSValueWithRepresentation, unsigned, EncodedJSValueWithRepresentationHash, EncodedJSValueWithRepresentationHashTraits> JSValueMap;
911 JSValueMap m_jsValueMap;
912 IdentifierStringMap m_stringMap;
913 TemplateRegistryKeyMap m_templateRegistryKeyMap;
915 StaticPropertyAnalyzer m_staticPropertyAnalyzer { &m_instructions };
919 OpcodeID m_lastOpcodeID = op_end;
921 size_t m_lastOpcodePosition { 0 };
924 bool m_usesExceptions { false };
925 bool m_expressionTooDeep { false };
926 bool m_isBuiltinFunction { false };
927 bool m_usesNonStrictEval { false };
928 bool m_inTailPosition { false };
929 bool m_isDerivedConstructorContext { false };
930 bool m_needsToUpdateArrowFunctionContext;
931 bool m_isNewTargetLoadedInArrowFunction { false };
936 #endif // BytecodeGenerator_h