]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecompiler/BytecodeGenerator.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / bytecompiler / BytecodeGenerator.h
CommitLineData
9dae56ea 1/*
ed1e77d3 2 * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
9dae56ea 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
93a37866 4 * Copyright (C) 2012 Igalia, S.L.
9dae56ea
A
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.
81345200 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
9dae56ea
A
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#ifndef BytecodeGenerator_h
32#define BytecodeGenerator_h
33
34#include "CodeBlock.h"
6fe7ccc8 35#include <wtf/HashTraits.h>
9dae56ea
A
36#include "Instruction.h"
37#include "Label.h"
38#include "LabelScope.h"
39#include "Interpreter.h"
93a37866 40#include "ParserError.h"
9dae56ea 41#include "RegisterID.h"
9dae56ea
A
42#include "SymbolTable.h"
43#include "Debugger.h"
44#include "Nodes.h"
93a37866 45#include "StaticPropertyAnalyzer.h"
ed1e77d3 46#include "TemplateRegistryKey.h"
93a37866 47#include "UnlinkedCodeBlock.h"
81345200
A
48
49#include <functional>
50
9dae56ea 51#include <wtf/PassRefPtr.h>
ba379fdc 52#include <wtf/SegmentedVector.h>
9dae56ea
A
53#include <wtf/Vector.h>
54
81345200 55
9dae56ea
A
56namespace JSC {
57
58 class Identifier;
ed1e77d3 59 class JSTemplateRegistryKey;
93a37866
A
60
61 enum ExpectedFunction {
62 NoExpectedFunction,
63 ExpectObjectConstructor,
64 ExpectArrayConstructor
65 };
14957cd0
A
66
67 class CallArguments {
68 public:
81345200 69 CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
14957cd0
A
70
71 RegisterID* thisRegister() { return m_argv[0].get(); }
72 RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
81345200
A
73 unsigned stackOffset() { return -m_argv[0]->index() + JSStack::CallFrameHeaderSize; }
74 unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
14957cd0
A
75 RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
76 ArgumentsNode* argumentsNode() { return m_argumentsNode; }
77
78 private:
79 RefPtr<RegisterID> m_profileHookRegister;
80 ArgumentsNode* m_argumentsNode;
93a37866 81 Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
81345200 82 unsigned m_padding;
14957cd0 83 };
9dae56ea
A
84
85 struct FinallyContext {
6fe7ccc8 86 StatementNode* finallyBlock;
ed1e77d3
A
87 RegisterID* iterator;
88 ThrowableExpressionData* enumerationNode;
6fe7ccc8
A
89 unsigned scopeContextStackSize;
90 unsigned switchContextStackSize;
91 unsigned forInContextStackSize;
93a37866 92 unsigned tryContextStackSize;
6fe7ccc8
A
93 unsigned labelScopesSize;
94 int finallyDepth;
95 int dynamicScopeDepth;
9dae56ea
A
96 };
97
98 struct ControlFlowContext {
99 bool isFinallyBlock;
100 FinallyContext finallyContext;
101 };
102
ed1e77d3
A
103 class ForInContext {
104 public:
105 ForInContext(RegisterID* localRegister)
106 : m_localRegister(localRegister)
107 , m_isValid(true)
108 {
109 }
110
111 virtual ~ForInContext()
112 {
113 }
114
115 bool isValid() const { return m_isValid; }
116 void invalidate() { m_isValid = false; }
117
118 enum ForInContextType {
119 StructureForInContextType,
120 IndexedForInContextType
121 };
122 virtual ForInContextType type() const = 0;
123
124 RegisterID* local() const { return m_localRegister.get(); }
125
126 private:
127 RefPtr<RegisterID> m_localRegister;
128 bool m_isValid;
129 };
130
131 class StructureForInContext : public ForInContext {
132 public:
133 StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
134 : ForInContext(localRegister)
135 , m_indexRegister(indexRegister)
136 , m_propertyRegister(propertyRegister)
137 , m_enumeratorRegister(enumeratorRegister)
138 {
139 }
140
141 virtual ForInContextType type() const
142 {
143 return StructureForInContextType;
144 }
145
146 RegisterID* index() const { return m_indexRegister.get(); }
147 RegisterID* property() const { return m_propertyRegister.get(); }
148 RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
149
150 private:
151 RefPtr<RegisterID> m_indexRegister;
152 RefPtr<RegisterID> m_propertyRegister;
153 RefPtr<RegisterID> m_enumeratorRegister;
154 };
155
156 class IndexedForInContext : public ForInContext {
157 public:
158 IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
159 : ForInContext(localRegister)
160 , m_indexRegister(indexRegister)
161 {
162 }
163
164 virtual ForInContextType type() const
165 {
166 return IndexedForInContextType;
167 }
168
169 RegisterID* index() const { return m_indexRegister.get(); }
170
171 private:
172 RefPtr<RegisterID> m_indexRegister;
f9bf01c6
A
173 };
174
93a37866
A
175 struct TryData {
176 RefPtr<Label> target;
177 unsigned targetScopeDepth;
ed1e77d3 178 HandlerType handlerType;
93a37866
A
179 };
180
181 struct TryContext {
182 RefPtr<Label> start;
183 TryData* tryData;
184 };
185
ed1e77d3 186 class Variable {
93a37866 187 public:
ed1e77d3
A
188 enum VariableKind { NormalVariable, SpecialVariable };
189
190 Variable()
191 : m_offset()
192 , m_local(nullptr)
193 , m_attributes(0)
194 , m_kind(NormalVariable)
195 {
196 }
197
198 Variable(const Identifier& ident)
199 : m_ident(ident)
200 , m_local(nullptr)
81345200 201 , m_attributes(0)
ed1e77d3 202 , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable.
93a37866 203 {
93a37866 204 }
81345200 205
ed1e77d3
A
206 Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind)
207 : m_ident(ident)
208 , m_offset(offset)
209 , m_local(local)
81345200 210 , m_attributes(attributes)
ed1e77d3 211 , m_kind(kind)
93a37866 212 {
93a37866 213 }
93a37866 214
ed1e77d3
A
215 // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be
216 // a stack variable, a scoped variable in the local scope, or a variable captured in the
217 // direct arguments object.
218 bool isResolved() const { return !!m_offset; }
219
220 const Identifier& ident() const { return m_ident; }
81345200 221
ed1e77d3
A
222 VarOffset offset() const { return m_offset; }
223 bool isLocal() const { return m_offset.isStack(); }
224 RegisterID* local() const { return m_local; }
225
226 bool isReadOnly() const { return m_attributes & ReadOnly; }
227 bool isSpecial() const { return m_kind != NormalVariable; }
93a37866
A
228
229 private:
ed1e77d3
A
230 Identifier m_ident;
231 VarOffset m_offset;
81345200
A
232 RegisterID* m_local;
233 unsigned m_attributes;
ed1e77d3 234 VariableKind m_kind;
93a37866
A
235 };
236
81345200
A
237 struct TryRange {
238 RefPtr<Label> start;
239 RefPtr<Label> end;
240 TryData* tryData;
93a37866
A
241 };
242
ed1e77d3
A
243 enum ProfileTypeBytecodeFlag {
244 ProfileTypeBytecodePutToScope,
245 ProfileTypeBytecodeGetFromScope,
246 ProfileTypeBytecodePutToLocalScope,
247 ProfileTypeBytecodeGetFromLocalScope,
248 ProfileTypeBytecodeHasGlobalID,
249 ProfileTypeBytecodeDoesNotHaveGlobalID,
250 ProfileTypeBytecodeFunctionArgument,
251 ProfileTypeBytecodeFunctionReturnStatement
252 };
253
14957cd0
A
254 class BytecodeGenerator {
255 WTF_MAKE_FAST_ALLOCATED;
ed1e77d3 256 WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
9dae56ea
A
257 public:
258 typedef DeclarationStacks::VarStack VarStack;
259 typedef DeclarationStacks::FunctionStack FunctionStack;
260
81345200 261 BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode);
ed1e77d3 262 BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode);
81345200 263 BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode);
9dae56ea 264
6fe7ccc8
A
265 ~BytecodeGenerator();
266
93a37866 267 VM* vm() const { return m_vm; }
ed1e77d3 268 ParserArena& parserArena() const { return m_scopeNode->parserArena(); }
93a37866 269 const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
9dae56ea 270
ed1e77d3
A
271 bool isConstructor() const { return m_codeBlock->isConstructor(); }
272#if ENABLE(ES6_CLASS_SYNTAX)
273 ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
274#else
275 ConstructorKind constructorKind() const { return ConstructorKind::None; }
276#endif
14957cd0 277
93a37866 278 ParserError generate();
14957cd0 279
6fe7ccc8 280 bool isArgumentNumber(const Identifier&, int);
14957cd0 281
ed1e77d3
A
282 Variable variable(const Identifier&);
283
284 // Ignores the possibility of intervening scopes.
285 Variable variablePerSymbolTable(const Identifier&);
286
287 enum ExistingVariableMode { VerifyExisting, IgnoreExisting };
288 void createVariable(const Identifier&, VarKind, ConstantMode, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible.
81345200 289
9dae56ea
A
290 // Returns the register storing "this"
291 RegisterID* thisRegister() { return &m_thisRegister; }
ed1e77d3
A
292 RegisterID* argumentsRegister() { return m_argumentsRegister; }
293 RegisterID* newTarget() { return m_newTargetRegister; }
294
295 RegisterID* scopeRegister() { return m_scopeRegister; }
9dae56ea 296
9dae56ea
A
297 // Returns the next available temporary register. Registers returned by
298 // newTemporary require a modified form of reference counting: any
299 // register with a refcount of 0 is considered "available", meaning that
300 // the next instruction may overwrite it.
301 RegisterID* newTemporary();
302
9dae56ea
A
303 // The same as newTemporary(), but this function returns "suggestion" if
304 // "suggestion" is a temporary. This function is helpful in situations
305 // where you've put "suggestion" in a RefPtr, but you'd like to allow
306 // the next instruction to overwrite it anyway.
307 RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
308
309 // Functions for handling of dst register
310
311 RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
312
313 // Returns a place to write intermediate values of an operation
314 // which reuses dst if it is safe to do so.
315 RegisterID* tempDestination(RegisterID* dst)
316 {
317 return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
318 }
319
320 // Returns the place to write the final output of an operation.
321 RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
322 {
323 if (originalDst && originalDst != ignoredResult())
324 return originalDst;
325 ASSERT(tempDst != ignoredResult());
326 if (tempDst && tempDst->isTemporary())
327 return tempDst;
328 return newTemporary();
329 }
330
331 RegisterID* destinationForAssignResult(RegisterID* dst)
332 {
333 if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
334 return dst->isTemporary() ? dst : newTemporary();
335 return 0;
336 }
337
338 // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
339 RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
340 {
341 return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
342 }
343
93a37866 344 LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
9dae56ea
A
345 PassRefPtr<Label> newLabel();
346
93a37866 347 void emitNode(RegisterID* dst, StatementNode* n)
9dae56ea
A
348 {
349 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
350 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
81345200 351 if (!m_vm->isSafeToRecurse()) {
93a37866
A
352 emitThrowExpressionTooDeepException();
353 return;
354 }
355 n->emitBytecode(*this, dst);
9dae56ea
A
356 }
357
93a37866
A
358 void emitNode(StatementNode* n)
359 {
360 emitNode(0, n);
361 }
362
363 RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
364 {
365 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
366 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
81345200 367 if (!m_vm->isSafeToRecurse())
93a37866
A
368 return emitThrowExpressionTooDeepException();
369 return n->emitBytecode(*this, dst);
370 }
371
372 RegisterID* emitNode(ExpressionNode* n)
9dae56ea
A
373 {
374 return emitNode(0, n);
375 }
376
93a37866 377 void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
f9bf01c6 378 {
81345200 379 if (!m_vm->isSafeToRecurse()) {
f9bf01c6 380 emitThrowExpressionTooDeepException();
93a37866
A
381 return;
382 }
383
384 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
f9bf01c6
A
385 }
386
81345200
A
387 void emitExpressionInfo(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
388 {
389 ASSERT(divot.offset >= divotStart.offset);
390 ASSERT(divotEnd.offset >= divot.offset);
391
93a37866
A
392 int sourceOffset = m_scopeNode->source().startOffset();
393 unsigned firstLine = m_scopeNode->source().firstLine();
14957cd0 394
81345200
A
395 int divotOffset = divot.offset - sourceOffset;
396 int startOffset = divot.offset - divotStart.offset;
397 int endOffset = divotEnd.offset - divot.offset;
93a37866 398
81345200
A
399 unsigned line = divot.line;
400 ASSERT(line >= firstLine);
401 line -= firstLine;
402
403 int lineStart = divot.lineStartOffset;
93a37866
A
404 if (lineStart > sourceOffset)
405 lineStart -= sourceOffset;
406 else
407 lineStart = 0;
408
81345200
A
409 if (divotOffset < lineStart)
410 return;
411
412 unsigned column = divotOffset - lineStart;
93a37866
A
413
414 unsigned instructionOffset = instructions().size();
81345200
A
415 if (!m_isBuiltinFunction)
416 m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
9dae56ea
A
417 }
418
ed1e77d3 419
9dae56ea
A
420 ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
421 {
422 return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
423 }
424
425 ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
426 {
427 if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
428 PassRefPtr<RegisterID> dst = newTemporary();
429 emitNode(dst.get(), n);
430 return dst;
431 }
432
6fe7ccc8 433 return emitNode(n);
9dae56ea
A
434 }
435
ed1e77d3
A
436 void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
437 void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const Identifier*);
438
439 void emitProfileControlFlow(int);
440
9dae56ea 441 RegisterID* emitLoad(RegisterID* dst, bool);
9dae56ea 442 RegisterID* emitLoad(RegisterID* dst, const Identifier&);
ed1e77d3 443 RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
93a37866 444 RegisterID* emitLoadGlobalObject(RegisterID* dst);
9dae56ea
A
445
446 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
447 RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
448 RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
449 RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
450
93a37866 451 RegisterID* emitCreateThis(RegisterID* dst);
ed1e77d3 452 void emitTDZCheck(RegisterID* target);
9dae56ea 453 RegisterID* emitNewObject(RegisterID* dst);
14957cd0 454 RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
9dae56ea 455
ed1e77d3
A
456 RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode*);
457 RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index);
9dae56ea 458 RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
ed1e77d3 459 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name);
14957cd0 460 RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
9dae56ea 461
ed1e77d3
A
462 RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
463 RegisterID* emitMoveEmptyValue(RegisterID* dst);
9dae56ea
A
464 RegisterID* emitMove(RegisterID* dst, RegisterID* src);
465
93a37866 466 RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); }
ed1e77d3 467 RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); }
93a37866
A
468 RegisterID* emitInc(RegisterID* srcDst);
469 RegisterID* emitDec(RegisterID* srcDst);
9dae56ea 470
93a37866
A
471 void emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target);
472 RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
9dae56ea
A
473 RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
474 RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
475
93a37866 476 RegisterID* emitInitGlobalConst(const Identifier&, RegisterID* value);
9dae56ea 477
9dae56ea
A
478 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
479 RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
ed1e77d3 480 RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);
9dae56ea
A
481 RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
482 RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
14957cd0 483 RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
9dae56ea 484 RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
81345200 485 RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
9dae56ea
A
486 RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
487 RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
ed1e77d3
A
488
489 void emitPutGetterById(RegisterID* base, const Identifier& property, RegisterID* getter);
490 void emitPutSetterById(RegisterID* base, const Identifier& property, RegisterID* setter);
6fe7ccc8 491 void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
93a37866
A
492
493 ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
81345200
A
494 RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
495 RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
496 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);
9dae56ea 497
ed1e77d3
A
498 enum PropertyDescriptorOption {
499 PropertyConfigurable = 1,
500 PropertyWritable = 1 << 1,
501 PropertyEnumerable = 1 << 2,
502 };
503 void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
504 RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
505
81345200 506 void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack);
ed1e77d3
A
507
508#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
509 RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
510#endif
511
9dae56ea
A
512 RegisterID* emitReturn(RegisterID* src);
513 RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
514
81345200 515 RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
ba379fdc
A
516 RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
517 void emitToPrimitive(RegisterID* dst, RegisterID* src);
9dae56ea 518
81345200 519 ResolveType resolveType();
ed1e77d3
A
520 RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&);
521 RegisterID* emitResolveScope(RegisterID* dst, const Variable&);
522 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable&, ResolveMode);
523 RegisterID* emitPutToScope(RegisterID* scope, const Variable&, RegisterID* value, ResolveMode);
524 RegisterID* initializeVariable(const Variable&, RegisterID* value);
81345200 525
9dae56ea 526 PassRefPtr<Label> emitLabel(Label*);
6fe7ccc8 527 void emitLoopHint();
9dae56ea
A
528 PassRefPtr<Label> emitJump(Label* target);
529 PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
530 PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
ba379fdc
A
531 PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
532 PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
ed1e77d3 533 void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
9dae56ea 534
ed1e77d3
A
535 RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
536 RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
537 RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
538 RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
539 RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
540 RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
541 RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
542 RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
543 RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
544 RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
545
546 RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
547 RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
548
549 RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node);
550 void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node);
9dae56ea 551
93a37866
A
552 void emitReadOnlyExceptionIfNeeded();
553
554 // Start a try block. 'start' must have been emitted.
555 TryData* pushTry(Label* start);
556 // End a try block. 'end' must have been emitted.
ed1e77d3 557 void popTryAndEmitCatch(TryData*, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType);
93a37866 558
14957cd0
A
559 void emitThrow(RegisterID* exc)
560 {
561 m_usesExceptions = true;
562 emitUnaryNoDstOp(op_throw, exc);
563 }
564
93a37866 565 void emitThrowReferenceError(const String& message);
ed1e77d3 566 void emitThrowTypeError(const String& message);
14957cd0 567
ed1e77d3
A
568 void emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
569 void emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
9dae56ea 570
ed1e77d3
A
571 void emitGetScope();
572 RegisterID* emitPushWithScope(RegisterID* dst, RegisterID* scope);
573 void emitPopScope(RegisterID* srcDst);
9dae56ea 574
81345200 575 void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
9dae56ea 576
81345200 577 int scopeDepth() { return m_localScopeDepth + m_finallyDepth; }
9dae56ea
A
578 bool hasFinaliser() { return m_finallyDepth != 0; }
579
6fe7ccc8 580 void pushFinallyContext(StatementNode* finallyBlock);
9dae56ea 581 void popFinallyContext();
ed1e77d3
A
582 void pushIteratorCloseContext(RegisterID* iterator, ThrowableExpressionData* enumerationNode);
583 void popIteratorCloseContext();
9dae56ea 584
ed1e77d3
A
585 void pushIndexedForInScope(RegisterID* local, RegisterID* index);
586 void popIndexedForInScope(RegisterID* local);
587 void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
588 void popStructureForInScope(RegisterID* local);
589 void invalidateForInContextForLocal(RegisterID* local);
f9bf01c6 590
81345200
A
591 LabelScopePtr breakTarget(const Identifier&);
592 LabelScopePtr continueTarget(const Identifier&);
9dae56ea
A
593
594 void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
595 void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
596
597 CodeType codeType() const { return m_codeType; }
598
14957cd0 599 bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
93a37866 600 bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
14957cd0
A
601
602 bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
81345200
A
603
604 bool isBuiltinFunction() const { return m_isBuiltinFunction; }
ed1e77d3
A
605
606 OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
607
9dae56ea 608 private:
ed1e77d3
A
609 Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&);
610
9dae56ea 611 void emitOpcode(OpcodeID);
93a37866
A
612 UnlinkedArrayAllocationProfile newArrayAllocationProfile();
613 UnlinkedObjectAllocationProfile newObjectAllocationProfile();
614 UnlinkedArrayProfile newArrayProfile();
615 UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
616 int kill(RegisterID* dst)
617 {
618 int index = dst->index();
619 m_staticPropertyAnalyzer.kill(index);
620 return index;
621 }
622
9dae56ea
A
623 void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
624 void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
4e4e5a6f
A
625 ALWAYS_INLINE void rewindBinaryOp();
626 ALWAYS_INLINE void rewindUnaryOp();
9dae56ea 627
ed1e77d3
A
628 void allocateAndEmitScope();
629 void emitComplexPopScopes(RegisterID*, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
9dae56ea 630
ba379fdc 631 typedef HashMap<double, JSValue> NumberMap;
ed1e77d3
A
632 typedef HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
633 typedef HashMap<TemplateRegistryKey, JSTemplateRegistryKey*> TemplateRegistryKeyMap;
93a37866
A
634
635 // Helper for emitCall() and emitConstruct(). This works because the set of
636 // expected functions have identical behavior for both call and construct
637 // (i.e. "Object()" is identical to "new Object()").
638 ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
9dae56ea 639
81345200 640 RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
14957cd0 641
9dae56ea
A
642 RegisterID* newRegister();
643
ed1e77d3 644 // Adds an anonymous local var slot. To give this slot a name, add it to symbolTable().
14957cd0
A
645 RegisterID* addVar()
646 {
647 ++m_codeBlock->m_numVars;
ed1e77d3
A
648 RegisterID* result = newRegister();
649 ASSERT(VirtualRegister(result->index()).toLocal() == m_codeBlock->m_numVars - 1);
650 result->ref(); // We should never free this slot.
651 return result;
14957cd0 652 }
9dae56ea 653
ed1e77d3
A
654 // Initializes the stack form the parameter; does nothing for the symbol table.
655 RegisterID* initializeNextParameter();
656 UniquedStringImpl* visibleNameForParameter(DestructuringPatternNode*);
657
658 RegisterID& registerFor(VirtualRegister reg)
9dae56ea 659 {
ed1e77d3
A
660 if (reg.isLocal())
661 return m_calleeRegisters[reg.toLocal()];
9dae56ea 662
ed1e77d3 663 if (reg.offset() == JSStack::Callee)
93a37866
A
664 return m_calleeRegister;
665
6fe7ccc8 666 ASSERT(m_parameters.size());
ed1e77d3 667 return m_parameters[reg.toArgument()];
9dae56ea
A
668 }
669
ed1e77d3 670 bool hasConstant(const Identifier&) const;
9dae56ea 671 unsigned addConstant(const Identifier&);
ed1e77d3 672 RegisterID* addConstantValue(JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
93a37866 673 RegisterID* addConstantEmptyValue();
9dae56ea
A
674 unsigned addRegExp(RegExp*);
675
14957cd0
A
676 unsigned addConstantBuffer(unsigned length);
677
93a37866 678 UnlinkedFunctionExecutable* makeFunction(FunctionBodyNode* body)
f9bf01c6 679 {
81345200 680 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), body, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction);
f9bf01c6
A
681 }
682
ed1e77d3 683 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);
81345200 684 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);
ed1e77d3 685
93a37866 686 public:
14957cd0 687 JSString* addStringConstant(const Identifier&);
ed1e77d3 688 JSTemplateRegistryKey* addTemplateRegistryKeyConstant(const TemplateRegistryKey&);
14957cd0 689
93a37866 690 Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
14957cd0 691
81345200 692 SymbolTable& symbolTable() { return *m_symbolTable; }
9dae56ea 693
6fe7ccc8
A
694 bool shouldOptimizeLocals()
695 {
81345200 696 if (m_codeType != FunctionCode)
6fe7ccc8
A
697 return false;
698
81345200 699 if (m_localScopeDepth)
6fe7ccc8
A
700 return false;
701
702 return true;
703 }
704
705 bool canOptimizeNonLocals()
706 {
81345200 707 if (m_localScopeDepth)
6fe7ccc8
A
708 return false;
709
710 if (m_codeType == EvalCode)
711 return false;
712
713 if (m_codeType == FunctionCode && m_codeBlock->usesEval())
714 return false;
715
716 return true;
717 }
9dae56ea
A
718
719 RegisterID* emitThrowExpressionTooDeepException();
720
ed1e77d3 721 private:
93a37866 722 Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
ba379fdc 723
9dae56ea
A
724 bool m_shouldEmitDebugHooks;
725 bool m_shouldEmitProfileHooks;
726
ed1e77d3 727 SymbolTable* m_symbolTable { nullptr };
9dae56ea 728
ed1e77d3 729 ScopeNode* const m_scopeNode;
93a37866 730 Strong<UnlinkedCodeBlock> m_codeBlock;
9dae56ea 731
ba379fdc
A
732 // Some of these objects keep pointers to one another. They are arranged
733 // to ensure a sane destruction order that avoids references to freed memory.
ed1e77d3 734 HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> m_functions;
9dae56ea
A
735 RegisterID m_ignoredResultRegister;
736 RegisterID m_thisRegister;
93a37866 737 RegisterID m_calleeRegister;
ed1e77d3
A
738 RegisterID* m_scopeRegister { nullptr };
739 RegisterID* m_argumentsRegister { nullptr };
740 RegisterID* m_lexicalEnvironmentRegister { nullptr };
741 RegisterID* m_emptyValueRegister { nullptr };
742 RegisterID* m_globalObjectRegister { nullptr };
743 RegisterID* m_newTargetRegister { nullptr };
744 RegisterID* m_linkTimeConstantRegisters[LinkTimeConstantCount];
745
f9bf01c6
A
746 SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
747 SegmentedVector<RegisterID, 32> m_calleeRegisters;
748 SegmentedVector<RegisterID, 32> m_parameters;
f9bf01c6 749 SegmentedVector<Label, 32> m_labels;
93a37866 750 LabelScopeStore m_labelScopes;
ed1e77d3
A
751 int m_finallyDepth { 0 };
752 int m_localScopeDepth { 0 };
753 const CodeType m_codeType;
9dae56ea 754
93a37866 755 Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
9dae56ea 756 Vector<SwitchInfo> m_switchContextStack;
ed1e77d3 757 Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
93a37866 758 Vector<TryContext> m_tryContextStack;
ed1e77d3
A
759 Vector<std::pair<RefPtr<RegisterID>, const DestructuringPatternNode*>> m_destructuringParameters;
760 enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
761 Vector<std::pair<FunctionBodyNode*, FunctionVariableType>> m_functionsToInitialize;
762 bool m_needToInitializeArguments { false };
93a37866
A
763
764 Vector<TryRange> m_tryRanges;
765 SegmentedVector<TryData, 8> m_tryData;
9dae56ea 766
ed1e77d3 767 int m_nextConstantOffset { 0 };
9dae56ea 768
14957cd0
A
769 typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
770 FunctionOffsetMap m_functionOffsets;
771
9dae56ea
A
772 // Constant pool
773 IdentifierMap m_identifierMap;
ed1e77d3
A
774
775 typedef HashMap<EncodedJSValueWithRepresentation, unsigned, EncodedJSValueWithRepresentationHash, EncodedJSValueWithRepresentationHashTraits> JSValueMap;
9dae56ea 776 JSValueMap m_jsValueMap;
9dae56ea 777 IdentifierStringMap m_stringMap;
ed1e77d3 778 TemplateRegistryKeyMap m_templateRegistryKeyMap;
9dae56ea 779
ed1e77d3 780 StaticPropertyAnalyzer m_staticPropertyAnalyzer { &m_instructions };
93a37866
A
781
782 VM* m_vm;
9dae56ea 783
ed1e77d3 784 OpcodeID m_lastOpcodeID = op_end;
14957cd0 785#ifndef NDEBUG
ed1e77d3 786 size_t m_lastOpcodePosition { 0 };
14957cd0 787#endif
9dae56ea 788
ed1e77d3
A
789 bool m_usesExceptions { false };
790 bool m_expressionTooDeep { false };
791 bool m_isBuiltinFunction { false };
b80e6193 792 };
93a37866 793
9dae56ea
A
794}
795
796#endif // BytecodeGenerator_h