blob: 3adc510abc0ae7c3ad252b675cb18b99dc7d2b63 [file] [log] [blame]
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00001/*
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002 * Copyright (C) 2008, 2009, 2012-2015 Apple Inc. All rights reserved.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00003 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +00004 * Copyright (C) 2012 Igalia, S.L.
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +00005 *
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.
mjs@apple.com92047332014-03-15 04:08:27 +000015 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000016 * 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
ggaren@apple.com8e06f202008-11-15 21:05:23 +000031#ifndef BytecodeGenerator_h
32#define BytecodeGenerator_h
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000033
34#include "CodeBlock.h"
eric@webkit.org3979f2d2012-03-07 08:50:54 +000035#include <wtf/HashTraits.h>
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000036#include "Instruction.h"
ggaren@apple.com2efe3de2008-11-17 16:18:13 +000037#include "Label.h"
ggaren@apple.com4dbab802008-10-31 19:59:08 +000038#include "LabelScope.h"
ggaren@apple.com901a8a22008-11-17 20:57:18 +000039#include "Interpreter.h"
fpizlo@apple.combb8aa752013-02-18 06:28:54 +000040#include "ParserError.h"
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000041#include "RegisterID.h"
weinig@apple.coma963b962008-06-05 05:36:55 +000042#include "SymbolTable.h"
cwzwarich@webkit.orga691b5a2008-10-31 05:56:58 +000043#include "Debugger.h"
cwzwarich@webkit.org3ff0e6a2008-11-07 00:18:07 +000044#include "Nodes.h"
ggaren@apple.comc862eac2013-01-29 05:48:01 +000045#include "StaticPropertyAnalyzer.h"
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +000046#include "TemplateRegistryKey.h"
oliver@apple.comf0c01b82012-11-07 00:13:54 +000047#include "UnlinkedCodeBlock.h"
oliver@apple.com72f8a822013-10-17 01:02:34 +000048
49#include <functional>
50
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000051#include <wtf/PassRefPtr.h>
ddkilzer@apple.com0a028aa2009-06-20 13:14:41 +000052#include <wtf/SegmentedVector.h>
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000053#include <wtf/Vector.h>
54
oliver@apple.com72f8a822013-10-17 01:02:34 +000055
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000056namespace JSC {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000057
58 class Identifier;
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +000059 class JSTemplateRegistryKey;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000060
fpizlo@apple.com4500e352012-10-17 21:39:11 +000061 enum ExpectedFunction {
62 NoExpectedFunction,
63 ExpectObjectConstructor,
64 ExpectArrayConstructor
65 };
66
barraclough@apple.com9835d1d2010-06-01 23:13:23 +000067 class CallArguments {
68 public:
oliver@apple.com20a9bf02013-10-04 20:35:24 +000069 CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +000070
71 RegisterID* thisRegister() { return m_argv[0].get(); }
72 RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +000073 unsigned stackOffset() { return -m_argv[0]->index() + JSStack::CallFrameHeaderSize; }
74 unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +000075 RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
barraclough@apple.com9835d1d2010-06-01 23:13:23 +000076 ArgumentsNode* argumentsNode() { return m_argumentsNode; }
77
78 private:
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +000079 RefPtr<RegisterID> m_profileHookRegister;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +000080 ArgumentsNode* m_argumentsNode;
oliver@apple.com4e3f9652013-04-08 04:14:50 +000081 Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +000082 unsigned m_padding;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +000083 };
84
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000085 struct FinallyContext {
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +000086 StatementNode* finallyBlock;
utatane.tea@gmail.combc074492015-04-01 09:36:15 +000087 RegisterID* iterator;
88 ThrowableExpressionData* enumerationNode;
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +000089 unsigned scopeContextStackSize;
90 unsigned switchContextStackSize;
91 unsigned forInContextStackSize;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +000092 unsigned tryContextStackSize;
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +000093 unsigned labelScopesSize;
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +000094 unsigned symbolTableStackSize;
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +000095 int finallyDepth;
96 int dynamicScopeDepth;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000097 };
weinig@apple.coma963b962008-06-05 05:36:55 +000098
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +000099 struct ControlFlowContext {
100 bool isFinallyBlock;
101 FinallyContext finallyContext;
102 };
weinig@apple.coma963b962008-06-05 05:36:55 +0000103
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000104 class ForInContext {
105 public:
fpizlo@apple.comcaf35052014-08-20 02:38:46 +0000106 ForInContext(RegisterID* localRegister)
107 : m_localRegister(localRegister)
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000108 , m_isValid(true)
109 {
110 }
111
112 virtual ~ForInContext()
113 {
114 }
115
116 bool isValid() const { return m_isValid; }
117 void invalidate() { m_isValid = false; }
118
119 enum ForInContextType {
120 StructureForInContextType,
121 IndexedForInContextType
122 };
123 virtual ForInContextType type() const = 0;
124
125 RegisterID* local() const { return m_localRegister.get(); }
126
127 private:
128 RefPtr<RegisterID> m_localRegister;
129 bool m_isValid;
130 };
131
132 class StructureForInContext : public ForInContext {
133 public:
fpizlo@apple.comcaf35052014-08-20 02:38:46 +0000134 StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
135 : ForInContext(localRegister)
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000136 , m_indexRegister(indexRegister)
137 , m_propertyRegister(propertyRegister)
138 , m_enumeratorRegister(enumeratorRegister)
139 {
140 }
141
142 virtual ForInContextType type() const
143 {
144 return StructureForInContextType;
145 }
146
147 RegisterID* index() const { return m_indexRegister.get(); }
148 RegisterID* property() const { return m_propertyRegister.get(); }
149 RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
150
151 private:
152 RefPtr<RegisterID> m_indexRegister;
153 RefPtr<RegisterID> m_propertyRegister;
154 RefPtr<RegisterID> m_enumeratorRegister;
155 };
156
157 class IndexedForInContext : public ForInContext {
158 public:
fpizlo@apple.comcaf35052014-08-20 02:38:46 +0000159 IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
160 : ForInContext(localRegister)
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000161 , m_indexRegister(indexRegister)
162 {
163 }
164
165 virtual ForInContextType type() const
166 {
167 return IndexedForInContextType;
168 }
169
170 RegisterID* index() const { return m_indexRegister.get(); }
171
172 private:
173 RefPtr<RegisterID> m_indexRegister;
oliver@apple.com0a4803c2009-10-29 01:25:02 +0000174 };
175
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000176 struct TryData {
177 RefPtr<Label> target;
178 unsigned targetScopeDepth;
mark.lam@apple.com1559ba92015-06-01 23:22:22 +0000179 HandlerType handlerType;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000180 };
181
182 struct TryContext {
183 RefPtr<Label> start;
184 TryData* tryData;
185 };
186
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000187 class Variable {
oliver@apple.com58c86752013-07-25 04:02:40 +0000188 public:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000189 enum VariableKind { NormalVariable, SpecialVariable };
190
191 Variable()
192 : m_offset()
193 , m_local(nullptr)
oliver@apple.com58c86752013-07-25 04:02:40 +0000194 , m_attributes(0)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000195 , m_kind(NormalVariable)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000196 , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000197 , m_isLexicallyScoped(false)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000198 {
199 }
200
201 Variable(const Identifier& ident)
202 : m_ident(ident)
203 , m_local(nullptr)
204 , m_attributes(0)
205 , m_kind(NormalVariable) // This is somewhat meaningless here for this kind of Variable.
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000206 , m_symbolTableConstantIndex(0) // This is meaningless here for this kind of Variable.
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000207 , m_isLexicallyScoped(false)
oliver@apple.com58c86752013-07-25 04:02:40 +0000208 {
209 }
210
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000211 Variable(const Identifier& ident, VarOffset offset, RegisterID* local, unsigned attributes, VariableKind kind, int symbolTableConstantIndex, bool isLexicallyScoped)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000212 : m_ident(ident)
213 , m_offset(offset)
214 , m_local(local)
oliver@apple.com58c86752013-07-25 04:02:40 +0000215 , m_attributes(attributes)
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000216 , m_kind(kind)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000217 , m_symbolTableConstantIndex(symbolTableConstantIndex)
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000218 , m_isLexicallyScoped(isLexicallyScoped)
oliver@apple.com58c86752013-07-25 04:02:40 +0000219 {
220 }
221
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000222 // If it's unset, then it is a non-locally-scoped variable. If it is set, then it could be
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000223 // a stack variable, a scoped variable in a local scope, or a variable captured in the
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000224 // direct arguments object.
225 bool isResolved() const { return !!m_offset; }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000226 int symbolTableConstantIndex() const { ASSERT(isResolved() && !isSpecial()); return m_symbolTableConstantIndex; }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000227
228 const Identifier& ident() const { return m_ident; }
229
230 VarOffset offset() const { return m_offset; }
231 bool isLocal() const { return m_offset.isStack(); }
232 RegisterID* local() const { return m_local; }
oliver@apple.com58c86752013-07-25 04:02:40 +0000233
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000234 bool isReadOnly() const { return m_attributes & ReadOnly; }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000235 bool isSpecial() const { return m_kind != NormalVariable; }
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000236 bool isConst() const { return isReadOnly() && m_isLexicallyScoped; }
oliver@apple.com58c86752013-07-25 04:02:40 +0000237
238 private:
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000239 Identifier m_ident;
240 VarOffset m_offset;
oliver@apple.com58c86752013-07-25 04:02:40 +0000241 RegisterID* m_local;
242 unsigned m_attributes;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000243 VariableKind m_kind;
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000244 int m_symbolTableConstantIndex;
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000245 bool m_isLexicallyScoped;
oliver@apple.com58c86752013-07-25 04:02:40 +0000246 };
247
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000248 struct TryRange {
249 RefPtr<Label> start;
250 RefPtr<Label> end;
251 TryData* tryData;
252 };
253
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000254 enum ProfileTypeBytecodeFlag {
255 ProfileTypeBytecodePutToScope,
256 ProfileTypeBytecodeGetFromScope,
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000257 ProfileTypeBytecodePutToLocalScope,
258 ProfileTypeBytecodeGetFromLocalScope,
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000259 ProfileTypeBytecodeHasGlobalID,
260 ProfileTypeBytecodeDoesNotHaveGlobalID,
261 ProfileTypeBytecodeFunctionArgument,
262 ProfileTypeBytecodeFunctionReturnStatement
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000263 };
264
ossy@webkit.org95c1bc42011-01-20 16:30:54 +0000265 class BytecodeGenerator {
266 WTF_MAKE_FAST_ALLOCATED;
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000267 WTF_MAKE_NONCOPYABLE(BytecodeGenerator);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000268 public:
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000269 typedef DeclarationStacks::FunctionStack FunctionStack;
weinig@apple.coma963b962008-06-05 05:36:55 +0000270
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000271 BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
272 BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
273 BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode, const VariableEnvironment*);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000274
oliver@apple.com780d3cc2011-10-25 00:21:29 +0000275 ~BytecodeGenerator();
276
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000277 VM* vm() const { return m_vm; }
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000278 ParserArena& parserArena() const { return m_scopeNode->parserArena(); }
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000279 const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000280
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000281 bool isConstructor() const { return m_codeBlock->isConstructor(); }
282#if ENABLE(ES6_CLASS_SYNTAX)
rniwa@webkit.orge6f83492015-03-13 23:01:51 +0000283 ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000284#else
rniwa@webkit.orge6f83492015-03-13 23:01:51 +0000285 ConstructorKind constructorKind() const { return ConstructorKind::None; }
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000286#endif
barraclough@apple.comfdaf8dc2010-05-20 04:57:20 +0000287
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000288 ParserError generate();
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000289
ggaren@apple.com50c5ac22011-11-14 23:16:27 +0000290 bool isArgumentNumber(const Identifier&, int);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +0000291
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000292 Variable variable(const Identifier&);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000293
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000294 enum ExistingVariableMode { VerifyExisting, IgnoreExisting };
saambarati1@gmail.com3321f092015-07-20 21:16:41 +0000295 void createVariable(const Identifier&, VarKind, SymbolTable*, ExistingVariableMode = VerifyExisting); // Creates the variable, or asserts that the already-created variable is sufficiently compatible.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000296
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000297 // Returns the register storing "this"
ggaren@apple.com873cb422008-06-02 20:45:13 +0000298 RegisterID* thisRegister() { return &m_thisRegister; }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000299 RegisterID* argumentsRegister() { return m_argumentsRegister; }
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000300 RegisterID* newTarget() { return m_newTargetRegister; }
301
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +0000302 RegisterID* scopeRegister() { return m_scopeRegister; }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000303
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000304 // Returns the next available temporary register. Registers returned by
305 // newTemporary require a modified form of reference counting: any
306 // register with a refcount of 0 is considered "available", meaning that
307 // the next instruction may overwrite it.
308 RegisterID* newTemporary();
309
310 // The same as newTemporary(), but this function returns "suggestion" if
311 // "suggestion" is a temporary. This function is helpful in situations
312 // where you've put "suggestion" in a RefPtr, but you'd like to allow
313 // the next instruction to overwrite it anyway.
314 RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
315
316 // Functions for handling of dst register
317
cwzwarich@webkit.orgd47b49a2008-12-03 06:13:58 +0000318 RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
319
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000320 // This will be allocated in the temporary region of registers, but it will
321 // not be marked as a temporary. This will ensure that finalDestination() does
322 // not overwrite a block scope variable that it mistakes as a temporary. These
323 // registers can be (and are) reclaimed when the lexical scope they belong to
324 // is no longer on the symbol table stack.
325 RegisterID* newBlockScopeVariable();
326
darin@apple.com87255fc2008-06-28 16:03:11 +0000327 // Returns a place to write intermediate values of an operation
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000328 // which reuses dst if it is safe to do so.
darin@apple.com87255fc2008-06-28 16:03:11 +0000329 RegisterID* tempDestination(RegisterID* dst)
330 {
331 return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
332 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000333
334 // Returns the place to write the final output of an operation.
weinig@apple.coma963b962008-06-05 05:36:55 +0000335 RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
336 {
darin@apple.com87255fc2008-06-28 16:03:11 +0000337 if (originalDst && originalDst != ignoredResult())
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000338 return originalDst;
darin@apple.com87255fc2008-06-28 16:03:11 +0000339 ASSERT(tempDst != ignoredResult());
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000340 if (tempDst && tempDst->isTemporary())
341 return tempDst;
weinig@apple.coma963b962008-06-05 05:36:55 +0000342 return newTemporary();
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000343 }
weinig@apple.coma963b962008-06-05 05:36:55 +0000344
345 RegisterID* destinationForAssignResult(RegisterID* dst)
346 {
weinig@apple.comcb26d812008-12-06 22:01:05 +0000347 if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000348 return dst->isTemporary() ? dst : newTemporary();
349 return 0;
350 }
351
darin@apple.com87255fc2008-06-28 16:03:11 +0000352 // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
353 RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
354 {
355 return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
356 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000357
oliver@apple.com6a976452013-03-11 21:02:39 +0000358 LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
ggaren@apple.comfae5b802008-11-15 22:33:58 +0000359 PassRefPtr<Label> newLabel();
weinig@apple.coma963b962008-06-05 05:36:55 +0000360
ggaren@apple.comd786e6b2013-04-04 23:16:20 +0000361 void emitNode(RegisterID* dst, StatementNode* n)
weinig@apple.coma963b962008-06-05 05:36:55 +0000362 {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000363 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
darin@apple.com87255fc2008-06-28 16:03:11 +0000364 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
mark.lam@apple.com30721252013-11-21 05:29:42 +0000365 if (!m_vm->isSafeToRecurse()) {
ggaren@apple.comd786e6b2013-04-04 23:16:20 +0000366 emitThrowExpressionTooDeepException();
367 return;
368 }
369 n->emitBytecode(*this, dst);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000370 }
371
ggaren@apple.comd786e6b2013-04-04 23:16:20 +0000372 void emitNode(StatementNode* n)
373 {
374 emitNode(0, n);
375 }
376
377 RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
378 {
379 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
380 ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
mark.lam@apple.com30721252013-11-21 05:29:42 +0000381 if (!m_vm->isSafeToRecurse())
ggaren@apple.comd786e6b2013-04-04 23:16:20 +0000382 return emitThrowExpressionTooDeepException();
383 return n->emitBytecode(*this, dst);
384 }
385
386 RegisterID* emitNode(ExpressionNode* n)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000387 {
388 return emitNode(0, n);
389 }
390
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +0000391 void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.coma46c49c2009-12-06 09:42:03 +0000392 {
mark.lam@apple.com30721252013-11-21 05:29:42 +0000393 if (!m_vm->isSafeToRecurse()) {
mjs@apple.coma46c49c2009-12-06 09:42:03 +0000394 emitThrowExpressionTooDeepException();
ggaren@apple.comd786e6b2013-04-04 23:16:20 +0000395 return;
396 }
397
398 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
mjs@apple.coma46c49c2009-12-06 09:42:03 +0000399 }
400
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000401 void emitExpressionInfo(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
402 {
403 ASSERT(divot.offset >= divotStart.offset);
404 ASSERT(divotEnd.offset >= divot.offset);
405
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000406 int sourceOffset = m_scopeNode->source().startOffset();
407 unsigned firstLine = m_scopeNode->source().firstLine();
408
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000409 int divotOffset = divot.offset - sourceOffset;
410 int startOffset = divot.offset - divotStart.offset;
411 int endOffset = divotEnd.offset - divot.offset;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000412
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000413 unsigned line = divot.line;
414 ASSERT(line >= firstLine);
415 line -= firstLine;
416
417 int lineStart = divot.lineStartOffset;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000418 if (lineStart > sourceOffset)
419 lineStart -= sourceOffset;
420 else
421 lineStart = 0;
oliver@apple.comd055db62013-10-02 19:11:04 +0000422
423 if (divotOffset < lineStart)
424 return;
425
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000426 unsigned column = divotOffset - lineStart;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000427
428 unsigned instructionOffset = instructions().size();
oliver@apple.com4cbc7012014-02-14 23:29:31 +0000429 if (!m_isBuiltinFunction)
430 m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
oliver@apple.com90b88ae2008-07-19 01:44:24 +0000431 }
cwzwarich@webkit.org2ead1b32008-12-12 22:48:53 +0000432
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000433
cwzwarich@webkit.org29477592008-06-15 05:24:21 +0000434 ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000435 {
weinig@apple.comcb26d812008-12-06 22:01:05 +0000436 return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000437 }
438
cwzwarich@webkit.org29477592008-06-15 05:24:21 +0000439 ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000440 {
cwzwarich@webkit.org29477592008-06-15 05:24:21 +0000441 if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000442 PassRefPtr<RegisterID> dst = newTemporary();
443 emitNode(dst.get(), n);
444 return dst;
445 }
weinig@apple.coma963b962008-06-05 05:36:55 +0000446
ggaren@apple.combcf06d32012-01-12 00:14:42 +0000447 return emitNode(n);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000448 }
449
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000450 void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
451 void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const Identifier*);
fpizlo@apple.com3378c482014-07-27 23:14:40 +0000452
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +0000453 void emitProfileControlFlow(int);
454
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000455 RegisterID* emitLoad(RegisterID* dst, bool);
darin@apple.coma372f0a2008-09-21 20:35:20 +0000456 RegisterID* emitLoad(RegisterID* dst, const Identifier&);
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000457 RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
oliver@apple.com75f804e2013-03-07 00:25:20 +0000458 RegisterID* emitLoadGlobalObject(RegisterID* dst);
weinig@apple.coma963b962008-06-05 05:36:55 +0000459
ggaren@apple.com1fd42372008-12-02 21:52:24 +0000460 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
ggaren@apple.com47d3f052008-11-15 21:37:49 +0000461 RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
462 RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
463 RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
mjs@apple.com33b75782008-06-15 23:59:24 +0000464
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000465 RegisterID* emitCreateThis(RegisterID* dst);
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000466 void emitTDZCheck(RegisterID* target);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000467 bool needsTDZCheck(const Variable&);
468 void emitTDZCheckIfNecessary(const Variable&, RegisterID* target, RegisterID* scope);
469 void liftTDZCheckIfPossible(const Variable&);
weinig@apple.com3412bb42008-09-01 21:22:54 +0000470 RegisterID* emitNewObject(RegisterID* dst);
oliver@apple.coma991d692011-06-14 23:39:25 +0000471 RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000472
oliver@apple.com47252262014-10-07 18:57:57 +0000473 RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode*);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000474 RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000475 RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +0000476 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name);
oliver@apple.com5652af72011-05-26 01:12:46 +0000477 RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000478
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000479 RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
joepeck@webkit.org408f48152015-03-27 02:55:57 +0000480 RegisterID* emitMoveEmptyValue(RegisterID* dst);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000481 RegisterID* emitMove(RegisterID* dst, RegisterID* src);
482
ggaren@apple.comf3036112013-04-27 23:14:04 +0000483 RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); }
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000484 RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000485 RegisterID* emitInc(RegisterID* srcDst);
486 RegisterID* emitDec(RegisterID* srcDst);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000487
barraclough@apple.comb46d57b42012-09-22 00:43:03 +0000488 void emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target);
barraclough@apple.com094dbd92012-09-22 01:18:54 +0000489 RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
ggaren@apple.com1fd42372008-12-02 21:52:24 +0000490 RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
barraclough@apple.comb8b15e22008-09-27 01:44:15 +0000491 RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000492
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000493 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
494 RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
joepeck@webkit.orga26e6e52015-03-06 21:31:27 +0000495 RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value, PropertyNode::PutType);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000496 RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
497 RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
oliver@apple.com74e00b02010-09-25 21:42:00 +0000498 RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000499 RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
oliver@apple.come050d642013-10-19 00:09:28 +0000500 RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000501 RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
502 RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000503
504 void emitPutGetterById(RegisterID* base, const Identifier& property, RegisterID* getter);
505 void emitPutSetterById(RegisterID* base, const Identifier& property, RegisterID* setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000506 void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000507
508 ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000509 RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
510 RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000511 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);
mjs@apple.com33b75782008-06-15 23:59:24 +0000512
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000513 enum PropertyDescriptorOption {
514 PropertyConfigurable = 1,
515 PropertyWritable = 1 << 1,
516 PropertyEnumerable = 1 << 2,
517 };
518 void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
519 RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&);
520
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000521 void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, VariableEnvironmentNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
ossy@webkit.orgdb391252015-05-21 12:29:43 +0000522
523#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000524 RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
ossy@webkit.orgdb391252015-05-21 12:29:43 +0000525#endif
526
cwzwarich@webkit.orga3b5f8a2008-10-06 06:00:58 +0000527 RegisterID* emitReturn(RegisterID* src);
mjs@apple.com33b75782008-06-15 23:59:24 +0000528 RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000529
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000530 RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
barraclough@apple.com14dc4e12009-05-07 00:06:07 +0000531 RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
532 void emitToPrimitive(RegisterID* dst, RegisterID* src);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000533
oliver@apple.com58c86752013-07-25 04:02:40 +0000534 ResolveType resolveType();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000535 RegisterID* emitResolveConstantLocal(RegisterID* dst, const Variable&);
536 RegisterID* emitResolveScope(RegisterID* dst, const Variable&);
537 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Variable&, ResolveMode);
538 RegisterID* emitPutToScope(RegisterID* scope, const Variable&, RegisterID* value, ResolveMode);
539 RegisterID* initializeVariable(const Variable&, RegisterID* value);
oliver@apple.com58c86752013-07-25 04:02:40 +0000540
ggaren@apple.comfae5b802008-11-15 22:33:58 +0000541 PassRefPtr<Label> emitLabel(Label*);
fpizlo@apple.coma71ab052011-09-13 05:35:53 +0000542 void emitLoopHint();
ggaren@apple.comfae5b802008-11-15 22:33:58 +0000543 PassRefPtr<Label> emitJump(Label* target);
544 PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
545 PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
oliver@apple.com6c106002009-03-28 03:50:39 +0000546 PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
oliver@apple.com65e286e2009-04-08 23:08:28 +0000547 PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
msaboff@apple.comc5b95392014-10-31 21:27:10 +0000548 void emitPopScopes(RegisterID* srcDst, int targetScopeDepth);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000549
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000550 RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
551 RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
552 RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
msaboff@apple.comb644c252015-03-24 10:05:21 +0000553 RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000554 RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
555 RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
556 RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
msaboff@apple.comb644c252015-03-24 10:05:21 +0000557 RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
558 RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000559 RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000560
utatane.tea@gmail.com4ddd5192015-03-05 14:57:17 +0000561 RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
562 RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
563
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +0000564 RegisterID* emitIteratorNext(RegisterID* dst, RegisterID* iterator, const ThrowableExpressionData* node);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +0000565 void emitIteratorClose(RegisterID* iterator, const ThrowableExpressionData* node);
utatane.tea@gmail.combc074492015-04-01 09:36:15 +0000566
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000567 bool emitReadOnlyExceptionIfNeeded(const Variable&);
ggaren@apple.com6e309822012-09-05 21:44:43 +0000568
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000569 // Start a try block. 'start' must have been emitted.
570 TryData* pushTry(Label* start);
571 // End a try block. 'end' must have been emitted.
mark.lam@apple.com6ed08272015-06-05 18:52:12 +0000572 void popTryAndEmitCatch(TryData*, RegisterID* exceptionRegister, RegisterID* thrownValueRegister, Label* end, HandlerType);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000573
oliver@apple.comfaeca002010-06-18 20:14:23 +0000574 void emitThrow(RegisterID* exc)
575 {
576 m_usesExceptions = true;
577 emitUnaryNoDstOp(op_throw, exc);
578 }
579
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000580 void emitThrowReferenceError(const String& message);
utatane.tea@gmail.com4ddd5192015-03-05 14:57:17 +0000581 void emitThrowTypeError(const String& message);
barraclough@apple.com4920ae92010-11-12 03:06:07 +0000582
msaboff@apple.comc5b95392014-10-31 21:27:10 +0000583 void emitPushFunctionNameScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
584 void emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes);
weinig@apple.coma963b962008-06-05 05:36:55 +0000585
msaboff@apple.com8b6b3412014-11-04 03:36:28 +0000586 void emitGetScope();
msaboff@apple.comc5b95392014-10-31 21:27:10 +0000587 RegisterID* emitPushWithScope(RegisterID* dst, RegisterID* scope);
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +0000588 void emitPopScope(RegisterID* dst, RegisterID* scope);
589 void emitPopWithOrCatchScope(RegisterID* srcDst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000590 RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
weinig@apple.coma963b962008-06-05 05:36:55 +0000591
mark.lam@apple.come72693d2013-09-24 23:52:57 +0000592 void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000593
oliver@apple.com05740a72009-03-18 07:24:39 +0000594 bool hasFinaliser() { return m_finallyDepth != 0; }
weinig@apple.coma963b962008-06-05 05:36:55 +0000595
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +0000596 void pushFinallyContext(StatementNode* finallyBlock);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000597 void popFinallyContext();
utatane.tea@gmail.combc074492015-04-01 09:36:15 +0000598 void pushIteratorCloseContext(RegisterID* iterator, ThrowableExpressionData* enumerationNode);
599 void popIteratorCloseContext();
ggaren@apple.com4dbab802008-10-31 19:59:08 +0000600
fpizlo@apple.comcaf35052014-08-20 02:38:46 +0000601 void pushIndexedForInScope(RegisterID* local, RegisterID* index);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000602 void popIndexedForInScope(RegisterID* local);
fpizlo@apple.comcaf35052014-08-20 02:38:46 +0000603 void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000604 void popStructureForInScope(RegisterID* local);
605 void invalidateForInContextForLocal(RegisterID* local);
oliver@apple.com0a4803c2009-10-29 01:25:02 +0000606
mark.lam@apple.comee88ae02014-03-21 23:48:39 +0000607 LabelScopePtr breakTarget(const Identifier&);
608 LabelScopePtr continueTarget(const Identifier&);
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000609
oliver@apple.com8007f462008-07-24 00:49:46 +0000610 void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
ggaren@apple.comfae5b802008-11-15 22:33:58 +0000611 void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
oliver@apple.com8007f462008-07-24 00:49:46 +0000612
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000613 CodeType codeType() const { return m_codeType; }
weinig@apple.coma963b962008-06-05 05:36:55 +0000614
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000615 bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000616 bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
oliver@apple.com59301852010-10-11 19:12:29 +0000617
618 bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
oliver@apple.comba848d12014-02-12 17:14:23 +0000619
620 bool isBuiltinFunction() const { return m_isBuiltinFunction; }
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +0000621
622 OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
623
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +0000624 private:
625 void pushLexicalScopeInternal(VariableEnvironment&, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult);
626 public:
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000627 void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr);
628 void popLexicalScope(VariableEnvironmentNode*);
629 void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +0000630 int labelScopeDepth() const;
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000631
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000632 private:
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000633 void reclaimFreeRegisters();
saambarati1@gmail.come4556722015-07-19 16:57:44 +0000634 Variable variableForLocalEntry(const Identifier&, const SymbolTableEntry&, int symbolTableConstantIndex, bool isLexicallyScoped);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000635
ggaren@apple.com47d3f052008-11-15 21:37:49 +0000636 void emitOpcode(OpcodeID);
fpizlo@apple.com75c91a72012-11-08 22:28:25 +0000637 UnlinkedArrayAllocationProfile newArrayAllocationProfile();
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000638 UnlinkedObjectAllocationProfile newObjectAllocationProfile();
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000639 UnlinkedArrayProfile newArrayProfile();
640 UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000641 int kill(RegisterID* dst)
642 {
643 int index = dst->index();
644 m_staticPropertyAnalyzer.kill(index);
645 return index;
646 }
647
cwzwarich@webkit.orgd195dd82008-06-11 19:48:15 +0000648 void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
oliver@apple.com15664942008-08-13 03:17:19 +0000649 void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
commit-queue@webkit.orgfcb562d2010-10-01 17:50:39 +0000650 ALWAYS_INLINE void rewindBinaryOp();
651 ALWAYS_INLINE void rewindUnaryOp();
cwzwarich@webkit.orgd195dd82008-06-11 19:48:15 +0000652
msaboff@apple.com5e62e3f2014-11-21 23:41:26 +0000653 void allocateAndEmitScope();
msaboff@apple.comc5b95392014-10-31 21:27:10 +0000654 void emitComplexPopScopes(RegisterID*, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
darin@apple.com5a494422008-10-18 23:08:12 +0000655
ggaren@apple.comdc067b62009-05-01 22:43:39 +0000656 typedef HashMap<double, JSValue> NumberMap;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000657 typedef HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000658 typedef HashMap<TemplateRegistryKey, JSTemplateRegistryKey*> TemplateRegistryKeyMap;
oliver@apple.com65e286e2009-04-08 23:08:28 +0000659
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000660 // Helper for emitCall() and emitConstruct(). This works because the set of
661 // expected functions have identical behavior for both call and construct
662 // (i.e. "Object()" is identical to "new Object()").
663 ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
664
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000665 RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
oliver@apple.comf61c9a12010-09-24 19:06:29 +0000666
ggaren@apple.com107bd0e2008-09-24 00:27:18 +0000667 RegisterID* newRegister();
weinig@apple.coma963b962008-06-05 05:36:55 +0000668
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000669 // Adds an anonymous local var slot. To give this slot a name, add it to symbolTable().
ggaren@apple.com83ce11c2010-05-19 05:10:11 +0000670 RegisterID* addVar()
671 {
672 ++m_codeBlock->m_numVars;
fpizlo@apple.come3b76872015-02-06 16:04:39 +0000673 RegisterID* result = newRegister();
674 ASSERT(VirtualRegister(result->index()).toLocal() == m_codeBlock->m_numVars - 1);
675 result->ref(); // We should never free this slot.
676 return result;
ggaren@apple.com83ce11c2010-05-19 05:10:11 +0000677 }
ggaren@apple.com82a62d02008-06-27 22:35:33 +0000678
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000679 // Initializes the stack form the parameter; does nothing for the symbol table.
680 RegisterID* initializeNextParameter();
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +0000681 UniquedStringImpl* visibleNameForParameter(DestructuringPatternNode*);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000682
683 RegisterID& registerFor(VirtualRegister reg)
ggaren@apple.com107bd0e2008-09-24 00:27:18 +0000684 {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000685 if (reg.isLocal())
686 return m_calleeRegisters[reg.toLocal()];
ggaren@apple.com107bd0e2008-09-24 00:27:18 +0000687
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000688 if (reg.offset() == JSStack::Callee)
ggaren@apple.comf8200082012-09-07 01:42:53 +0000689 return m_calleeRegister;
690
ggaren@apple.com99e9f3f2011-06-22 20:07:37 +0000691 ASSERT(m_parameters.size());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000692 return m_parameters[reg.toArgument()];
ggaren@apple.com107bd0e2008-09-24 00:27:18 +0000693 }
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000694
mark.lam@apple.comdd723072015-01-22 19:05:42 +0000695 bool hasConstant(const Identifier&) const;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000696 unsigned addConstant(const Identifier&);
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000697 RegisterID* addConstantValue(JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
ggaren@apple.com63a291e2012-09-10 20:23:50 +0000698 RegisterID* addConstantEmptyValue();
oliver@apple.com5652af72011-05-26 01:12:46 +0000699 unsigned addRegExp(RegExp*);
weinig@apple.coma963b962008-06-05 05:36:55 +0000700
oliver@apple.com673aed62011-06-28 20:21:37 +0000701 unsigned addConstantBuffer(unsigned length);
oliver@apple.coma991d692011-06-14 23:39:25 +0000702
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000703 UnlinkedFunctionExecutable* makeFunction(FunctionBodyNode* body)
704 {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000705 VariableEnvironment variablesUnderTDZ;
706 getVariablesUnderTDZ(variablesUnderTDZ);
utatane.tea@gmail.com54887a12015-07-23 02:36:20 +0000707
708 FunctionParseMode parseMode = body->parseMode();
709 ConstructAbility constructAbility = ConstructAbility::CanConstruct;
710 if (parseMode == GetterMode || parseMode == SetterMode || parseMode == ArrowFunctionMode || (parseMode == MethodMode && body->constructorKind() == ConstructorKind::None))
711 constructAbility = ConstructAbility::CannotConstruct;
712
713 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), body, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, variablesUnderTDZ);
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000714 }
715
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000716 void getVariablesUnderTDZ(VariableEnvironment&);
717
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000718 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);
oliver@apple.com177c2b92014-03-28 01:10:25 +0000719 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);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000720
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +0000721 void initializeVarLexicalEnvironment(int symbolTableConstantIndex);
722 void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const std::function<bool (UniquedStringImpl*)>& captures);
723
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000724 public:
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000725 JSString* addStringConstant(const Identifier&);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000726 JSTemplateRegistryKey* addTemplateRegistryKeyConstant(const TemplateRegistryKey&);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000727
oliver@apple.com4e3f9652013-04-08 04:14:50 +0000728 Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000729
darin@apple.comfa069502008-11-10 01:04:30 +0000730 RegisterID* emitThrowExpressionTooDeepException();
731
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +0000732 private:
oliver@apple.com4e3f9652013-04-08 04:14:50 +0000733 Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
oliver@apple.combe38ac42009-05-12 08:58:56 +0000734
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000735 bool m_shouldEmitDebugHooks;
ggaren@apple.com4b8c0fb2008-10-20 16:48:30 +0000736 bool m_shouldEmitProfileHooks;
weinig@apple.coma963b962008-06-05 05:36:55 +0000737
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000738 struct SymbolTableStackEntry {
739 Strong<SymbolTable> m_symbolTable;
740 RegisterID* m_scope;
741 bool m_isWithOrCatch;
742 int m_symbolTableConstantIndex;
743 };
744 Vector<SymbolTableStackEntry> m_symbolTableStack;
745 Vector<std::pair<VariableEnvironment, bool>> m_TDZStack;
weinig@apple.coma963b962008-06-05 05:36:55 +0000746
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000747 ScopeNode* const m_scopeNode;
oliver@apple.comf0c01b82012-11-07 00:13:54 +0000748 Strong<UnlinkedCodeBlock> m_codeBlock;
weinig@apple.coma963b962008-06-05 05:36:55 +0000749
ggaren@apple.come010bc1b2009-03-26 02:34:54 +0000750 // Some of these objects keep pointers to one another. They are arranged
751 // to ensure a sane destruction order that avoids references to freed memory.
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000752 HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> m_functions;
cwzwarich@webkit.orgd47b49a2008-12-03 06:13:58 +0000753 RegisterID m_ignoredResultRegister;
ggaren@apple.com873cb422008-06-02 20:45:13 +0000754 RegisterID m_thisRegister;
ggaren@apple.comf8200082012-09-07 01:42:53 +0000755 RegisterID m_calleeRegister;
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000756 RegisterID* m_scopeRegister { nullptr };
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000757 RegisterID* m_argumentsRegister { nullptr };
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000758 RegisterID* m_lexicalEnvironmentRegister { nullptr };
759 RegisterID* m_emptyValueRegister { nullptr };
760 RegisterID* m_globalObjectRegister { nullptr };
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000761 RegisterID* m_newTargetRegister { nullptr };
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000762 RegisterID* m_linkTimeConstantRegisters[LinkTimeConstantCount];
oliver@apple.com71684cb2014-10-17 16:07:08 +0000763
darin@apple.com1828ba22009-08-14 01:15:15 +0000764 SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
765 SegmentedVector<RegisterID, 32> m_calleeRegisters;
766 SegmentedVector<RegisterID, 32> m_parameters;
darin@apple.com1828ba22009-08-14 01:15:15 +0000767 SegmentedVector<Label, 32> m_labels;
oliver@apple.com6a976452013-03-11 21:02:39 +0000768 LabelScopeStore m_labelScopes;
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000769 int m_finallyDepth { 0 };
770 int m_localScopeDepth { 0 };
771 const CodeType m_codeType;
weinig@apple.coma963b962008-06-05 05:36:55 +0000772
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000773 int calculateTargetScopeDepthForExceptionHandler() const;
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +0000774 int localScopeDepth() const;
775 void pushScopedControlFlowContext();
776 void popScopedControlFlowContext();
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000777
oliver@apple.com4e3f9652013-04-08 04:14:50 +0000778 Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
oliver@apple.com8007f462008-07-24 00:49:46 +0000779 Vector<SwitchInfo> m_switchContextStack;
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000780 Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000781 Vector<TryContext> m_tryContextStack;
saambarati1@gmail.com03edc3b2015-05-08 01:59:14 +0000782 enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
783 Vector<std::pair<FunctionBodyNode*, FunctionVariableType>> m_functionsToInitialize;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000784 bool m_needToInitializeArguments { false };
fpizlo@apple.comb08ed272012-08-27 00:49:25 +0000785
786 Vector<TryRange> m_tryRanges;
787 SegmentedVector<TryData, 8> m_tryData;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000788
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000789 int m_nextConstantOffset { 0 };
ggaren@apple.com82a62d02008-06-27 22:35:33 +0000790
oliver@apple.comf61c9a12010-09-24 19:06:29 +0000791 typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
792 FunctionOffsetMap m_functionOffsets;
793
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000794 // Constant pool
795 IdentifierMap m_identifierMap;
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000796
797 typedef HashMap<EncodedJSValueWithRepresentation, unsigned, EncodedJSValueWithRepresentationHash, EncodedJSValueWithRepresentationHashTraits> JSValueMap;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000798 JSValueMap m_jsValueMap;
darin@apple.coma372f0a2008-09-21 20:35:20 +0000799 IdentifierStringMap m_stringMap;
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000800 TemplateRegistryKeyMap m_templateRegistryKeyMap;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000801
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000802 StaticPropertyAnalyzer m_staticPropertyAnalyzer { &m_instructions };
ggaren@apple.comc862eac2013-01-29 05:48:01 +0000803
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000804 VM* m_vm;
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000805
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000806 OpcodeID m_lastOpcodeID = op_end;
commit-queue@webkit.org6ef841b2010-08-05 22:22:49 +0000807#ifndef NDEBUG
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000808 size_t m_lastOpcodePosition { 0 };
commit-queue@webkit.org6ef841b2010-08-05 22:22:49 +0000809#endif
commit-queue@webkit.orgad641af2013-02-26 09:07:57 +0000810
benjamin@webkit.orgb8d53f92015-02-12 22:20:18 +0000811 bool m_usesExceptions { false };
812 bool m_expressionTooDeep { false };
813 bool m_isBuiltinFunction { false };
saambarati1@gmail.com3321f092015-07-20 21:16:41 +0000814 bool m_usesNonStrictEval { false };
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000815 };
816
817}
818
ggaren@apple.com8e06f202008-11-15 21:05:23 +0000819#endif // BytecodeGenerator_h