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/interpreter-assembler.h" | 5 #include "src/interpreter/interpreter-assembler.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <ostream> | 8 #include <ostream> |
9 | 9 |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 } | 79 } |
80 | 80 |
81 void InterpreterAssembler::SetContext(Node* value) { | 81 void InterpreterAssembler::SetContext(Node* value) { |
82 StoreRegister(value, Register::current_context()); | 82 StoreRegister(value, Register::current_context()); |
83 } | 83 } |
84 | 84 |
85 Node* InterpreterAssembler::GetContextAtDepth(Node* context, Node* depth) { | 85 Node* InterpreterAssembler::GetContextAtDepth(Node* context, Node* depth) { |
86 Variable cur_context(this, MachineRepresentation::kTaggedPointer); | 86 Variable cur_context(this, MachineRepresentation::kTaggedPointer); |
87 cur_context.Bind(context); | 87 cur_context.Bind(context); |
88 | 88 |
89 Variable cur_depth(this, MachineRepresentation::kWord32); | 89 Variable cur_depth(this, MachineType::PointerRepresentation()); |
90 cur_depth.Bind(depth); | 90 cur_depth.Bind(depth); |
91 | 91 |
92 Label context_found(this); | 92 Label context_found(this); |
93 | 93 |
94 Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context}; | 94 Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context}; |
95 Label context_search(this, 2, context_search_loop_variables); | 95 Label context_search(this, 2, context_search_loop_variables); |
96 | 96 |
97 // Fast path if the depth is 0. | 97 // Fast path if the depth is 0. |
98 Branch(Word32Equal(depth, Int32Constant(0)), &context_found, &context_search); | 98 Branch(WordEqual(depth, IntPtrConstant(0)), &context_found, &context_search); |
99 | 99 |
100 // Loop until the depth is 0. | 100 // Loop until the depth is 0. |
101 Bind(&context_search); | 101 Bind(&context_search); |
102 { | 102 { |
103 cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1))); | 103 cur_depth.Bind(IntPtrSub(cur_depth.value(), IntPtrConstant(1))); |
104 cur_context.Bind( | 104 cur_context.Bind( |
105 LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX)); | 105 LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX)); |
106 | 106 |
107 Branch(Word32Equal(cur_depth.value(), Int32Constant(0)), &context_found, | 107 Branch(WordEqual(cur_depth.value(), IntPtrConstant(0)), &context_found, |
108 &context_search); | 108 &context_search); |
109 } | 109 } |
110 | 110 |
111 Bind(&context_found); | 111 Bind(&context_found); |
112 return cur_context.value(); | 112 return cur_context.value(); |
113 } | 113 } |
114 | 114 |
115 void InterpreterAssembler::GotoIfHasContextExtensionUpToDepth(Node* context, | 115 void InterpreterAssembler::GotoIfHasContextExtensionUpToDepth(Node* context, |
116 Node* depth, | 116 Node* depth, |
117 Label* target) { | 117 Label* target) { |
118 Variable cur_context(this, MachineRepresentation::kTaggedPointer); | 118 Variable cur_context(this, MachineRepresentation::kTaggedPointer); |
119 cur_context.Bind(context); | 119 cur_context.Bind(context); |
120 | 120 |
121 Variable cur_depth(this, MachineRepresentation::kWord32); | 121 Variable cur_depth(this, MachineType::PointerRepresentation()); |
122 cur_depth.Bind(depth); | 122 cur_depth.Bind(depth); |
123 | 123 |
124 Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context}; | 124 Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context}; |
125 Label context_search(this, 2, context_search_loop_variables); | 125 Label context_search(this, 2, context_search_loop_variables); |
126 | 126 |
127 // Loop until the depth is 0. | 127 // Loop until the depth is 0. |
128 Goto(&context_search); | 128 Goto(&context_search); |
129 Bind(&context_search); | 129 Bind(&context_search); |
130 { | 130 { |
131 // TODO(leszeks): We only need to do this check if the context had a sloppy | 131 // TODO(leszeks): We only need to do this check if the context had a sloppy |
132 // eval, we could pass in a context chain bitmask to figure out which | 132 // eval, we could pass in a context chain bitmask to figure out which |
133 // contexts actually need to be checked. | 133 // contexts actually need to be checked. |
134 | 134 |
135 Node* extension_slot = | 135 Node* extension_slot = |
136 LoadContextElement(cur_context.value(), Context::EXTENSION_INDEX); | 136 LoadContextElement(cur_context.value(), Context::EXTENSION_INDEX); |
137 | 137 |
138 // Jump to the target if the extension slot is not a hole. | 138 // Jump to the target if the extension slot is not a hole. |
139 GotoIf(WordNotEqual(extension_slot, TheHoleConstant()), target); | 139 GotoIf(WordNotEqual(extension_slot, TheHoleConstant()), target); |
140 | 140 |
141 cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1))); | 141 cur_depth.Bind(IntPtrSub(cur_depth.value(), IntPtrConstant(1))); |
142 cur_context.Bind( | 142 cur_context.Bind( |
143 LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX)); | 143 LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX)); |
144 | 144 |
145 GotoIf(Word32NotEqual(cur_depth.value(), Int32Constant(0)), | 145 GotoIf(WordNotEqual(cur_depth.value(), IntPtrConstant(0)), &context_search); |
146 &context_search); | |
147 } | 146 } |
148 } | 147 } |
149 | 148 |
150 Node* InterpreterAssembler::BytecodeOffset() { | 149 Node* InterpreterAssembler::BytecodeOffset() { |
151 return bytecode_offset_.value(); | 150 return bytecode_offset_.value(); |
152 } | 151 } |
153 | 152 |
154 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() { | 153 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() { |
155 if (made_call_) { | 154 if (made_call_) { |
156 // If we have made a call, restore bytecode array from stack frame in case | 155 // If we have made a call, restore bytecode array from stack frame in case |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
204 Node* InterpreterAssembler::OperandOffset(int operand_index) { | 203 Node* InterpreterAssembler::OperandOffset(int operand_index) { |
205 return IntPtrConstant( | 204 return IntPtrConstant( |
206 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale())); | 205 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale())); |
207 } | 206 } |
208 | 207 |
209 Node* InterpreterAssembler::BytecodeOperandUnsignedByte(int operand_index) { | 208 Node* InterpreterAssembler::BytecodeOperandUnsignedByte(int operand_index) { |
210 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 209 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
211 DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize( | 210 DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize( |
212 bytecode_, operand_index, operand_scale())); | 211 bytecode_, operand_index, operand_scale())); |
213 Node* operand_offset = OperandOffset(operand_index); | 212 Node* operand_offset = OperandOffset(operand_index); |
214 return Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), | 213 Node* load = Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
215 IntPtrAdd(BytecodeOffset(), operand_offset)); | 214 IntPtrAdd(BytecodeOffset(), operand_offset)); |
215 return ChangeUint32ToWord(load); | |
rmcilroy
2016/12/09 11:21:37
Not something for this CL (unless it's easier) but
Igor Sheludko
2016/12/10 00:09:50
Done.
| |
216 } | 216 } |
217 | 217 |
218 Node* InterpreterAssembler::BytecodeOperandSignedByte(int operand_index) { | 218 Node* InterpreterAssembler::BytecodeOperandSignedByte(int operand_index) { |
219 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 219 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
220 DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize( | 220 DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize( |
221 bytecode_, operand_index, operand_scale())); | 221 bytecode_, operand_index, operand_scale())); |
222 Node* operand_offset = OperandOffset(operand_index); | 222 Node* operand_offset = OperandOffset(operand_index); |
223 Node* load = Load(MachineType::Int8(), BytecodeArrayTaggedPointer(), | 223 Node* load = Load(MachineType::Int8(), BytecodeArrayTaggedPointer(), |
224 IntPtrAdd(BytecodeOffset(), operand_offset)); | 224 IntPtrAdd(BytecodeOffset(), operand_offset)); |
225 | 225 |
226 // Ensure that we sign extend to full pointer size | 226 // Ensure that we sign extend to full pointer size |
227 if (kPointerSize == 8) { | 227 return ChangeInt32ToIntPtr(load); |
228 load = ChangeInt32ToInt64(load); | |
229 } | |
230 return load; | |
231 } | 228 } |
232 | 229 |
233 compiler::Node* InterpreterAssembler::BytecodeOperandReadUnaligned( | 230 compiler::Node* InterpreterAssembler::BytecodeOperandReadUnaligned( |
234 int relative_offset, MachineType result_type) { | 231 int relative_offset, MachineType result_type) { |
235 static const int kMaxCount = 4; | 232 static const int kMaxCount = 4; |
236 DCHECK(!TargetSupportsUnalignedAccess()); | 233 DCHECK(!TargetSupportsUnalignedAccess()); |
237 | 234 |
238 int count; | 235 int count; |
239 switch (result_type.representation()) { | 236 switch (result_type.representation()) { |
240 case MachineRepresentation::kWord16: | 237 case MachineRepresentation::kWord16: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 return result; | 278 return result; |
282 } | 279 } |
283 | 280 |
284 Node* InterpreterAssembler::BytecodeOperandUnsignedShort(int operand_index) { | 281 Node* InterpreterAssembler::BytecodeOperandUnsignedShort(int operand_index) { |
285 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 282 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
286 DCHECK_EQ( | 283 DCHECK_EQ( |
287 OperandSize::kShort, | 284 OperandSize::kShort, |
288 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); | 285 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); |
289 int operand_offset = | 286 int operand_offset = |
290 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); | 287 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
288 Node* load; | |
291 if (TargetSupportsUnalignedAccess()) { | 289 if (TargetSupportsUnalignedAccess()) { |
292 return Load(MachineType::Uint16(), BytecodeArrayTaggedPointer(), | 290 load = Load(MachineType::Uint16(), BytecodeArrayTaggedPointer(), |
293 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); | 291 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
294 } else { | 292 } else { |
295 return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint16()); | 293 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint16()); |
296 } | 294 } |
295 return ChangeUint32ToWord(load); | |
297 } | 296 } |
298 | 297 |
299 Node* InterpreterAssembler::BytecodeOperandSignedShort(int operand_index) { | 298 Node* InterpreterAssembler::BytecodeOperandSignedShort(int operand_index) { |
300 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 299 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
301 DCHECK_EQ( | 300 DCHECK_EQ( |
302 OperandSize::kShort, | 301 OperandSize::kShort, |
303 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); | 302 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); |
304 int operand_offset = | 303 int operand_offset = |
305 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); | 304 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
306 Node* load; | 305 Node* load; |
307 if (TargetSupportsUnalignedAccess()) { | 306 if (TargetSupportsUnalignedAccess()) { |
308 load = Load(MachineType::Int16(), BytecodeArrayTaggedPointer(), | 307 load = Load(MachineType::Int16(), BytecodeArrayTaggedPointer(), |
309 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); | 308 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
310 } else { | 309 } else { |
311 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Int16()); | 310 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Int16()); |
312 } | 311 } |
313 | 312 |
314 // Ensure that we sign extend to full pointer size | 313 // Ensure that we sign extend to full pointer size |
315 if (kPointerSize == 8) { | 314 return ChangeInt32ToIntPtr(load); |
316 load = ChangeInt32ToInt64(load); | |
317 } | |
318 return load; | |
319 } | 315 } |
320 | 316 |
321 Node* InterpreterAssembler::BytecodeOperandUnsignedQuad(int operand_index) { | 317 Node* InterpreterAssembler::BytecodeOperandUnsignedQuad(int operand_index) { |
322 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 318 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
323 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( | 319 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( |
324 bytecode_, operand_index, operand_scale())); | 320 bytecode_, operand_index, operand_scale())); |
325 int operand_offset = | 321 int operand_offset = |
326 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); | 322 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
323 Node* load; | |
327 if (TargetSupportsUnalignedAccess()) { | 324 if (TargetSupportsUnalignedAccess()) { |
328 return Load(MachineType::Uint32(), BytecodeArrayTaggedPointer(), | 325 load = Load(MachineType::Uint32(), BytecodeArrayTaggedPointer(), |
329 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); | 326 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
330 } else { | 327 } else { |
331 return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint32()); | 328 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint32()); |
332 } | 329 } |
330 return ChangeUint32ToWord(load); | |
333 } | 331 } |
334 | 332 |
335 Node* InterpreterAssembler::BytecodeOperandSignedQuad(int operand_index) { | 333 Node* InterpreterAssembler::BytecodeOperandSignedQuad(int operand_index) { |
336 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 334 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
337 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( | 335 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( |
338 bytecode_, operand_index, operand_scale())); | 336 bytecode_, operand_index, operand_scale())); |
339 int operand_offset = | 337 int operand_offset = |
340 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); | 338 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
341 Node* load; | 339 Node* load; |
342 if (TargetSupportsUnalignedAccess()) { | 340 if (TargetSupportsUnalignedAccess()) { |
343 load = Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), | 341 load = Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), |
344 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); | 342 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
345 } else { | 343 } else { |
346 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Int32()); | 344 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Int32()); |
347 } | 345 } |
348 | 346 |
349 // Ensure that we sign extend to full pointer size | 347 // Ensure that we sign extend to full pointer size |
350 if (kPointerSize == 8) { | 348 return ChangeInt32ToIntPtr(load); |
351 load = ChangeInt32ToInt64(load); | |
352 } | |
353 return load; | |
354 } | 349 } |
355 | 350 |
356 Node* InterpreterAssembler::BytecodeSignedOperand(int operand_index, | 351 Node* InterpreterAssembler::BytecodeSignedOperand(int operand_index, |
357 OperandSize operand_size) { | 352 OperandSize operand_size) { |
358 DCHECK(!Bytecodes::IsUnsignedOperandType( | 353 DCHECK(!Bytecodes::IsUnsignedOperandType( |
359 Bytecodes::GetOperandType(bytecode_, operand_index))); | 354 Bytecodes::GetOperandType(bytecode_, operand_index))); |
360 switch (operand_size) { | 355 switch (operand_size) { |
361 case OperandSize::kByte: | 356 case OperandSize::kByte: |
362 return BytecodeOperandSignedByte(operand_index); | 357 return BytecodeOperandSignedByte(operand_index); |
363 case OperandSize::kShort: | 358 case OperandSize::kShort: |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 Bytecodes::GetOperandType(bytecode_, operand_index)); | 445 Bytecodes::GetOperandType(bytecode_, operand_index)); |
451 OperandSize operand_size = | 446 OperandSize operand_size = |
452 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 447 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
453 DCHECK_EQ(operand_size, OperandSize::kByte); | 448 DCHECK_EQ(operand_size, OperandSize::kByte); |
454 return BytecodeUnsignedOperand(operand_index, operand_size); | 449 return BytecodeUnsignedOperand(operand_index, operand_size); |
455 } | 450 } |
456 | 451 |
457 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) { | 452 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) { |
458 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), | 453 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), |
459 BytecodeArray::kConstantPoolOffset); | 454 BytecodeArray::kConstantPoolOffset); |
460 Node* entry_offset = | 455 return LoadFixedArrayElement(constant_pool, index, 0, INTPTR_PARAMETERS); |
461 IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag), | |
462 WordShl(index, kPointerSizeLog2)); | |
463 return Load(MachineType::AnyTagged(), constant_pool, entry_offset); | |
464 } | 456 } |
465 | 457 |
466 Node* InterpreterAssembler::LoadAndUntagConstantPoolEntry(Node* index) { | 458 Node* InterpreterAssembler::LoadAndUntagConstantPoolEntry(Node* index) { |
467 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), | 459 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), |
468 BytecodeArray::kConstantPoolOffset); | 460 BytecodeArray::kConstantPoolOffset); |
461 // TODO(ishell): move the implementation to CSA. | |
469 int offset = FixedArray::kHeaderSize - kHeapObjectTag; | 462 int offset = FixedArray::kHeaderSize - kHeapObjectTag; |
470 #if V8_TARGET_LITTLE_ENDIAN | 463 #if V8_TARGET_LITTLE_ENDIAN |
471 if (Is64()) { | 464 if (Is64()) { |
472 offset += kPointerSize / 2; | 465 offset += kPointerSize / 2; |
473 } | 466 } |
474 #endif | 467 #endif |
475 Node* entry_offset = | 468 Node* entry_offset = |
476 IntPtrAdd(IntPtrConstant(offset), WordShl(index, kPointerSizeLog2)); | 469 IntPtrAdd(IntPtrConstant(offset), WordShl(index, kPointerSizeLog2)); |
477 if (Is64()) { | 470 if (Is64()) { |
478 return ChangeInt32ToInt64( | 471 return ChangeInt32ToInt64( |
(...skipping 29 matching lines...) Expand all Loading... | |
508 stack_pointer_before_call_ = nullptr; | 501 stack_pointer_before_call_ = nullptr; |
509 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, | 502 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, |
510 kUnexpectedStackPointer); | 503 kUnexpectedStackPointer); |
511 } | 504 } |
512 } | 505 } |
513 | 506 |
514 Node* InterpreterAssembler::IncrementCallCount(Node* type_feedback_vector, | 507 Node* InterpreterAssembler::IncrementCallCount(Node* type_feedback_vector, |
515 Node* slot_id) { | 508 Node* slot_id) { |
516 Comment("increment call count"); | 509 Comment("increment call count"); |
517 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); | 510 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); |
518 Node* call_count = | 511 Node* call_count = LoadFixedArrayElement( |
519 LoadFixedArrayElement(type_feedback_vector, call_count_slot); | 512 type_feedback_vector, call_count_slot, 0, INTPTR_PARAMETERS); |
520 Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1))); | 513 Node* new_count = SmiAdd(call_count, SmiConstant(1)); |
521 // Count is Smi, so we don't need a write barrier. | 514 // Count is Smi, so we don't need a write barrier. |
522 return StoreFixedArrayElement(type_feedback_vector, call_count_slot, | 515 return StoreFixedArrayElement(type_feedback_vector, call_count_slot, |
523 new_count, SKIP_WRITE_BARRIER); | 516 new_count, SKIP_WRITE_BARRIER, 0, |
517 INTPTR_PARAMETERS); | |
524 } | 518 } |
525 | 519 |
526 Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, | 520 Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
527 Node* first_arg, Node* arg_count, | 521 Node* first_arg, Node* arg_count, |
528 Node* slot_id, | 522 Node* slot_id, |
529 Node* type_feedback_vector, | 523 Node* type_feedback_vector, |
530 TailCallMode tail_call_mode) { | 524 TailCallMode tail_call_mode) { |
531 // Static checks to assert it is safe to examine the type feedback element. | 525 // Static checks to assert it is safe to examine the type feedback element. |
532 // We don't know that we have a weak cell. We might have a private symbol | 526 // We don't know that we have a weak cell. We might have a private symbol |
533 // or an AllocationSite, but the memory is safe to examine. | 527 // or an AllocationSite, but the memory is safe to examine. |
534 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to | 528 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to |
535 // FixedArray. | 529 // FixedArray. |
536 // WeakCell::kValueOffset - contains a JSFunction or Smi(0) | 530 // WeakCell::kValueOffset - contains a JSFunction or Smi(0) |
537 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not | 531 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not |
538 // computed, meaning that it can't appear to be a pointer. If the low bit is | 532 // computed, meaning that it can't appear to be a pointer. If the low bit is |
539 // 0, then hash is computed, but the 0 bit prevents the field from appearing | 533 // 0, then hash is computed, but the 0 bit prevents the field from appearing |
540 // to be a pointer. | 534 // to be a pointer. |
541 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); | 535 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); |
542 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == | 536 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == |
543 WeakCell::kValueOffset && | 537 WeakCell::kValueOffset && |
544 WeakCell::kValueOffset == Symbol::kHashFieldSlot); | 538 WeakCell::kValueOffset == Symbol::kHashFieldSlot); |
545 | 539 |
540 // Truncate |arg_count| to match the calling convention. | |
541 arg_count = TruncateWordToWord32(arg_count); | |
542 | |
546 Variable return_value(this, MachineRepresentation::kTagged); | 543 Variable return_value(this, MachineRepresentation::kTagged); |
547 Label call_function(this), extra_checks(this, Label::kDeferred), call(this), | 544 Label call_function(this), extra_checks(this, Label::kDeferred), call(this), |
548 end(this); | 545 end(this); |
549 | 546 |
550 // The checks. First, does function match the recorded monomorphic target? | 547 // The checks. First, does function match the recorded monomorphic target? |
551 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); | 548 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id, |
549 0, INTPTR_PARAMETERS); | |
552 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 550 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
553 Node* is_monomorphic = WordEqual(function, feedback_value); | 551 Node* is_monomorphic = WordEqual(function, feedback_value); |
554 GotoUnless(is_monomorphic, &extra_checks); | 552 GotoUnless(is_monomorphic, &extra_checks); |
555 | 553 |
556 // The compare above could have been a SMI/SMI comparison. Guard against | 554 // The compare above could have been a SMI/SMI comparison. Guard against |
557 // this convincing us that we have a monomorphic JSFunction. | 555 // this convincing us that we have a monomorphic JSFunction. |
558 Node* is_smi = TaggedIsSmi(function); | 556 Node* is_smi = TaggedIsSmi(function); |
559 Branch(is_smi, &extra_checks, &call_function); | 557 Branch(is_smi, &extra_checks, &call_function); |
560 | 558 |
561 Bind(&call_function); | 559 Bind(&call_function); |
(...skipping 17 matching lines...) Expand all Loading... | |
579 create_allocation_site(this); | 577 create_allocation_site(this); |
580 | 578 |
581 Comment("check if megamorphic"); | 579 Comment("check if megamorphic"); |
582 // Check if it is a megamorphic target. | 580 // Check if it is a megamorphic target. |
583 Node* is_megamorphic = WordEqual( | 581 Node* is_megamorphic = WordEqual( |
584 feedback_element, | 582 feedback_element, |
585 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | 583 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
586 GotoIf(is_megamorphic, &call); | 584 GotoIf(is_megamorphic, &call); |
587 | 585 |
588 Comment("check if it is an allocation site"); | 586 Comment("check if it is an allocation site"); |
589 Node* is_allocation_site = WordEqual( | 587 GotoUnless(IsAllocationSiteMap(LoadMap(feedback_element)), |
590 LoadMap(feedback_element), LoadRoot(Heap::kAllocationSiteMapRootIndex)); | 588 &check_initialized); |
591 GotoUnless(is_allocation_site, &check_initialized); | |
592 | 589 |
593 // If it is not the Array() function, mark megamorphic. | 590 // If it is not the Array() function, mark megamorphic. |
594 Node* context_slot = LoadContextElement(LoadNativeContext(context), | 591 Node* context_slot = LoadContextElement(LoadNativeContext(context), |
595 Context::ARRAY_FUNCTION_INDEX); | 592 Context::ARRAY_FUNCTION_INDEX); |
596 Node* is_array_function = WordEqual(context_slot, function); | 593 Node* is_array_function = WordEqual(context_slot, function); |
597 GotoUnless(is_array_function, &mark_megamorphic); | 594 GotoUnless(is_array_function, &mark_megamorphic); |
598 | 595 |
599 // It is a monomorphic Array function. Increment the call count. | 596 // It is a monomorphic Array function. Increment the call count. |
600 IncrementCallCount(type_feedback_vector, slot_id); | 597 IncrementCallCount(type_feedback_vector, slot_id); |
601 | 598 |
(...skipping 17 matching lines...) Expand all Loading... | |
619 GotoUnless(is_uninitialized, &mark_megamorphic); | 616 GotoUnless(is_uninitialized, &mark_megamorphic); |
620 | 617 |
621 Comment("handle_unitinitialized"); | 618 Comment("handle_unitinitialized"); |
622 // If it is not a JSFunction mark it as megamorphic. | 619 // If it is not a JSFunction mark it as megamorphic. |
623 Node* is_smi = TaggedIsSmi(function); | 620 Node* is_smi = TaggedIsSmi(function); |
624 GotoIf(is_smi, &mark_megamorphic); | 621 GotoIf(is_smi, &mark_megamorphic); |
625 | 622 |
626 // Check if function is an object of JSFunction type. | 623 // Check if function is an object of JSFunction type. |
627 Node* instance_type = LoadInstanceType(function); | 624 Node* instance_type = LoadInstanceType(function); |
628 Node* is_js_function = | 625 Node* is_js_function = |
629 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 626 Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
630 GotoUnless(is_js_function, &mark_megamorphic); | 627 GotoUnless(is_js_function, &mark_megamorphic); |
631 | 628 |
632 // Check if it is the Array() function. | 629 // Check if it is the Array() function. |
633 Node* context_slot = LoadContextElement(LoadNativeContext(context), | 630 Node* context_slot = LoadContextElement(LoadNativeContext(context), |
634 Context::ARRAY_FUNCTION_INDEX); | 631 Context::ARRAY_FUNCTION_INDEX); |
635 Node* is_array_function = WordEqual(context_slot, function); | 632 Node* is_array_function = WordEqual(context_slot, function); |
636 GotoIf(is_array_function, &create_allocation_site); | 633 GotoIf(is_array_function, &create_allocation_site); |
637 | 634 |
638 // Check if the function belongs to the same native context. | 635 // Check if the function belongs to the same native context. |
639 Node* native_context = LoadNativeContext( | 636 Node* native_context = LoadNativeContext( |
(...skipping 22 matching lines...) Expand all Loading... | |
662 | 659 |
663 Bind(&mark_megamorphic); | 660 Bind(&mark_megamorphic); |
664 { | 661 { |
665 // Mark it as a megamorphic. | 662 // Mark it as a megamorphic. |
666 // MegamorphicSentinel is created as a part of Heap::InitialObjects | 663 // MegamorphicSentinel is created as a part of Heap::InitialObjects |
667 // and will not move during a GC. So it is safe to skip write barrier. | 664 // and will not move during a GC. So it is safe to skip write barrier. |
668 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); | 665 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
669 StoreFixedArrayElement( | 666 StoreFixedArrayElement( |
670 type_feedback_vector, slot_id, | 667 type_feedback_vector, slot_id, |
671 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), | 668 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
672 SKIP_WRITE_BARRIER); | 669 SKIP_WRITE_BARRIER, 0, INTPTR_PARAMETERS); |
673 Goto(&call); | 670 Goto(&call); |
674 } | 671 } |
675 } | 672 } |
676 | 673 |
677 Bind(&call); | 674 Bind(&call); |
678 { | 675 { |
679 Comment("Increment call count and call using Call builtin"); | 676 Comment("Increment call count and call using Call builtin"); |
680 // Increment the call count. | 677 // Increment the call count. |
681 IncrementCallCount(type_feedback_vector, slot_id); | 678 IncrementCallCount(type_feedback_vector, slot_id); |
682 | 679 |
(...skipping 10 matching lines...) Expand all Loading... | |
693 Bind(&end); | 690 Bind(&end); |
694 return return_value.value(); | 691 return return_value.value(); |
695 } | 692 } |
696 | 693 |
697 Node* InterpreterAssembler::CallJS(Node* function, Node* context, | 694 Node* InterpreterAssembler::CallJS(Node* function, Node* context, |
698 Node* first_arg, Node* arg_count, | 695 Node* first_arg, Node* arg_count, |
699 TailCallMode tail_call_mode) { | 696 TailCallMode tail_call_mode) { |
700 Callable callable = CodeFactory::InterpreterPushArgsAndCall( | 697 Callable callable = CodeFactory::InterpreterPushArgsAndCall( |
701 isolate(), tail_call_mode, CallableType::kAny); | 698 isolate(), tail_call_mode, CallableType::kAny); |
702 Node* code_target = HeapConstant(callable.code()); | 699 Node* code_target = HeapConstant(callable.code()); |
700 | |
701 // Truncate |arg_count| to match the calling convention. | |
702 arg_count = TruncateWordToWord32(arg_count); | |
703 | |
703 return CallStub(callable.descriptor(), code_target, context, arg_count, | 704 return CallStub(callable.descriptor(), code_target, context, arg_count, |
704 first_arg, function); | 705 first_arg, function); |
705 } | 706 } |
706 | 707 |
707 Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, | 708 Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, |
708 Node* new_target, Node* first_arg, | 709 Node* new_target, Node* first_arg, |
709 Node* arg_count, Node* slot_id, | 710 Node* arg_count, Node* slot_id, |
710 Node* type_feedback_vector) { | 711 Node* type_feedback_vector) { |
711 Variable return_value(this, MachineRepresentation::kTagged); | 712 Variable return_value(this, MachineRepresentation::kTagged); |
712 Variable allocation_feedback(this, MachineRepresentation::kTagged); | 713 Variable allocation_feedback(this, MachineRepresentation::kTagged); |
713 Label call_construct_function(this, &allocation_feedback), | 714 Label call_construct_function(this, &allocation_feedback), |
714 extra_checks(this, Label::kDeferred), call_construct(this), end(this); | 715 extra_checks(this, Label::kDeferred), call_construct(this), end(this); |
715 | 716 |
717 // Truncate |arg_count| to match the calling convention. | |
718 arg_count = TruncateWordToWord32(arg_count); | |
719 | |
716 // Slot id of 0 is used to indicate no type feedback is available. | 720 // Slot id of 0 is used to indicate no type feedback is available. |
717 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); | 721 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); |
718 Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); | 722 Node* is_feedback_unavailable = WordEqual(slot_id, IntPtrConstant(0)); |
719 GotoIf(is_feedback_unavailable, &call_construct); | 723 GotoIf(is_feedback_unavailable, &call_construct); |
720 | 724 |
721 // Check that the constructor is not a smi. | 725 // Check that the constructor is not a smi. |
722 Node* is_smi = TaggedIsSmi(constructor); | 726 Node* is_smi = TaggedIsSmi(constructor); |
723 GotoIf(is_smi, &call_construct); | 727 GotoIf(is_smi, &call_construct); |
724 | 728 |
725 // Check that constructor is a JSFunction. | 729 // Check that constructor is a JSFunction. |
726 Node* instance_type = LoadInstanceType(constructor); | 730 Node* instance_type = LoadInstanceType(constructor); |
727 Node* is_js_function = | 731 Node* is_js_function = |
728 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 732 Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
729 GotoUnless(is_js_function, &call_construct); | 733 GotoUnless(is_js_function, &call_construct); |
730 | 734 |
731 // Check if it is a monomorphic constructor. | 735 // Check if it is a monomorphic constructor. |
732 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); | 736 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id, |
737 0, INTPTR_PARAMETERS); | |
733 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 738 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
734 Node* is_monomorphic = WordEqual(constructor, feedback_value); | 739 Node* is_monomorphic = WordEqual(constructor, feedback_value); |
735 allocation_feedback.Bind(UndefinedConstant()); | 740 allocation_feedback.Bind(UndefinedConstant()); |
736 Branch(is_monomorphic, &call_construct_function, &extra_checks); | 741 Branch(is_monomorphic, &call_construct_function, &extra_checks); |
737 | 742 |
738 Bind(&call_construct_function); | 743 Bind(&call_construct_function); |
739 { | 744 { |
740 Comment("call using callConstructFunction"); | 745 Comment("call using callConstructFunction"); |
741 IncrementCallCount(type_feedback_vector, slot_id); | 746 IncrementCallCount(type_feedback_vector, slot_id); |
742 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( | 747 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
827 | 832 |
828 Bind(&mark_megamorphic); | 833 Bind(&mark_megamorphic); |
829 { | 834 { |
830 // MegamorphicSentinel is an immortal immovable object so | 835 // MegamorphicSentinel is an immortal immovable object so |
831 // write-barrier is not needed. | 836 // write-barrier is not needed. |
832 Comment("transition to megamorphic"); | 837 Comment("transition to megamorphic"); |
833 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); | 838 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
834 StoreFixedArrayElement( | 839 StoreFixedArrayElement( |
835 type_feedback_vector, slot_id, | 840 type_feedback_vector, slot_id, |
836 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), | 841 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
837 SKIP_WRITE_BARRIER); | 842 SKIP_WRITE_BARRIER, 0, INTPTR_PARAMETERS); |
838 Goto(&call_construct_function); | 843 Goto(&call_construct_function); |
839 } | 844 } |
840 } | 845 } |
841 | 846 |
842 Bind(&call_construct); | 847 Bind(&call_construct); |
843 { | 848 { |
844 Comment("call using callConstruct builtin"); | 849 Comment("call using callConstruct builtin"); |
845 Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( | 850 Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( |
846 isolate(), CallableType::kAny); | 851 isolate(), CallableType::kAny); |
847 Node* code_target = HeapConstant(callable.code()); | 852 Node* code_target = HeapConstant(callable.code()); |
(...skipping 10 matching lines...) Expand all Loading... | |
858 Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context, | 863 Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context, |
859 Node* first_arg, Node* arg_count, | 864 Node* first_arg, Node* arg_count, |
860 int result_size) { | 865 int result_size) { |
861 Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size); | 866 Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size); |
862 Node* code_target = HeapConstant(callable.code()); | 867 Node* code_target = HeapConstant(callable.code()); |
863 | 868 |
864 // Get the function entry from the function id. | 869 // Get the function entry from the function id. |
865 Node* function_table = ExternalConstant( | 870 Node* function_table = ExternalConstant( |
866 ExternalReference::runtime_function_table_address(isolate())); | 871 ExternalReference::runtime_function_table_address(isolate())); |
867 Node* function_offset = | 872 Node* function_offset = |
868 Int32Mul(function_id, Int32Constant(sizeof(Runtime::Function))); | 873 IntPtrMul(function_id, IntPtrConstant(sizeof(Runtime::Function))); |
869 Node* function = IntPtrAdd(function_table, function_offset); | 874 Node* function = IntPtrAdd(function_table, function_offset); |
870 Node* function_entry = | 875 Node* function_entry = |
871 Load(MachineType::Pointer(), function, | 876 Load(MachineType::Pointer(), function, |
872 IntPtrConstant(offsetof(Runtime::Function, entry))); | 877 IntPtrConstant(offsetof(Runtime::Function, entry))); |
873 | 878 |
879 // Truncate |arg_count| to match the calling convention. | |
880 arg_count = TruncateWordToWord32(arg_count); | |
881 | |
874 return CallStub(callable.descriptor(), code_target, context, arg_count, | 882 return CallStub(callable.descriptor(), code_target, context, arg_count, |
875 first_arg, function_entry, result_size); | 883 first_arg, function_entry, result_size); |
876 } | 884 } |
877 | 885 |
878 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { | 886 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { |
879 // TODO(rmcilroy): It might be worthwhile to only update the budget for | 887 // TODO(rmcilroy): It might be worthwhile to only update the budget for |
880 // backwards branches. Those are distinguishable by the {JumpLoop} bytecode. | 888 // backwards branches. Those are distinguishable by the {JumpLoop} bytecode. |
881 | 889 |
882 Label ok(this), interrupt_check(this, Label::kDeferred), end(this); | 890 Label ok(this), interrupt_check(this, Label::kDeferred), end(this); |
883 Node* budget_offset = | 891 Node* budget_offset = |
884 IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag); | 892 IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag); |
885 | 893 |
886 // Update budget by |weight| and check if it reaches zero. | 894 // Update budget by |weight| and check if it reaches zero. |
887 Variable new_budget(this, MachineRepresentation::kWord32); | 895 Variable new_budget(this, MachineRepresentation::kWord32); |
888 Node* old_budget = | 896 Node* old_budget = |
889 Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset); | 897 Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset); |
890 new_budget.Bind(Int32Add(old_budget, weight)); | 898 new_budget.Bind(Int32Add(old_budget, TruncateWordToWord32(weight))); |
891 Node* condition = | 899 Node* condition = |
892 Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0)); | 900 Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0)); |
893 Branch(condition, &ok, &interrupt_check); | 901 Branch(condition, &ok, &interrupt_check); |
894 | 902 |
895 // Perform interrupt and reset budget. | 903 // Perform interrupt and reset budget. |
896 Bind(&interrupt_check); | 904 Bind(&interrupt_check); |
897 { | 905 { |
898 CallRuntime(Runtime::kInterrupt, GetContext()); | 906 CallRuntime(Runtime::kInterrupt, GetContext()); |
899 new_budget.Bind(Int32Constant(Interpreter::InterruptBudget())); | 907 new_budget.Bind(Int32Constant(Interpreter::InterruptBudget())); |
900 Goto(&ok); | 908 Goto(&ok); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
948 } | 956 } |
949 | 957 |
950 void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, | 958 void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, |
951 Node* delta) { | 959 Node* delta) { |
952 JumpConditional(WordNotEqual(lhs, rhs), delta); | 960 JumpConditional(WordNotEqual(lhs, rhs), delta); |
953 } | 961 } |
954 | 962 |
955 Node* InterpreterAssembler::LoadBytecode(compiler::Node* bytecode_offset) { | 963 Node* InterpreterAssembler::LoadBytecode(compiler::Node* bytecode_offset) { |
956 Node* bytecode = | 964 Node* bytecode = |
957 Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), bytecode_offset); | 965 Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), bytecode_offset); |
958 if (kPointerSize == 8) { | 966 return ChangeUint32ToWord(bytecode); |
959 bytecode = ChangeUint32ToUint64(bytecode); | |
960 } | |
961 return bytecode; | |
962 } | 967 } |
963 | 968 |
964 Node* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) { | 969 Node* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) { |
965 Label do_inline_star(this), done(this); | 970 Label do_inline_star(this), done(this); |
966 | 971 |
967 Variable var_bytecode(this, MachineType::PointerRepresentation()); | 972 Variable var_bytecode(this, MachineType::PointerRepresentation()); |
968 var_bytecode.Bind(target_bytecode); | 973 var_bytecode.Bind(target_bytecode); |
969 | 974 |
970 Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar)); | 975 Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar)); |
971 Node* is_star = WordEqual(target_bytecode, star_bytecode); | 976 Node* is_star = WordEqual(target_bytecode, star_bytecode); |
(...skipping 22 matching lines...) Expand all Loading... | |
994 StoreRegister(GetAccumulator(), BytecodeOperandReg(0)); | 999 StoreRegister(GetAccumulator(), BytecodeOperandReg(0)); |
995 | 1000 |
996 DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_)); | 1001 DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_)); |
997 | 1002 |
998 Advance(); | 1003 Advance(); |
999 bytecode_ = previous_bytecode; | 1004 bytecode_ = previous_bytecode; |
1000 accumulator_use_ = previous_acc_use; | 1005 accumulator_use_ = previous_acc_use; |
1001 } | 1006 } |
1002 | 1007 |
1003 Node* InterpreterAssembler::Dispatch() { | 1008 Node* InterpreterAssembler::Dispatch() { |
1009 Comment("========= Dispatch"); | |
1004 Node* target_offset = Advance(); | 1010 Node* target_offset = Advance(); |
1005 Node* target_bytecode = LoadBytecode(target_offset); | 1011 Node* target_bytecode = LoadBytecode(target_offset); |
1006 | 1012 |
1007 if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) { | 1013 if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) { |
1008 target_bytecode = StarDispatchLookahead(target_bytecode); | 1014 target_bytecode = StarDispatchLookahead(target_bytecode); |
1009 } | 1015 } |
1010 return DispatchToBytecode(target_bytecode, BytecodeOffset()); | 1016 return DispatchToBytecode(target_bytecode, BytecodeOffset()); |
1011 } | 1017 } |
1012 | 1018 |
1013 Node* InterpreterAssembler::DispatchToBytecode(Node* target_bytecode, | 1019 Node* InterpreterAssembler::DispatchToBytecode(Node* target_bytecode, |
1014 Node* new_bytecode_offset) { | 1020 Node* new_bytecode_offset) { |
1015 if (FLAG_trace_ignition_dispatches) { | 1021 if (FLAG_trace_ignition_dispatches) { |
1016 TraceBytecodeDispatch(target_bytecode); | 1022 TraceBytecodeDispatch(target_bytecode); |
1017 } | 1023 } |
1018 | 1024 |
1019 Node* target_code_entry = | 1025 Node* target_code_entry = |
1020 Load(MachineType::Pointer(), DispatchTableRawPointer(), | 1026 Load(MachineType::Pointer(), DispatchTableRawPointer(), |
1021 WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2))); | 1027 WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2))); |
1022 | 1028 |
1023 return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset); | 1029 return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset); |
1024 } | 1030 } |
1025 | 1031 |
1026 Node* InterpreterAssembler::DispatchToBytecodeHandler(Node* handler, | 1032 Node* InterpreterAssembler::DispatchToBytecodeHandler(Node* handler, |
1027 Node* bytecode_offset) { | 1033 Node* bytecode_offset) { |
1028 Node* handler_entry = | 1034 Node* handler_entry = |
1029 IntPtrAdd(handler, IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); | 1035 IntPtrAdd(BitcastTaggedToWord(handler), |
1036 IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); | |
rmcilroy
2016/12/09 11:21:37
nit - Maybe there should be a CSA helper which con
Igor Sheludko
2016/12/10 00:09:50
Added TODO, will address in a follow-up CL.
| |
1030 return DispatchToBytecodeHandlerEntry(handler_entry, bytecode_offset); | 1037 return DispatchToBytecodeHandlerEntry(handler_entry, bytecode_offset); |
1031 } | 1038 } |
1032 | 1039 |
1033 Node* InterpreterAssembler::DispatchToBytecodeHandlerEntry( | 1040 Node* InterpreterAssembler::DispatchToBytecodeHandlerEntry( |
1034 Node* handler_entry, Node* bytecode_offset) { | 1041 Node* handler_entry, Node* bytecode_offset) { |
1035 InterpreterDispatchDescriptor descriptor(isolate()); | 1042 InterpreterDispatchDescriptor descriptor(isolate()); |
1036 Node* args[] = {GetAccumulatorUnchecked(), bytecode_offset, | 1043 Node* args[] = {GetAccumulatorUnchecked(), bytecode_offset, |
1037 BytecodeArrayTaggedPointer(), DispatchTableRawPointer()}; | 1044 BytecodeArrayTaggedPointer(), DispatchTableRawPointer()}; |
1038 return TailCallBytecodeDispatch(descriptor, handler_entry, args); | 1045 return TailCallBytecodeDispatch(descriptor, handler_entry, args); |
1039 } | 1046 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1160 return var_result.value(); | 1167 return var_result.value(); |
1161 } | 1168 } |
1162 | 1169 |
1163 void InterpreterAssembler::UpdateInterruptBudgetOnReturn() { | 1170 void InterpreterAssembler::UpdateInterruptBudgetOnReturn() { |
1164 // TODO(rmcilroy): Investigate whether it is worth supporting self | 1171 // TODO(rmcilroy): Investigate whether it is worth supporting self |
1165 // optimization of primitive functions like FullCodegen. | 1172 // optimization of primitive functions like FullCodegen. |
1166 | 1173 |
1167 // Update profiling count by -BytecodeOffset to simulate backedge to start of | 1174 // Update profiling count by -BytecodeOffset to simulate backedge to start of |
1168 // function. | 1175 // function. |
1169 Node* profiling_weight = | 1176 Node* profiling_weight = |
1170 Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize), | 1177 IntPtrSub(IntPtrConstant(kHeapObjectTag + BytecodeArray::kHeaderSize), |
1171 BytecodeOffset()); | 1178 BytecodeOffset()); |
1172 UpdateInterruptBudget(profiling_weight); | 1179 UpdateInterruptBudget(profiling_weight); |
1173 } | 1180 } |
1174 | 1181 |
1175 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() { | 1182 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() { |
1176 Node* sp = LoadStackPointer(); | 1183 Node* sp = LoadStackPointer(); |
1177 Node* stack_limit = Load( | 1184 Node* stack_limit = Load( |
1178 MachineType::Pointer(), | 1185 MachineType::Pointer(), |
1179 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); | 1186 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); |
1180 return UintPtrLessThan(sp, stack_limit); | 1187 return UintPtrLessThan(sp, stack_limit); |
1181 } | 1188 } |
1182 | 1189 |
1183 Node* InterpreterAssembler::LoadOSRNestingLevel() { | 1190 Node* InterpreterAssembler::LoadOSRNestingLevel() { |
1184 Node* offset = | 1191 Node* offset = |
1185 IntPtrConstant(BytecodeArray::kOSRNestingLevelOffset - kHeapObjectTag); | 1192 IntPtrConstant(BytecodeArray::kOSRNestingLevelOffset - kHeapObjectTag); |
1186 return Load(MachineType::Int8(), BytecodeArrayTaggedPointer(), offset); | 1193 Node* load = Load(MachineType::Int8(), BytecodeArrayTaggedPointer(), offset); |
1194 // Ensure that we sign extend to full pointer size | |
1195 return ChangeInt32ToIntPtr(load); | |
1187 } | 1196 } |
1188 | 1197 |
1189 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { | 1198 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { |
1190 disable_stack_check_across_call_ = true; | 1199 disable_stack_check_across_call_ = true; |
1191 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); | 1200 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); |
1192 CallRuntime(Runtime::kAbort, GetContext(), abort_id); | 1201 CallRuntime(Runtime::kAbort, GetContext(), abort_id); |
1193 disable_stack_check_across_call_ = false; | 1202 disable_stack_check_across_call_ = false; |
1194 } | 1203 } |
1195 | 1204 |
1196 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, | 1205 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1248 V8_TARGET_ARCH_PPC | 1257 V8_TARGET_ARCH_PPC |
1249 return true; | 1258 return true; |
1250 #else | 1259 #else |
1251 #error "Unknown Architecture" | 1260 #error "Unknown Architecture" |
1252 #endif | 1261 #endif |
1253 } | 1262 } |
1254 | 1263 |
1255 Node* InterpreterAssembler::RegisterCount() { | 1264 Node* InterpreterAssembler::RegisterCount() { |
1256 Node* bytecode_array = LoadRegister(Register::bytecode_array()); | 1265 Node* bytecode_array = LoadRegister(Register::bytecode_array()); |
1257 Node* frame_size = LoadObjectField( | 1266 Node* frame_size = LoadObjectField( |
1258 bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32()); | 1267 bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Uint32()); |
1259 return Word32Sar(frame_size, Int32Constant(kPointerSizeLog2)); | 1268 return WordShr(ChangeUint32ToWord(frame_size), |
1269 IntPtrConstant(kPointerSizeLog2)); | |
1260 } | 1270 } |
1261 | 1271 |
1262 Node* InterpreterAssembler::ExportRegisterFile(Node* array) { | 1272 Node* InterpreterAssembler::ExportRegisterFile(Node* array) { |
1273 Node* register_count = RegisterCount(); | |
1263 if (FLAG_debug_code) { | 1274 if (FLAG_debug_code) { |
1264 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); | 1275 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); |
1265 AbortIfWordNotEqual( | 1276 AbortIfWordNotEqual(array_size, register_count, |
1266 array_size, RegisterCount(), kInvalidRegisterFileInGenerator); | 1277 kInvalidRegisterFileInGenerator); |
1267 } | 1278 } |
1268 | 1279 |
1269 Variable var_index(this, MachineRepresentation::kWord32); | 1280 Variable var_index(this, MachineType::PointerRepresentation()); |
1270 var_index.Bind(Int32Constant(0)); | 1281 var_index.Bind(IntPtrConstant(0)); |
1271 | 1282 |
1272 // Iterate over register file and write values into array. | 1283 // Iterate over register file and write values into array. |
1273 // The mapping of register to array index must match that used in | 1284 // The mapping of register to array index must match that used in |
1274 // BytecodeGraphBuilder::VisitResumeGenerator. | 1285 // BytecodeGraphBuilder::VisitResumeGenerator. |
1275 Label loop(this, &var_index), done_loop(this); | 1286 Label loop(this, &var_index), done_loop(this); |
1276 Goto(&loop); | 1287 Goto(&loop); |
1277 Bind(&loop); | 1288 Bind(&loop); |
1278 { | 1289 { |
1279 Node* index = var_index.value(); | 1290 Node* index = var_index.value(); |
1280 Node* condition = Int32LessThan(index, RegisterCount()); | 1291 GotoUnless(UintPtrLessThan(index, register_count), &done_loop); |
1281 GotoUnless(condition, &done_loop); | |
1282 | 1292 |
1283 Node* reg_index = | 1293 Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index); |
1284 Int32Sub(Int32Constant(Register(0).ToOperand()), index); | 1294 Node* value = LoadRegister(reg_index); |
1285 Node* value = LoadRegister(ChangeInt32ToIntPtr(reg_index)); | |
1286 | 1295 |
1287 StoreFixedArrayElement(array, index, value); | 1296 StoreFixedArrayElement(array, index, value, UPDATE_WRITE_BARRIER, 0, |
1297 INTPTR_PARAMETERS); | |
rmcilroy
2016/12/09 11:21:37
Do you need the extra arguments here, aren't these
Igor Sheludko
2016/12/10 00:09:50
Currently, all Load/StoreFixedXXXArray methods exp
| |
1288 | 1298 |
1289 var_index.Bind(Int32Add(index, Int32Constant(1))); | 1299 var_index.Bind(IntPtrAdd(index, IntPtrConstant(1))); |
1290 Goto(&loop); | 1300 Goto(&loop); |
1291 } | 1301 } |
1292 Bind(&done_loop); | 1302 Bind(&done_loop); |
1293 | 1303 |
1294 return array; | 1304 return array; |
1295 } | 1305 } |
1296 | 1306 |
1297 Node* InterpreterAssembler::ImportRegisterFile(Node* array) { | 1307 Node* InterpreterAssembler::ImportRegisterFile(Node* array) { |
1308 Node* register_count = RegisterCount(); | |
1298 if (FLAG_debug_code) { | 1309 if (FLAG_debug_code) { |
1299 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); | 1310 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); |
1300 AbortIfWordNotEqual( | 1311 AbortIfWordNotEqual(array_size, register_count, |
1301 array_size, RegisterCount(), kInvalidRegisterFileInGenerator); | 1312 kInvalidRegisterFileInGenerator); |
1302 } | 1313 } |
1303 | 1314 |
1304 Variable var_index(this, MachineRepresentation::kWord32); | 1315 Variable var_index(this, MachineType::PointerRepresentation()); |
1305 var_index.Bind(Int32Constant(0)); | 1316 var_index.Bind(IntPtrConstant(0)); |
1306 | 1317 |
1307 // Iterate over array and write values into register file. Also erase the | 1318 // Iterate over array and write values into register file. Also erase the |
1308 // array contents to not keep them alive artificially. | 1319 // array contents to not keep them alive artificially. |
1309 Label loop(this, &var_index), done_loop(this); | 1320 Label loop(this, &var_index), done_loop(this); |
1310 Goto(&loop); | 1321 Goto(&loop); |
1311 Bind(&loop); | 1322 Bind(&loop); |
1312 { | 1323 { |
1313 Node* index = var_index.value(); | 1324 Node* index = var_index.value(); |
1314 Node* condition = Int32LessThan(index, RegisterCount()); | 1325 GotoUnless(UintPtrLessThan(index, register_count), &done_loop); |
1315 GotoUnless(condition, &done_loop); | |
1316 | 1326 |
1317 Node* value = LoadFixedArrayElement(array, index); | 1327 Node* value = LoadFixedArrayElement(array, index, 0, INTPTR_PARAMETERS); |
1318 | 1328 |
1319 Node* reg_index = | 1329 Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index); |
1320 Int32Sub(Int32Constant(Register(0).ToOperand()), index); | 1330 StoreRegister(value, reg_index); |
1321 StoreRegister(value, ChangeInt32ToIntPtr(reg_index)); | |
1322 | 1331 |
1323 StoreFixedArrayElement(array, index, StaleRegisterConstant()); | 1332 StoreFixedArrayElement(array, index, StaleRegisterConstant(), |
1333 UPDATE_WRITE_BARRIER, 0, INTPTR_PARAMETERS); | |
1324 | 1334 |
1325 var_index.Bind(Int32Add(index, Int32Constant(1))); | 1335 var_index.Bind(IntPtrAdd(index, IntPtrConstant(1))); |
1326 Goto(&loop); | 1336 Goto(&loop); |
1327 } | 1337 } |
1328 Bind(&done_loop); | 1338 Bind(&done_loop); |
1329 | 1339 |
1330 return array; | 1340 return array; |
1331 } | 1341 } |
1332 | 1342 |
1333 } // namespace interpreter | 1343 } // namespace interpreter |
1334 } // namespace internal | 1344 } // namespace internal |
1335 } // namespace v8 | 1345 } // namespace v8 |
OLD | NEW |