OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-array-builder.h" | 5 #include "src/interpreter/bytecode-array-builder.h" |
6 | 6 |
7 #include "src/globals.h" | 7 #include "src/globals.h" |
8 #include "src/interpreter/bytecode-array-writer.h" | 8 #include "src/interpreter/bytecode-array-writer.h" |
9 #include "src/interpreter/bytecode-dead-code-optimizer.h" | 9 #include "src/interpreter/bytecode-dead-code-optimizer.h" |
10 #include "src/interpreter/bytecode-label.h" | 10 #include "src/interpreter/bytecode-label.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 return reg.is_parameter() || reg.index() < locals_count(); | 73 return reg.is_parameter() || reg.index() < locals_count(); |
74 } | 74 } |
75 | 75 |
76 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { | 76 Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { |
77 DCHECK(return_seen_in_block_); | 77 DCHECK(return_seen_in_block_); |
78 DCHECK(!bytecode_generated_); | 78 DCHECK(!bytecode_generated_); |
79 bytecode_generated_ = true; | 79 bytecode_generated_ = true; |
80 | 80 |
81 Handle<FixedArray> handler_table = | 81 Handle<FixedArray> handler_table = |
82 handler_table_builder()->ToHandlerTable(isolate); | 82 handler_table_builder()->ToHandlerTable(isolate); |
83 return pipeline_->ToBytecodeArray(isolate, fixed_register_count(), | 83 return pipeline_->ToBytecodeArray(isolate, |
84 fixed_and_temporary_register_count(), | |
84 parameter_count(), handler_table); | 85 parameter_count(), handler_table); |
85 } | 86 } |
86 | 87 |
87 namespace { | |
88 | |
89 static bool ExpressionPositionIsNeeded(Bytecode bytecode) { | |
90 // An expression position is always needed if filtering is turned | |
91 // off. Otherwise an expression is only needed if the bytecode has | |
92 // external side effects. | |
93 return !FLAG_ignition_filter_expression_positions || | |
94 !Bytecodes::IsWithoutExternalSideEffects(bytecode); | |
95 } | |
96 | |
97 } // namespace | |
98 | |
99 void BytecodeArrayBuilder::AttachSourceInfo(BytecodeNode* node) { | |
100 if (latest_source_info_.is_valid()) { | |
101 // Statement positions need to be emitted immediately. Expression | |
102 // positions can be pushed back until a bytecode is found that can | |
103 // throw. Hence we only invalidate the existing source position | |
104 // information if it is used. | |
105 if (latest_source_info_.is_statement() || | |
106 ExpressionPositionIsNeeded(node->bytecode())) { | |
107 node->source_info().Clone(latest_source_info_); | |
108 latest_source_info_.set_invalid(); | |
109 } | |
110 } | |
111 } | |
112 | |
113 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 88 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
114 uint32_t operand1, uint32_t operand2, | 89 uint32_t operand1, uint32_t operand2, |
115 uint32_t operand3) { | 90 uint32_t operand3) { |
116 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); | 91 DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); |
117 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3); | 92 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, |
118 AttachSourceInfo(&node); | 93 &latest_source_info_); |
119 pipeline()->Write(&node); | 94 pipeline()->Write(&node); |
120 } | 95 } |
121 | 96 |
122 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 97 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
123 uint32_t operand1, uint32_t operand2) { | 98 uint32_t operand1, uint32_t operand2) { |
124 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); | 99 DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); |
125 BytecodeNode node(bytecode, operand0, operand1, operand2); | 100 BytecodeNode node(bytecode, operand0, operand1, operand2, |
126 AttachSourceInfo(&node); | 101 &latest_source_info_); |
127 pipeline()->Write(&node); | 102 pipeline()->Write(&node); |
128 } | 103 } |
129 | 104 |
130 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, | 105 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
131 uint32_t operand1) { | 106 uint32_t operand1) { |
132 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); | 107 DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); |
133 BytecodeNode node(bytecode, operand0, operand1); | 108 BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_); |
134 AttachSourceInfo(&node); | |
135 pipeline()->Write(&node); | 109 pipeline()->Write(&node); |
136 } | 110 } |
137 | 111 |
138 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { | 112 void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { |
139 DCHECK(OperandsAreValid(bytecode, 1, operand0)); | 113 DCHECK(OperandsAreValid(bytecode, 1, operand0)); |
140 BytecodeNode node(bytecode, operand0); | 114 BytecodeNode node(bytecode, operand0, &latest_source_info_); |
141 AttachSourceInfo(&node); | |
142 pipeline()->Write(&node); | 115 pipeline()->Write(&node); |
143 } | 116 } |
144 | 117 |
145 void BytecodeArrayBuilder::Output(Bytecode bytecode) { | 118 void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
146 DCHECK(OperandsAreValid(bytecode, 0)); | 119 DCHECK(OperandsAreValid(bytecode, 0)); |
147 BytecodeNode node(bytecode); | 120 BytecodeNode node(bytecode, &latest_source_info_); |
148 AttachSourceInfo(&node); | |
149 pipeline()->Write(&node); | 121 pipeline()->Write(&node); |
150 } | 122 } |
151 | 123 |
124 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, | |
125 BytecodeLabel* label) { | |
126 BytecodeNode node(bytecode, 0, &latest_source_info_); | |
127 pipeline_->WriteJump(&node, label); | |
128 LeaveBasicBlock(); | |
129 } | |
130 | |
131 void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, | |
132 uint32_t operand0, BytecodeLabel* label) { | |
133 BytecodeNode node(bytecode, 0, operand0, &latest_source_info_); | |
134 pipeline_->WriteJump(&node, label); | |
135 LeaveBasicBlock(); | |
136 } | |
137 | |
152 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, | 138 BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
153 Register reg, | 139 Register reg, |
154 int feedback_slot) { | 140 int feedback_slot) { |
155 Output(BytecodeForBinaryOperation(op), RegisterOperand(reg), | 141 switch (op) { |
156 UnsignedOperand(feedback_slot)); | 142 case Token::Value::ADD: |
143 Output(Bytecode::kAdd, RegisterOperand(reg), | |
144 UnsignedOperand(feedback_slot)); | |
145 break; | |
146 case Token::Value::SUB: | |
147 Output(Bytecode::kSub, RegisterOperand(reg), | |
148 UnsignedOperand(feedback_slot)); | |
149 break; | |
150 case Token::Value::MUL: | |
151 Output(Bytecode::kMul, RegisterOperand(reg), | |
152 UnsignedOperand(feedback_slot)); | |
153 break; | |
154 case Token::Value::DIV: | |
155 Output(Bytecode::kDiv, RegisterOperand(reg), | |
156 UnsignedOperand(feedback_slot)); | |
157 break; | |
158 case Token::Value::MOD: | |
159 Output(Bytecode::kMod, RegisterOperand(reg), | |
160 UnsignedOperand(feedback_slot)); | |
161 break; | |
162 case Token::Value::BIT_OR: | |
163 Output(Bytecode::kBitwiseOr, RegisterOperand(reg), | |
164 UnsignedOperand(feedback_slot)); | |
165 break; | |
166 case Token::Value::BIT_XOR: | |
167 Output(Bytecode::kBitwiseXor, RegisterOperand(reg), | |
168 UnsignedOperand(feedback_slot)); | |
169 break; | |
170 case Token::Value::BIT_AND: | |
171 Output(Bytecode::kBitwiseAnd, RegisterOperand(reg), | |
172 UnsignedOperand(feedback_slot)); | |
173 break; | |
174 case Token::Value::SHL: | |
175 Output(Bytecode::kShiftLeft, RegisterOperand(reg), | |
176 UnsignedOperand(feedback_slot)); | |
177 break; | |
178 case Token::Value::SAR: | |
179 Output(Bytecode::kShiftRight, RegisterOperand(reg), | |
180 UnsignedOperand(feedback_slot)); | |
181 break; | |
182 case Token::Value::SHR: | |
183 Output(Bytecode::kShiftRightLogical, RegisterOperand(reg), | |
184 UnsignedOperand(feedback_slot)); | |
185 break; | |
186 default: | |
187 UNREACHABLE(); | |
188 } | |
157 return *this; | 189 return *this; |
158 } | 190 } |
159 | 191 |
160 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, | 192 BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, |
161 int feedback_slot) { | 193 int feedback_slot) { |
162 Output(BytecodeForCountOperation(op), UnsignedOperand(feedback_slot)); | 194 if (op == Token::Value::ADD) { |
195 Output(Bytecode::kInc, UnsignedOperand(feedback_slot)); | |
196 } else { | |
197 DCHECK_EQ(op, Token::Value::SUB); | |
198 Output(Bytecode::kDec, UnsignedOperand(feedback_slot)); | |
199 } | |
163 return *this; | 200 return *this; |
164 } | 201 } |
165 | 202 |
166 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { | 203 BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
167 Output(Bytecode::kToBooleanLogicalNot); | 204 Output(Bytecode::kToBooleanLogicalNot); |
168 return *this; | 205 return *this; |
169 } | 206 } |
170 | 207 |
171 | |
172 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { | 208 BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
173 Output(Bytecode::kTypeOf); | 209 Output(Bytecode::kTypeOf); |
174 return *this; | 210 return *this; |
175 } | 211 } |
176 | 212 |
177 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( | 213 BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
178 Token::Value op, Register reg, int feedback_slot) { | 214 Token::Value op, Register reg, int feedback_slot) { |
179 if (op == Token::INSTANCEOF || op == Token::IN) { | 215 switch (op) { |
180 Output(BytecodeForCompareOperation(op), RegisterOperand(reg)); | 216 case Token::Value::EQ: |
181 } else { | 217 Output(Bytecode::kTestEqual, RegisterOperand(reg), |
182 Output(BytecodeForCompareOperation(op), RegisterOperand(reg), | 218 UnsignedOperand(feedback_slot)); |
183 UnsignedOperand(feedback_slot)); | 219 break; |
220 case Token::Value::NE: | |
221 Output(Bytecode::kTestNotEqual, RegisterOperand(reg), | |
222 UnsignedOperand(feedback_slot)); | |
223 break; | |
224 case Token::Value::EQ_STRICT: | |
225 Output(Bytecode::kTestEqualStrict, RegisterOperand(reg), | |
226 UnsignedOperand(feedback_slot)); | |
227 break; | |
228 case Token::Value::LT: | |
229 Output(Bytecode::kTestLessThan, RegisterOperand(reg), | |
230 UnsignedOperand(feedback_slot)); | |
231 break; | |
232 case Token::Value::GT: | |
233 Output(Bytecode::kTestGreaterThan, RegisterOperand(reg), | |
234 UnsignedOperand(feedback_slot)); | |
235 break; | |
236 case Token::Value::LTE: | |
237 Output(Bytecode::kTestLessThanOrEqual, RegisterOperand(reg), | |
238 UnsignedOperand(feedback_slot)); | |
239 break; | |
240 case Token::Value::GTE: | |
241 Output(Bytecode::kTestGreaterThanOrEqual, RegisterOperand(reg), | |
242 UnsignedOperand(feedback_slot)); | |
243 break; | |
244 case Token::Value::INSTANCEOF: | |
245 Output(Bytecode::kTestInstanceOf, RegisterOperand(reg)); | |
246 break; | |
247 case Token::Value::IN: | |
248 Output(Bytecode::kTestIn, RegisterOperand(reg)); | |
249 break; | |
250 default: | |
251 UNREACHABLE(); | |
184 } | 252 } |
185 return *this; | 253 return *this; |
186 } | 254 } |
187 | 255 |
188 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( | 256 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( |
189 size_t entry) { | 257 size_t entry) { |
190 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); | 258 Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); |
191 return *this; | 259 return *this; |
192 } | 260 } |
193 | 261 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 | 315 |
248 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, | 316 BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
249 Register to) { | 317 Register to) { |
250 DCHECK(from != to); | 318 DCHECK(from != to); |
251 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); | 319 Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); |
252 return *this; | 320 return *this; |
253 } | 321 } |
254 | 322 |
255 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, | 323 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, |
256 TypeofMode typeof_mode) { | 324 TypeofMode typeof_mode) { |
257 // TODO(rmcilroy): Potentially store typeof information in an | 325 if (typeof_mode == INSIDE_TYPEOF) { |
258 // operand rather than having extra bytecodes. | 326 Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot); |
259 Bytecode bytecode = BytecodeForLoadGlobal(typeof_mode); | 327 } else { |
260 Output(bytecode, UnsignedOperand(feedback_slot)); | 328 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
329 Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot)); | |
330 } | |
261 return *this; | 331 return *this; |
262 } | 332 } |
263 | 333 |
264 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( | 334 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
265 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { | 335 const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
266 Bytecode bytecode = BytecodeForStoreGlobal(language_mode); | |
267 size_t name_index = GetConstantPoolEntry(name); | 336 size_t name_index = GetConstantPoolEntry(name); |
268 Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | 337 if (language_mode == SLOPPY) { |
338 Output(Bytecode::kStaGlobalSloppy, UnsignedOperand(name_index), | |
339 UnsignedOperand(feedback_slot)); | |
340 } else { | |
341 DCHECK_EQ(language_mode, STRICT); | |
342 Output(Bytecode::kStaGlobalStrict, UnsignedOperand(name_index), | |
343 UnsignedOperand(feedback_slot)); | |
344 } | |
269 return *this; | 345 return *this; |
270 } | 346 } |
271 | 347 |
272 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, | 348 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
273 int slot_index, | 349 int slot_index, |
274 int depth) { | 350 int depth) { |
275 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), | 351 Output(Bytecode::kLdaContextSlot, RegisterOperand(context), |
276 UnsignedOperand(slot_index), UnsignedOperand(depth)); | 352 UnsignedOperand(slot_index), UnsignedOperand(depth)); |
277 return *this; | 353 return *this; |
278 } | 354 } |
279 | 355 |
280 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, | 356 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
281 int slot_index, | 357 int slot_index, |
282 int depth) { | 358 int depth) { |
283 Output(Bytecode::kStaContextSlot, RegisterOperand(context), | 359 Output(Bytecode::kStaContextSlot, RegisterOperand(context), |
284 UnsignedOperand(slot_index), UnsignedOperand(depth)); | 360 UnsignedOperand(slot_index), UnsignedOperand(depth)); |
285 return *this; | 361 return *this; |
286 } | 362 } |
287 | 363 |
288 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( | 364 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
289 const Handle<String> name, TypeofMode typeof_mode) { | 365 const Handle<String> name, TypeofMode typeof_mode) { |
290 Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) | |
291 ? Bytecode::kLdaLookupSlotInsideTypeof | |
292 : Bytecode::kLdaLookupSlot; | |
293 size_t name_index = GetConstantPoolEntry(name); | 366 size_t name_index = GetConstantPoolEntry(name); |
294 Output(bytecode, UnsignedOperand(name_index)); | 367 if (typeof_mode == INSIDE_TYPEOF) { |
368 Output(Bytecode::kLdaLookupSlotInsideTypeof, UnsignedOperand(name_index)); | |
369 } else { | |
370 DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); | |
371 Output(Bytecode::kLdaLookupSlot, UnsignedOperand(name_index)); | |
372 } | |
295 return *this; | 373 return *this; |
296 } | 374 } |
297 | 375 |
298 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( | 376 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
299 const Handle<String> name, LanguageMode language_mode) { | 377 const Handle<String> name, LanguageMode language_mode) { |
300 Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode); | |
301 size_t name_index = GetConstantPoolEntry(name); | 378 size_t name_index = GetConstantPoolEntry(name); |
302 Output(bytecode, UnsignedOperand(name_index)); | 379 if (language_mode == SLOPPY) { |
380 Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index)); | |
381 } else { | |
Leszek Swirski
2016/09/20 10:37:56
DCHECK for strict
rmcilroy
2016/09/20 16:57:25
Done.
| |
382 Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index)); | |
383 } | |
303 return *this; | 384 return *this; |
304 } | 385 } |
305 | 386 |
306 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( | 387 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
307 Register object, const Handle<Name> name, int feedback_slot) { | 388 Register object, const Handle<Name> name, int feedback_slot) { |
308 size_t name_index = GetConstantPoolEntry(name); | 389 size_t name_index = GetConstantPoolEntry(name); |
309 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), | 390 Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), |
310 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | 391 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
311 return *this; | 392 return *this; |
312 } | 393 } |
313 | 394 |
314 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( | 395 BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
315 Register object, int feedback_slot) { | 396 Register object, int feedback_slot) { |
316 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), | 397 Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), |
317 UnsignedOperand(feedback_slot)); | 398 UnsignedOperand(feedback_slot)); |
318 return *this; | 399 return *this; |
319 } | 400 } |
320 | 401 |
321 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( | 402 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
322 Register object, const Handle<Name> name, int feedback_slot, | 403 Register object, const Handle<Name> name, int feedback_slot, |
323 LanguageMode language_mode) { | 404 LanguageMode language_mode) { |
324 Bytecode bytecode = BytecodeForStoreNamedProperty(language_mode); | |
325 size_t name_index = GetConstantPoolEntry(name); | 405 size_t name_index = GetConstantPoolEntry(name); |
326 Output(bytecode, RegisterOperand(object), UnsignedOperand(name_index), | 406 if (language_mode == SLOPPY) { |
327 UnsignedOperand(feedback_slot)); | 407 Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object), |
408 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
409 } else { | |
410 DCHECK_EQ(language_mode, STRICT); | |
411 Output(Bytecode::kStaNamedPropertyStrict, RegisterOperand(object), | |
412 UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); | |
413 } | |
328 return *this; | 414 return *this; |
329 } | 415 } |
330 | 416 |
331 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( | 417 BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
332 Register object, Register key, int feedback_slot, | 418 Register object, Register key, int feedback_slot, |
333 LanguageMode language_mode) { | 419 LanguageMode language_mode) { |
334 Bytecode bytecode = BytecodeForStoreKeyedProperty(language_mode); | 420 if (language_mode == SLOPPY) { |
335 Output(bytecode, RegisterOperand(object), RegisterOperand(key), | 421 Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object), |
336 UnsignedOperand(feedback_slot)); | 422 RegisterOperand(key), UnsignedOperand(feedback_slot)); |
423 } else { | |
424 DCHECK_EQ(language_mode, STRICT); | |
425 Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object), | |
426 RegisterOperand(key), UnsignedOperand(feedback_slot)); | |
427 } | |
337 return *this; | 428 return *this; |
338 } | 429 } |
339 | 430 |
340 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, | 431 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, |
341 int flags) { | 432 int flags) { |
342 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), | 433 Output(Bytecode::kCreateClosure, UnsignedOperand(entry), |
343 UnsignedOperand(flags)); | 434 UnsignedOperand(flags)); |
344 return *this; | 435 return *this; |
345 } | 436 } |
346 | 437 |
(...skipping 21 matching lines...) Expand all Loading... | |
368 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( | 459 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( |
369 Register object, Handle<ScopeInfo> scope_info) { | 460 Register object, Handle<ScopeInfo> scope_info) { |
370 size_t scope_info_index = GetConstantPoolEntry(scope_info); | 461 size_t scope_info_index = GetConstantPoolEntry(scope_info); |
371 Output(Bytecode::kCreateWithContext, RegisterOperand(object), | 462 Output(Bytecode::kCreateWithContext, RegisterOperand(object), |
372 UnsignedOperand(scope_info_index)); | 463 UnsignedOperand(scope_info_index)); |
373 return *this; | 464 return *this; |
374 } | 465 } |
375 | 466 |
376 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( | 467 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
377 CreateArgumentsType type) { | 468 CreateArgumentsType type) { |
378 // TODO(rmcilroy): Consider passing the type as a bytecode operand rather | 469 switch (type) { |
379 // than having two different bytecodes once we have better support for | 470 case CreateArgumentsType::kMappedArguments: |
380 // branches in the InterpreterAssembler. | 471 Output(Bytecode::kCreateMappedArguments); |
381 Bytecode bytecode = BytecodeForCreateArguments(type); | 472 break; |
382 Output(bytecode); | 473 case CreateArgumentsType::kUnmappedArguments: |
474 Output(Bytecode::kCreateUnmappedArguments); | |
475 break; | |
476 case CreateArgumentsType::kRestParameter: | |
477 Output(Bytecode::kCreateRestParameter); | |
478 break; | |
479 default: | |
480 UNREACHABLE(); | |
481 } | |
383 return *this; | 482 return *this; |
384 } | 483 } |
385 | 484 |
386 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( | 485 BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
387 Handle<String> pattern, int literal_index, int flags) { | 486 Handle<String> pattern, int literal_index, int flags) { |
388 size_t pattern_entry = GetConstantPoolEntry(pattern); | 487 size_t pattern_entry = GetConstantPoolEntry(pattern); |
389 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), | 488 Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), |
390 UnsignedOperand(literal_index), UnsignedOperand(flags)); | 489 UnsignedOperand(literal_index), UnsignedOperand(flags)); |
391 return *this; | 490 return *this; |
392 } | 491 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
445 return *this; | 544 return *this; |
446 } | 545 } |
447 | 546 |
448 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, | 547 BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, |
449 BytecodeLabel* label) { | 548 BytecodeLabel* label) { |
450 pipeline_->BindLabel(target, label); | 549 pipeline_->BindLabel(target, label); |
451 LeaveBasicBlock(); | 550 LeaveBasicBlock(); |
452 return *this; | 551 return *this; |
453 } | 552 } |
454 | 553 |
455 BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(BytecodeNode* node, | |
456 BytecodeLabel* label) { | |
457 AttachSourceInfo(node); | |
458 pipeline_->WriteJump(node, label); | |
459 LeaveBasicBlock(); | |
460 return *this; | |
461 } | |
462 | |
463 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { | 554 BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
464 BytecodeNode node(Bytecode::kJump, 0); | 555 OutputJump(Bytecode::kJump, label); |
465 return OutputJump(&node, label); | 556 return *this; |
466 } | 557 } |
467 | 558 |
468 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { | 559 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
469 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue | 560 // The peephole optimizer attempts to simplify JumpIfToBooleanTrue |
470 // to JumpIfTrue. | 561 // to JumpIfTrue. |
471 BytecodeNode node(Bytecode::kJumpIfToBooleanTrue, 0); | 562 OutputJump(Bytecode::kJumpIfToBooleanTrue, label); |
472 return OutputJump(&node, label); | 563 return *this; |
473 } | 564 } |
474 | 565 |
475 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { | 566 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { |
476 // The peephole optimizer attempts to simplify JumpIfToBooleanFalse | 567 OutputJump(Bytecode::kJumpIfToBooleanFalse, label); |
477 // to JumpIfFalse. | 568 return *this; |
478 BytecodeNode node(Bytecode::kJumpIfToBooleanFalse, 0); | |
479 return OutputJump(&node, label); | |
480 } | 569 } |
481 | 570 |
482 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { | 571 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { |
483 BytecodeNode node(Bytecode::kJumpIfNull, 0); | 572 OutputJump(Bytecode::kJumpIfNull, label); |
484 return OutputJump(&node, label); | 573 return *this; |
485 } | 574 } |
486 | 575 |
487 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( | 576 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( |
488 BytecodeLabel* label) { | 577 BytecodeLabel* label) { |
489 BytecodeNode node(Bytecode::kJumpIfUndefined, 0); | 578 OutputJump(Bytecode::kJumpIfUndefined, label); |
490 return OutputJump(&node, label); | 579 return *this; |
491 } | 580 } |
492 | 581 |
493 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( | 582 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
494 BytecodeLabel* label) { | 583 BytecodeLabel* label) { |
495 BytecodeNode node(Bytecode::kJumpIfNotHole, 0); | 584 OutputJump(Bytecode::kJumpIfNotHole, label); |
496 return OutputJump(&node, label); | 585 return *this; |
497 } | 586 } |
498 | 587 |
499 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, | 588 BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, |
500 int loop_depth) { | 589 int loop_depth) { |
501 BytecodeNode node(Bytecode::kJumpLoop, 0, UnsignedOperand(loop_depth)); | 590 OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label); |
502 return OutputJump(&node, label); | 591 return *this; |
503 } | 592 } |
504 | 593 |
505 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { | 594 BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { |
506 if (position != kNoSourcePosition) { | 595 if (position != kNoSourcePosition) { |
507 // We need to attach a non-breakable source position to a stack | 596 // We need to attach a non-breakable source position to a stack |
508 // check, so we simply add it as expression position. There can be | 597 // check, so we simply add it as expression position. There can be |
509 // a prior statement position from constructs like: | 598 // a prior statement position from constructs like: |
510 // | 599 // |
511 // do var x; while (false); | 600 // do var x; while (false); |
512 // | 601 // |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 Return(); | 702 Return(); |
614 } | 703 } |
615 DCHECK(return_seen_in_block_); | 704 DCHECK(return_seen_in_block_); |
616 } | 705 } |
617 | 706 |
618 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, | 707 BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
619 Register receiver_args, | 708 Register receiver_args, |
620 size_t receiver_args_count, | 709 size_t receiver_args_count, |
621 int feedback_slot, | 710 int feedback_slot, |
622 TailCallMode tail_call_mode) { | 711 TailCallMode tail_call_mode) { |
623 Bytecode bytecode = BytecodeForCall(tail_call_mode); | 712 if (tail_call_mode == TailCallMode::kDisallow) { |
624 Output(bytecode, RegisterOperand(callable), RegisterOperand(receiver_args), | 713 Output(Bytecode::kCall, RegisterOperand(callable), |
625 UnsignedOperand(receiver_args_count), UnsignedOperand(feedback_slot)); | 714 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count), |
715 UnsignedOperand(feedback_slot)); | |
716 } else { | |
717 DCHECK(tail_call_mode == TailCallMode::kAllow); | |
718 Output(Bytecode::kTailCall, RegisterOperand(callable), | |
719 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count), | |
720 UnsignedOperand(feedback_slot)); | |
721 } | |
626 return *this; | 722 return *this; |
627 } | 723 } |
628 | 724 |
629 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, | 725 BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
630 Register first_arg, | 726 Register first_arg, |
631 size_t arg_count, | 727 size_t arg_count, |
632 int feedback_slot_id) { | 728 int feedback_slot_id) { |
633 if (!first_arg.is_valid()) { | 729 if (!first_arg.is_valid()) { |
634 DCHECK_EQ(0u, arg_count); | 730 DCHECK_EQ(0u, arg_count); |
635 first_arg = Register(0); | 731 first_arg = Register(0); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
678 | 774 |
679 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( | 775 BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime( |
680 int context_index, Register receiver_args, size_t receiver_args_count) { | 776 int context_index, Register receiver_args, size_t receiver_args_count) { |
681 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), | 777 Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), |
682 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); | 778 RegisterOperand(receiver_args), UnsignedOperand(receiver_args_count)); |
683 return *this; | 779 return *this; |
684 } | 780 } |
685 | 781 |
686 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, | 782 BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
687 LanguageMode language_mode) { | 783 LanguageMode language_mode) { |
688 Output(BytecodeForDelete(language_mode), RegisterOperand(object)); | 784 if (language_mode == SLOPPY) { |
785 Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); | |
786 } else { | |
787 DCHECK_EQ(language_mode, STRICT); | |
788 Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); | |
789 } | |
689 return *this; | 790 return *this; |
690 } | 791 } |
691 | 792 |
692 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { | 793 size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) { |
693 return constant_array_builder()->Insert(object); | 794 return constant_array_builder()->Insert(object); |
694 } | 795 } |
695 | 796 |
696 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { | 797 size_t BytecodeArrayBuilder::AllocateConstantPoolEntry() { |
697 return constant_array_builder()->AllocateEntry(); | 798 return constant_array_builder()->AllocateEntry(); |
698 } | 799 } |
699 | 800 |
700 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, | 801 void BytecodeArrayBuilder::InsertConstantPoolEntryAt(size_t entry, |
701 Handle<Object> object) { | 802 Handle<Object> object) { |
702 constant_array_builder()->InsertAllocatedEntry(entry, object); | 803 constant_array_builder()->InsertAllocatedEntry(entry, object); |
703 } | 804 } |
704 | 805 |
705 void BytecodeArrayBuilder::SetReturnPosition() { | 806 void BytecodeArrayBuilder::SetReturnPosition() { |
706 if (return_position_ == kNoSourcePosition) return; | 807 if (return_position_ == kNoSourcePosition) return; |
707 latest_source_info_.MakeStatementPosition(return_position_); | 808 latest_source_info_.MakeStatementPosition(return_position_); |
708 } | 809 } |
709 | 810 |
710 void BytecodeArrayBuilder::SetStatementPosition(Statement* stmt) { | |
711 if (stmt->position() == kNoSourcePosition) return; | |
712 latest_source_info_.MakeStatementPosition(stmt->position()); | |
713 } | |
714 | |
715 void BytecodeArrayBuilder::SetExpressionPosition(Expression* expr) { | |
716 if (expr->position() == kNoSourcePosition) return; | |
717 if (!latest_source_info_.is_statement()) { | |
718 // Ensure the current expression position is overwritten with the | |
719 // latest value. | |
720 latest_source_info_.MakeExpressionPosition(expr->position()); | |
721 } | |
722 } | |
723 | |
724 void BytecodeArrayBuilder::SetExpressionAsStatementPosition(Expression* expr) { | |
725 if (expr->position() == kNoSourcePosition) return; | |
726 latest_source_info_.MakeStatementPosition(expr->position()); | |
727 } | |
728 | |
729 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { | 811 bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const { |
730 return temporary_register_allocator()->RegisterIsLive(reg); | 812 return temporary_register_allocator()->RegisterIsLive(reg); |
731 } | 813 } |
732 | 814 |
733 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { | 815 bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { |
734 if (!reg.is_valid()) { | 816 if (!reg.is_valid()) { |
735 return false; | 817 return false; |
736 } | 818 } |
737 | 819 |
738 if (reg.is_current_context() || reg.is_function_closure() || | 820 if (reg.is_current_context() || reg.is_function_closure() || |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
782 } | 864 } |
783 break; | 865 break; |
784 case OperandType::kRuntimeId: | 866 case OperandType::kRuntimeId: |
785 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > | 867 if (Bytecodes::SizeForUnsignedOperand(operands[i]) > |
786 OperandSize::kShort) { | 868 OperandSize::kShort) { |
787 return false; | 869 return false; |
788 } | 870 } |
789 break; | 871 break; |
790 case OperandType::kIdx: | 872 case OperandType::kIdx: |
791 // TODO(leszeks): Possibly split this up into constant pool indices and | 873 // TODO(leszeks): Possibly split this up into constant pool indices and |
792 // other indices, for checking | 874 // other indices, for checking. |
793 break; | 875 break; |
794 case OperandType::kUImm: | 876 case OperandType::kUImm: |
795 case OperandType::kImm: | 877 case OperandType::kImm: |
796 break; | 878 break; |
797 case OperandType::kMaybeReg: | 879 case OperandType::kMaybeReg: |
798 if (Register::FromOperand(operands[i]) == Register(0)) { | 880 if (Register::FromOperand(operands[i]) == Register(0)) { |
799 break; | 881 break; |
800 } | 882 } |
801 // Fall-through to kReg case. | 883 // Fall-through to kReg case. |
802 case OperandType::kReg: | 884 case OperandType::kReg: |
(...skipping 22 matching lines...) Expand all Loading... | |
825 return false; | 907 return false; |
826 } | 908 } |
827 break; | 909 break; |
828 } | 910 } |
829 } | 911 } |
830 } | 912 } |
831 | 913 |
832 return true; | 914 return true; |
833 } | 915 } |
834 | 916 |
835 // static | |
836 Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { | |
837 switch (op) { | |
838 case Token::Value::ADD: | |
839 return Bytecode::kAdd; | |
840 case Token::Value::SUB: | |
841 return Bytecode::kSub; | |
842 case Token::Value::MUL: | |
843 return Bytecode::kMul; | |
844 case Token::Value::DIV: | |
845 return Bytecode::kDiv; | |
846 case Token::Value::MOD: | |
847 return Bytecode::kMod; | |
848 case Token::Value::BIT_OR: | |
849 return Bytecode::kBitwiseOr; | |
850 case Token::Value::BIT_XOR: | |
851 return Bytecode::kBitwiseXor; | |
852 case Token::Value::BIT_AND: | |
853 return Bytecode::kBitwiseAnd; | |
854 case Token::Value::SHL: | |
855 return Bytecode::kShiftLeft; | |
856 case Token::Value::SAR: | |
857 return Bytecode::kShiftRight; | |
858 case Token::Value::SHR: | |
859 return Bytecode::kShiftRightLogical; | |
860 default: | |
861 UNREACHABLE(); | |
862 return Bytecode::kIllegal; | |
863 } | |
864 } | |
865 | |
866 // static | |
867 Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) { | |
868 switch (op) { | |
869 case Token::Value::ADD: | |
870 return Bytecode::kInc; | |
871 case Token::Value::SUB: | |
872 return Bytecode::kDec; | |
873 default: | |
874 UNREACHABLE(); | |
875 return Bytecode::kIllegal; | |
876 } | |
877 } | |
878 | |
879 // static | |
880 Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) { | |
881 switch (op) { | |
882 case Token::Value::EQ: | |
883 return Bytecode::kTestEqual; | |
884 case Token::Value::NE: | |
885 return Bytecode::kTestNotEqual; | |
886 case Token::Value::EQ_STRICT: | |
887 return Bytecode::kTestEqualStrict; | |
888 case Token::Value::LT: | |
889 return Bytecode::kTestLessThan; | |
890 case Token::Value::GT: | |
891 return Bytecode::kTestGreaterThan; | |
892 case Token::Value::LTE: | |
893 return Bytecode::kTestLessThanOrEqual; | |
894 case Token::Value::GTE: | |
895 return Bytecode::kTestGreaterThanOrEqual; | |
896 case Token::Value::INSTANCEOF: | |
897 return Bytecode::kTestInstanceOf; | |
898 case Token::Value::IN: | |
899 return Bytecode::kTestIn; | |
900 default: | |
901 UNREACHABLE(); | |
902 return Bytecode::kIllegal; | |
903 } | |
904 } | |
905 | |
906 // static | |
907 Bytecode BytecodeArrayBuilder::BytecodeForStoreNamedProperty( | |
908 LanguageMode language_mode) { | |
909 switch (language_mode) { | |
910 case SLOPPY: | |
911 return Bytecode::kStaNamedPropertySloppy; | |
912 case STRICT: | |
913 return Bytecode::kStaNamedPropertyStrict; | |
914 default: | |
915 UNREACHABLE(); | |
916 } | |
917 return Bytecode::kIllegal; | |
918 } | |
919 | |
920 // static | |
921 Bytecode BytecodeArrayBuilder::BytecodeForStoreKeyedProperty( | |
922 LanguageMode language_mode) { | |
923 switch (language_mode) { | |
924 case SLOPPY: | |
925 return Bytecode::kStaKeyedPropertySloppy; | |
926 case STRICT: | |
927 return Bytecode::kStaKeyedPropertyStrict; | |
928 default: | |
929 UNREACHABLE(); | |
930 } | |
931 return Bytecode::kIllegal; | |
932 } | |
933 | |
934 // static | |
935 Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(TypeofMode typeof_mode) { | |
936 return typeof_mode == INSIDE_TYPEOF ? Bytecode::kLdaGlobalInsideTypeof | |
937 : Bytecode::kLdaGlobal; | |
938 } | |
939 | |
940 // static | |
941 Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal( | |
942 LanguageMode language_mode) { | |
943 switch (language_mode) { | |
944 case SLOPPY: | |
945 return Bytecode::kStaGlobalSloppy; | |
946 case STRICT: | |
947 return Bytecode::kStaGlobalStrict; | |
948 default: | |
949 UNREACHABLE(); | |
950 } | |
951 return Bytecode::kIllegal; | |
952 } | |
953 | |
954 // static | |
955 Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot( | |
956 LanguageMode language_mode) { | |
957 switch (language_mode) { | |
958 case SLOPPY: | |
959 return Bytecode::kStaLookupSlotSloppy; | |
960 case STRICT: | |
961 return Bytecode::kStaLookupSlotStrict; | |
962 default: | |
963 UNREACHABLE(); | |
964 } | |
965 return Bytecode::kIllegal; | |
966 } | |
967 | |
968 // static | |
969 Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments( | |
970 CreateArgumentsType type) { | |
971 switch (type) { | |
972 case CreateArgumentsType::kMappedArguments: | |
973 return Bytecode::kCreateMappedArguments; | |
974 case CreateArgumentsType::kUnmappedArguments: | |
975 return Bytecode::kCreateUnmappedArguments; | |
976 case CreateArgumentsType::kRestParameter: | |
977 return Bytecode::kCreateRestParameter; | |
978 } | |
979 UNREACHABLE(); | |
980 return Bytecode::kIllegal; | |
981 } | |
982 | |
983 // static | |
984 Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) { | |
985 switch (language_mode) { | |
986 case SLOPPY: | |
987 return Bytecode::kDeletePropertySloppy; | |
988 case STRICT: | |
989 return Bytecode::kDeletePropertyStrict; | |
990 default: | |
991 UNREACHABLE(); | |
992 } | |
993 return Bytecode::kIllegal; | |
994 } | |
995 | |
996 // static | |
997 Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) { | |
998 switch (tail_call_mode) { | |
999 case TailCallMode::kDisallow: | |
1000 return Bytecode::kCall; | |
1001 case TailCallMode::kAllow: | |
1002 return Bytecode::kTailCall; | |
1003 default: | |
1004 UNREACHABLE(); | |
1005 } | |
1006 return Bytecode::kIllegal; | |
1007 } | |
1008 | |
1009 } // namespace interpreter | 917 } // namespace interpreter |
1010 } // namespace internal | 918 } // namespace internal |
1011 } // namespace v8 | 919 } // namespace v8 |
OLD | NEW |