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 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 Node* operand_offset = OperandOffset(operand_index); | 213 Node* operand_offset = OperandOffset(operand_index); |
214 return Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), | 214 return Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), |
215 IntPtrAdd(BytecodeOffset(), operand_offset)); | 215 IntPtrAdd(BytecodeOffset(), operand_offset)); |
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 return Load(MachineType::Int8(), BytecodeArrayTaggedPointer(), |
224 IntPtrAdd(BytecodeOffset(), operand_offset)); | 224 IntPtrAdd(BytecodeOffset(), operand_offset)); |
225 | |
226 // Ensure that we sign extend to full pointer size | |
227 if (kPointerSize == 8) { | |
228 load = ChangeInt32ToInt64(load); | |
229 } | |
230 return load; | |
231 } | 225 } |
232 | 226 |
233 compiler::Node* InterpreterAssembler::BytecodeOperandReadUnaligned( | 227 compiler::Node* InterpreterAssembler::BytecodeOperandReadUnaligned( |
234 int relative_offset, MachineType result_type) { | 228 int relative_offset, MachineType result_type) { |
235 static const int kMaxCount = 4; | 229 static const int kMaxCount = 4; |
236 DCHECK(!TargetSupportsUnalignedAccess()); | 230 DCHECK(!TargetSupportsUnalignedAccess()); |
237 | 231 |
238 int count; | 232 int count; |
239 switch (result_type.representation()) { | 233 switch (result_type.representation()) { |
240 case MachineRepresentation::kWord16: | 234 case MachineRepresentation::kWord16: |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 } | 290 } |
297 } | 291 } |
298 | 292 |
299 Node* InterpreterAssembler::BytecodeOperandSignedShort(int operand_index) { | 293 Node* InterpreterAssembler::BytecodeOperandSignedShort(int operand_index) { |
300 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 294 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
301 DCHECK_EQ( | 295 DCHECK_EQ( |
302 OperandSize::kShort, | 296 OperandSize::kShort, |
303 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); | 297 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale())); |
304 int operand_offset = | 298 int operand_offset = |
305 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); | 299 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
306 Node* load; | |
307 if (TargetSupportsUnalignedAccess()) { | 300 if (TargetSupportsUnalignedAccess()) { |
308 load = Load(MachineType::Int16(), BytecodeArrayTaggedPointer(), | 301 return Load(MachineType::Int16(), BytecodeArrayTaggedPointer(), |
309 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); | 302 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
310 } else { | 303 } else { |
311 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Int16()); | 304 return BytecodeOperandReadUnaligned(operand_offset, MachineType::Int16()); |
312 } | 305 } |
313 | |
314 // Ensure that we sign extend to full pointer size | |
315 if (kPointerSize == 8) { | |
316 load = ChangeInt32ToInt64(load); | |
317 } | |
318 return load; | |
319 } | 306 } |
320 | 307 |
321 Node* InterpreterAssembler::BytecodeOperandUnsignedQuad(int operand_index) { | 308 Node* InterpreterAssembler::BytecodeOperandUnsignedQuad(int operand_index) { |
322 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 309 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
323 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( | 310 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( |
324 bytecode_, operand_index, operand_scale())); | 311 bytecode_, operand_index, operand_scale())); |
325 int operand_offset = | 312 int operand_offset = |
326 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); | 313 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
327 if (TargetSupportsUnalignedAccess()) { | 314 if (TargetSupportsUnalignedAccess()) { |
328 return Load(MachineType::Uint32(), BytecodeArrayTaggedPointer(), | 315 return Load(MachineType::Uint32(), BytecodeArrayTaggedPointer(), |
329 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); | 316 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
330 } else { | 317 } else { |
331 return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint32()); | 318 return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint32()); |
332 } | 319 } |
333 } | 320 } |
334 | 321 |
335 Node* InterpreterAssembler::BytecodeOperandSignedQuad(int operand_index) { | 322 Node* InterpreterAssembler::BytecodeOperandSignedQuad(int operand_index) { |
336 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); | 323 DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_)); |
337 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( | 324 DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize( |
338 bytecode_, operand_index, operand_scale())); | 325 bytecode_, operand_index, operand_scale())); |
339 int operand_offset = | 326 int operand_offset = |
340 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); | 327 Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()); |
341 Node* load; | |
342 if (TargetSupportsUnalignedAccess()) { | 328 if (TargetSupportsUnalignedAccess()) { |
343 load = Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), | 329 return Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), |
344 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); | 330 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset))); |
345 } else { | 331 } else { |
346 load = BytecodeOperandReadUnaligned(operand_offset, MachineType::Int32()); | 332 return BytecodeOperandReadUnaligned(operand_offset, MachineType::Int32()); |
347 } | 333 } |
348 | |
349 // Ensure that we sign extend to full pointer size | |
350 if (kPointerSize == 8) { | |
351 load = ChangeInt32ToInt64(load); | |
352 } | |
353 return load; | |
354 } | 334 } |
355 | 335 |
356 Node* InterpreterAssembler::BytecodeSignedOperand(int operand_index, | 336 Node* InterpreterAssembler::BytecodeSignedOperand(int operand_index, |
357 OperandSize operand_size) { | 337 OperandSize operand_size) { |
358 DCHECK(!Bytecodes::IsUnsignedOperandType( | 338 DCHECK(!Bytecodes::IsUnsignedOperandType( |
359 Bytecodes::GetOperandType(bytecode_, operand_index))); | 339 Bytecodes::GetOperandType(bytecode_, operand_index))); |
360 switch (operand_size) { | 340 switch (operand_size) { |
361 case OperandSize::kByte: | 341 case OperandSize::kByte: |
362 return BytecodeOperandSignedByte(operand_index); | 342 return BytecodeOperandSignedByte(operand_index); |
363 case OperandSize::kShort: | 343 case OperandSize::kShort: |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 } | 393 } |
414 | 394 |
415 Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) { | 395 Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) { |
416 DCHECK_EQ(OperandType::kImm, | 396 DCHECK_EQ(OperandType::kImm, |
417 Bytecodes::GetOperandType(bytecode_, operand_index)); | 397 Bytecodes::GetOperandType(bytecode_, operand_index)); |
418 OperandSize operand_size = | 398 OperandSize operand_size = |
419 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 399 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
420 return BytecodeSignedOperand(operand_index, operand_size); | 400 return BytecodeSignedOperand(operand_index, operand_size); |
421 } | 401 } |
422 | 402 |
| 403 Node* InterpreterAssembler::BytecodeOperandImmIntPtr(int operand_index) { |
| 404 return ChangeInt32ToIntPtr(BytecodeOperandImm(operand_index)); |
| 405 } |
| 406 |
| 407 Node* InterpreterAssembler::BytecodeOperandImmSmi(int operand_index) { |
| 408 return SmiFromWord32(BytecodeOperandImm(operand_index)); |
| 409 } |
| 410 |
423 Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) { | 411 Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) { |
424 DCHECK(OperandType::kIdx == | 412 DCHECK(OperandType::kIdx == |
425 Bytecodes::GetOperandType(bytecode_, operand_index)); | 413 Bytecodes::GetOperandType(bytecode_, operand_index)); |
426 OperandSize operand_size = | 414 OperandSize operand_size = |
427 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 415 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
428 return BytecodeUnsignedOperand(operand_index, operand_size); | 416 return ChangeUint32ToWord( |
| 417 BytecodeUnsignedOperand(operand_index, operand_size)); |
| 418 } |
| 419 |
| 420 Node* InterpreterAssembler::BytecodeOperandIdxSmi(int operand_index) { |
| 421 return SmiTag(BytecodeOperandIdx(operand_index)); |
429 } | 422 } |
430 | 423 |
431 Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) { | 424 Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) { |
432 DCHECK(Bytecodes::IsRegisterOperandType( | 425 DCHECK(Bytecodes::IsRegisterOperandType( |
433 Bytecodes::GetOperandType(bytecode_, operand_index))); | 426 Bytecodes::GetOperandType(bytecode_, operand_index))); |
434 OperandSize operand_size = | 427 OperandSize operand_size = |
435 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 428 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
436 return BytecodeSignedOperand(operand_index, operand_size); | 429 return ChangeInt32ToIntPtr( |
| 430 BytecodeSignedOperand(operand_index, operand_size)); |
437 } | 431 } |
438 | 432 |
439 Node* InterpreterAssembler::BytecodeOperandRuntimeId(int operand_index) { | 433 Node* InterpreterAssembler::BytecodeOperandRuntimeId(int operand_index) { |
440 DCHECK(OperandType::kRuntimeId == | 434 DCHECK(OperandType::kRuntimeId == |
441 Bytecodes::GetOperandType(bytecode_, operand_index)); | 435 Bytecodes::GetOperandType(bytecode_, operand_index)); |
442 OperandSize operand_size = | 436 OperandSize operand_size = |
443 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 437 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
444 DCHECK_EQ(operand_size, OperandSize::kShort); | 438 DCHECK_EQ(operand_size, OperandSize::kShort); |
445 return BytecodeUnsignedOperand(operand_index, operand_size); | 439 return BytecodeUnsignedOperand(operand_index, operand_size); |
446 } | 440 } |
447 | 441 |
448 Node* InterpreterAssembler::BytecodeOperandIntrinsicId(int operand_index) { | 442 Node* InterpreterAssembler::BytecodeOperandIntrinsicId(int operand_index) { |
449 DCHECK(OperandType::kIntrinsicId == | 443 DCHECK(OperandType::kIntrinsicId == |
450 Bytecodes::GetOperandType(bytecode_, operand_index)); | 444 Bytecodes::GetOperandType(bytecode_, operand_index)); |
451 OperandSize operand_size = | 445 OperandSize operand_size = |
452 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 446 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
453 DCHECK_EQ(operand_size, OperandSize::kByte); | 447 DCHECK_EQ(operand_size, OperandSize::kByte); |
454 return BytecodeUnsignedOperand(operand_index, operand_size); | 448 return BytecodeUnsignedOperand(operand_index, operand_size); |
455 } | 449 } |
456 | 450 |
457 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) { | 451 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) { |
458 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), | 452 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), |
459 BytecodeArray::kConstantPoolOffset); | 453 BytecodeArray::kConstantPoolOffset); |
460 Node* entry_offset = | 454 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 } | 455 } |
465 | 456 |
466 Node* InterpreterAssembler::LoadAndUntagConstantPoolEntry(Node* index) { | 457 Node* InterpreterAssembler::LoadAndUntagConstantPoolEntry(Node* index) { |
467 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(), | 458 return SmiUntag(LoadConstantPoolEntry(index)); |
468 BytecodeArray::kConstantPoolOffset); | |
469 int offset = FixedArray::kHeaderSize - kHeapObjectTag; | |
470 #if V8_TARGET_LITTLE_ENDIAN | |
471 if (Is64()) { | |
472 offset += kPointerSize / 2; | |
473 } | |
474 #endif | |
475 Node* entry_offset = | |
476 IntPtrAdd(IntPtrConstant(offset), WordShl(index, kPointerSizeLog2)); | |
477 if (Is64()) { | |
478 return ChangeInt32ToInt64( | |
479 Load(MachineType::Int32(), constant_pool, entry_offset)); | |
480 } else { | |
481 return SmiUntag( | |
482 Load(MachineType::AnyTagged(), constant_pool, entry_offset)); | |
483 } | |
484 } | 459 } |
485 | 460 |
486 Node* InterpreterAssembler::LoadTypeFeedbackVector() { | 461 Node* InterpreterAssembler::LoadTypeFeedbackVector() { |
487 Node* function = LoadRegister(Register::function_closure()); | 462 Node* function = LoadRegister(Register::function_closure()); |
488 Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset); | 463 Node* literals = LoadObjectField(function, JSFunction::kLiteralsOffset); |
489 Node* vector = | 464 Node* vector = |
490 LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset); | 465 LoadObjectField(literals, LiteralsArray::kFeedbackVectorOffset); |
491 return vector; | 466 return vector; |
492 } | 467 } |
493 | 468 |
(...skipping 14 matching lines...) Expand all Loading... |
508 stack_pointer_before_call_ = nullptr; | 483 stack_pointer_before_call_ = nullptr; |
509 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, | 484 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, |
510 kUnexpectedStackPointer); | 485 kUnexpectedStackPointer); |
511 } | 486 } |
512 } | 487 } |
513 | 488 |
514 Node* InterpreterAssembler::IncrementCallCount(Node* type_feedback_vector, | 489 Node* InterpreterAssembler::IncrementCallCount(Node* type_feedback_vector, |
515 Node* slot_id) { | 490 Node* slot_id) { |
516 Comment("increment call count"); | 491 Comment("increment call count"); |
517 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); | 492 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); |
518 Node* call_count = | 493 Node* call_count = LoadFixedArrayElement( |
519 LoadFixedArrayElement(type_feedback_vector, call_count_slot); | 494 type_feedback_vector, call_count_slot, 0, INTPTR_PARAMETERS); |
520 Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1))); | 495 Node* new_count = SmiAdd(call_count, SmiConstant(1)); |
521 // Count is Smi, so we don't need a write barrier. | 496 // Count is Smi, so we don't need a write barrier. |
522 return StoreFixedArrayElement(type_feedback_vector, call_count_slot, | 497 return StoreFixedArrayElement(type_feedback_vector, call_count_slot, |
523 new_count, SKIP_WRITE_BARRIER); | 498 new_count, SKIP_WRITE_BARRIER, 0, |
| 499 INTPTR_PARAMETERS); |
524 } | 500 } |
525 | 501 |
526 Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, | 502 Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
527 Node* first_arg, Node* arg_count, | 503 Node* first_arg, Node* arg_count, |
528 Node* slot_id, | 504 Node* slot_id, |
529 Node* type_feedback_vector, | 505 Node* type_feedback_vector, |
530 TailCallMode tail_call_mode) { | 506 TailCallMode tail_call_mode) { |
531 // Static checks to assert it is safe to examine the type feedback element. | 507 // 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 | 508 // 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. | 509 // or an AllocationSite, but the memory is safe to examine. |
534 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to | 510 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to |
535 // FixedArray. | 511 // FixedArray. |
536 // WeakCell::kValueOffset - contains a JSFunction or Smi(0) | 512 // WeakCell::kValueOffset - contains a JSFunction or Smi(0) |
537 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not | 513 // 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 | 514 // 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 | 515 // 0, then hash is computed, but the 0 bit prevents the field from appearing |
540 // to be a pointer. | 516 // to be a pointer. |
541 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); | 517 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); |
542 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == | 518 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == |
543 WeakCell::kValueOffset && | 519 WeakCell::kValueOffset && |
544 WeakCell::kValueOffset == Symbol::kHashFieldSlot); | 520 WeakCell::kValueOffset == Symbol::kHashFieldSlot); |
545 | 521 |
546 Variable return_value(this, MachineRepresentation::kTagged); | 522 Variable return_value(this, MachineRepresentation::kTagged); |
547 Label call_function(this), extra_checks(this, Label::kDeferred), call(this), | 523 Label call_function(this), extra_checks(this, Label::kDeferred), call(this), |
548 end(this); | 524 end(this); |
549 | 525 |
550 // The checks. First, does function match the recorded monomorphic target? | 526 // The checks. First, does function match the recorded monomorphic target? |
551 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); | 527 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id, |
| 528 0, INTPTR_PARAMETERS); |
552 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 529 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
553 Node* is_monomorphic = WordEqual(function, feedback_value); | 530 Node* is_monomorphic = WordEqual(function, feedback_value); |
554 GotoUnless(is_monomorphic, &extra_checks); | 531 GotoUnless(is_monomorphic, &extra_checks); |
555 | 532 |
556 // The compare above could have been a SMI/SMI comparison. Guard against | 533 // The compare above could have been a SMI/SMI comparison. Guard against |
557 // this convincing us that we have a monomorphic JSFunction. | 534 // this convincing us that we have a monomorphic JSFunction. |
558 Node* is_smi = TaggedIsSmi(function); | 535 Node* is_smi = TaggedIsSmi(function); |
559 Branch(is_smi, &extra_checks, &call_function); | 536 Branch(is_smi, &extra_checks, &call_function); |
560 | 537 |
561 Bind(&call_function); | 538 Bind(&call_function); |
(...skipping 17 matching lines...) Expand all Loading... |
579 create_allocation_site(this); | 556 create_allocation_site(this); |
580 | 557 |
581 Comment("check if megamorphic"); | 558 Comment("check if megamorphic"); |
582 // Check if it is a megamorphic target. | 559 // Check if it is a megamorphic target. |
583 Node* is_megamorphic = WordEqual( | 560 Node* is_megamorphic = WordEqual( |
584 feedback_element, | 561 feedback_element, |
585 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | 562 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
586 GotoIf(is_megamorphic, &call); | 563 GotoIf(is_megamorphic, &call); |
587 | 564 |
588 Comment("check if it is an allocation site"); | 565 Comment("check if it is an allocation site"); |
589 Node* is_allocation_site = WordEqual( | 566 GotoUnless(IsAllocationSiteMap(LoadMap(feedback_element)), |
590 LoadMap(feedback_element), LoadRoot(Heap::kAllocationSiteMapRootIndex)); | 567 &check_initialized); |
591 GotoUnless(is_allocation_site, &check_initialized); | |
592 | 568 |
593 // If it is not the Array() function, mark megamorphic. | 569 // If it is not the Array() function, mark megamorphic. |
594 Node* context_slot = LoadContextElement(LoadNativeContext(context), | 570 Node* context_slot = LoadContextElement(LoadNativeContext(context), |
595 Context::ARRAY_FUNCTION_INDEX); | 571 Context::ARRAY_FUNCTION_INDEX); |
596 Node* is_array_function = WordEqual(context_slot, function); | 572 Node* is_array_function = WordEqual(context_slot, function); |
597 GotoUnless(is_array_function, &mark_megamorphic); | 573 GotoUnless(is_array_function, &mark_megamorphic); |
598 | 574 |
599 // It is a monomorphic Array function. Increment the call count. | 575 // It is a monomorphic Array function. Increment the call count. |
600 IncrementCallCount(type_feedback_vector, slot_id); | 576 IncrementCallCount(type_feedback_vector, slot_id); |
601 | 577 |
(...skipping 17 matching lines...) Expand all Loading... |
619 GotoUnless(is_uninitialized, &mark_megamorphic); | 595 GotoUnless(is_uninitialized, &mark_megamorphic); |
620 | 596 |
621 Comment("handle_unitinitialized"); | 597 Comment("handle_unitinitialized"); |
622 // If it is not a JSFunction mark it as megamorphic. | 598 // If it is not a JSFunction mark it as megamorphic. |
623 Node* is_smi = TaggedIsSmi(function); | 599 Node* is_smi = TaggedIsSmi(function); |
624 GotoIf(is_smi, &mark_megamorphic); | 600 GotoIf(is_smi, &mark_megamorphic); |
625 | 601 |
626 // Check if function is an object of JSFunction type. | 602 // Check if function is an object of JSFunction type. |
627 Node* instance_type = LoadInstanceType(function); | 603 Node* instance_type = LoadInstanceType(function); |
628 Node* is_js_function = | 604 Node* is_js_function = |
629 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 605 Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
630 GotoUnless(is_js_function, &mark_megamorphic); | 606 GotoUnless(is_js_function, &mark_megamorphic); |
631 | 607 |
632 // Check if it is the Array() function. | 608 // Check if it is the Array() function. |
633 Node* context_slot = LoadContextElement(LoadNativeContext(context), | 609 Node* context_slot = LoadContextElement(LoadNativeContext(context), |
634 Context::ARRAY_FUNCTION_INDEX); | 610 Context::ARRAY_FUNCTION_INDEX); |
635 Node* is_array_function = WordEqual(context_slot, function); | 611 Node* is_array_function = WordEqual(context_slot, function); |
636 GotoIf(is_array_function, &create_allocation_site); | 612 GotoIf(is_array_function, &create_allocation_site); |
637 | 613 |
638 // Check if the function belongs to the same native context. | 614 // Check if the function belongs to the same native context. |
639 Node* native_context = LoadNativeContext( | 615 Node* native_context = LoadNativeContext( |
(...skipping 22 matching lines...) Expand all Loading... |
662 | 638 |
663 Bind(&mark_megamorphic); | 639 Bind(&mark_megamorphic); |
664 { | 640 { |
665 // Mark it as a megamorphic. | 641 // Mark it as a megamorphic. |
666 // MegamorphicSentinel is created as a part of Heap::InitialObjects | 642 // 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. | 643 // and will not move during a GC. So it is safe to skip write barrier. |
668 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); | 644 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
669 StoreFixedArrayElement( | 645 StoreFixedArrayElement( |
670 type_feedback_vector, slot_id, | 646 type_feedback_vector, slot_id, |
671 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), | 647 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
672 SKIP_WRITE_BARRIER); | 648 SKIP_WRITE_BARRIER, 0, INTPTR_PARAMETERS); |
673 Goto(&call); | 649 Goto(&call); |
674 } | 650 } |
675 } | 651 } |
676 | 652 |
677 Bind(&call); | 653 Bind(&call); |
678 { | 654 { |
679 Comment("Increment call count and call using Call builtin"); | 655 Comment("Increment call count and call using Call builtin"); |
680 // Increment the call count. | 656 // Increment the call count. |
681 IncrementCallCount(type_feedback_vector, slot_id); | 657 IncrementCallCount(type_feedback_vector, slot_id); |
682 | 658 |
(...skipping 10 matching lines...) Expand all Loading... |
693 Bind(&end); | 669 Bind(&end); |
694 return return_value.value(); | 670 return return_value.value(); |
695 } | 671 } |
696 | 672 |
697 Node* InterpreterAssembler::CallJS(Node* function, Node* context, | 673 Node* InterpreterAssembler::CallJS(Node* function, Node* context, |
698 Node* first_arg, Node* arg_count, | 674 Node* first_arg, Node* arg_count, |
699 TailCallMode tail_call_mode) { | 675 TailCallMode tail_call_mode) { |
700 Callable callable = CodeFactory::InterpreterPushArgsAndCall( | 676 Callable callable = CodeFactory::InterpreterPushArgsAndCall( |
701 isolate(), tail_call_mode, CallableType::kAny); | 677 isolate(), tail_call_mode, CallableType::kAny); |
702 Node* code_target = HeapConstant(callable.code()); | 678 Node* code_target = HeapConstant(callable.code()); |
| 679 |
703 return CallStub(callable.descriptor(), code_target, context, arg_count, | 680 return CallStub(callable.descriptor(), code_target, context, arg_count, |
704 first_arg, function); | 681 first_arg, function); |
705 } | 682 } |
706 | 683 |
707 Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, | 684 Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, |
708 Node* new_target, Node* first_arg, | 685 Node* new_target, Node* first_arg, |
709 Node* arg_count, Node* slot_id, | 686 Node* arg_count, Node* slot_id, |
710 Node* type_feedback_vector) { | 687 Node* type_feedback_vector) { |
711 Variable return_value(this, MachineRepresentation::kTagged); | 688 Variable return_value(this, MachineRepresentation::kTagged); |
712 Variable allocation_feedback(this, MachineRepresentation::kTagged); | 689 Variable allocation_feedback(this, MachineRepresentation::kTagged); |
713 Label call_construct_function(this, &allocation_feedback), | 690 Label call_construct_function(this, &allocation_feedback), |
714 extra_checks(this, Label::kDeferred), call_construct(this), end(this); | 691 extra_checks(this, Label::kDeferred), call_construct(this), end(this); |
715 | 692 |
716 // Slot id of 0 is used to indicate no type feedback is available. | 693 // Slot id of 0 is used to indicate no type feedback is available. |
717 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); | 694 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); |
718 Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); | 695 Node* is_feedback_unavailable = WordEqual(slot_id, IntPtrConstant(0)); |
719 GotoIf(is_feedback_unavailable, &call_construct); | 696 GotoIf(is_feedback_unavailable, &call_construct); |
720 | 697 |
721 // Check that the constructor is not a smi. | 698 // Check that the constructor is not a smi. |
722 Node* is_smi = TaggedIsSmi(constructor); | 699 Node* is_smi = TaggedIsSmi(constructor); |
723 GotoIf(is_smi, &call_construct); | 700 GotoIf(is_smi, &call_construct); |
724 | 701 |
725 // Check that constructor is a JSFunction. | 702 // Check that constructor is a JSFunction. |
726 Node* instance_type = LoadInstanceType(constructor); | 703 Node* instance_type = LoadInstanceType(constructor); |
727 Node* is_js_function = | 704 Node* is_js_function = |
728 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 705 Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
729 GotoUnless(is_js_function, &call_construct); | 706 GotoUnless(is_js_function, &call_construct); |
730 | 707 |
731 // Check if it is a monomorphic constructor. | 708 // Check if it is a monomorphic constructor. |
732 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); | 709 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id, |
| 710 0, INTPTR_PARAMETERS); |
733 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 711 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
734 Node* is_monomorphic = WordEqual(constructor, feedback_value); | 712 Node* is_monomorphic = WordEqual(constructor, feedback_value); |
735 allocation_feedback.Bind(UndefinedConstant()); | 713 allocation_feedback.Bind(UndefinedConstant()); |
736 Branch(is_monomorphic, &call_construct_function, &extra_checks); | 714 Branch(is_monomorphic, &call_construct_function, &extra_checks); |
737 | 715 |
738 Bind(&call_construct_function); | 716 Bind(&call_construct_function); |
739 { | 717 { |
740 Comment("call using callConstructFunction"); | 718 Comment("call using callConstructFunction"); |
741 IncrementCallCount(type_feedback_vector, slot_id); | 719 IncrementCallCount(type_feedback_vector, slot_id); |
742 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( | 720 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 | 805 |
828 Bind(&mark_megamorphic); | 806 Bind(&mark_megamorphic); |
829 { | 807 { |
830 // MegamorphicSentinel is an immortal immovable object so | 808 // MegamorphicSentinel is an immortal immovable object so |
831 // write-barrier is not needed. | 809 // write-barrier is not needed. |
832 Comment("transition to megamorphic"); | 810 Comment("transition to megamorphic"); |
833 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); | 811 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
834 StoreFixedArrayElement( | 812 StoreFixedArrayElement( |
835 type_feedback_vector, slot_id, | 813 type_feedback_vector, slot_id, |
836 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), | 814 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
837 SKIP_WRITE_BARRIER); | 815 SKIP_WRITE_BARRIER, 0, INTPTR_PARAMETERS); |
838 Goto(&call_construct_function); | 816 Goto(&call_construct_function); |
839 } | 817 } |
840 } | 818 } |
841 | 819 |
842 Bind(&call_construct); | 820 Bind(&call_construct); |
843 { | 821 { |
844 Comment("call using callConstruct builtin"); | 822 Comment("call using callConstruct builtin"); |
845 Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( | 823 Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( |
846 isolate(), CallableType::kAny); | 824 isolate(), CallableType::kAny); |
847 Node* code_target = HeapConstant(callable.code()); | 825 Node* code_target = HeapConstant(callable.code()); |
(...skipping 11 matching lines...) Expand all Loading... |
859 Node* first_arg, Node* arg_count, | 837 Node* first_arg, Node* arg_count, |
860 int result_size) { | 838 int result_size) { |
861 Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size); | 839 Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size); |
862 Node* code_target = HeapConstant(callable.code()); | 840 Node* code_target = HeapConstant(callable.code()); |
863 | 841 |
864 // Get the function entry from the function id. | 842 // Get the function entry from the function id. |
865 Node* function_table = ExternalConstant( | 843 Node* function_table = ExternalConstant( |
866 ExternalReference::runtime_function_table_address(isolate())); | 844 ExternalReference::runtime_function_table_address(isolate())); |
867 Node* function_offset = | 845 Node* function_offset = |
868 Int32Mul(function_id, Int32Constant(sizeof(Runtime::Function))); | 846 Int32Mul(function_id, Int32Constant(sizeof(Runtime::Function))); |
869 Node* function = IntPtrAdd(function_table, function_offset); | 847 Node* function = |
| 848 IntPtrAdd(function_table, ChangeUint32ToWord(function_offset)); |
870 Node* function_entry = | 849 Node* function_entry = |
871 Load(MachineType::Pointer(), function, | 850 Load(MachineType::Pointer(), function, |
872 IntPtrConstant(offsetof(Runtime::Function, entry))); | 851 IntPtrConstant(offsetof(Runtime::Function, entry))); |
873 | 852 |
874 return CallStub(callable.descriptor(), code_target, context, arg_count, | 853 return CallStub(callable.descriptor(), code_target, context, arg_count, |
875 first_arg, function_entry, result_size); | 854 first_arg, function_entry, result_size); |
876 } | 855 } |
877 | 856 |
878 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { | 857 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { |
879 // TODO(rmcilroy): It might be worthwhile to only update the budget for | 858 // TODO(rmcilroy): It might be worthwhile to only update the budget for |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); | 899 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); |
921 } | 900 } |
922 Node* next_offset = IntPtrAdd(BytecodeOffset(), delta); | 901 Node* next_offset = IntPtrAdd(BytecodeOffset(), delta); |
923 bytecode_offset_.Bind(next_offset); | 902 bytecode_offset_.Bind(next_offset); |
924 return next_offset; | 903 return next_offset; |
925 } | 904 } |
926 | 905 |
927 Node* InterpreterAssembler::Jump(Node* delta) { | 906 Node* InterpreterAssembler::Jump(Node* delta) { |
928 DCHECK(!Bytecodes::IsStarLookahead(bytecode_, operand_scale_)); | 907 DCHECK(!Bytecodes::IsStarLookahead(bytecode_, operand_scale_)); |
929 | 908 |
930 UpdateInterruptBudget(delta); | 909 UpdateInterruptBudget(TruncateWordToWord32(delta)); |
931 Node* new_bytecode_offset = Advance(delta); | 910 Node* new_bytecode_offset = Advance(delta); |
932 Node* target_bytecode = LoadBytecode(new_bytecode_offset); | 911 Node* target_bytecode = LoadBytecode(new_bytecode_offset); |
933 return DispatchToBytecode(target_bytecode, new_bytecode_offset); | 912 return DispatchToBytecode(target_bytecode, new_bytecode_offset); |
934 } | 913 } |
935 | 914 |
936 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { | 915 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { |
937 Label match(this), no_match(this); | 916 Label match(this), no_match(this); |
938 | 917 |
939 Branch(condition, &match, &no_match); | 918 Branch(condition, &match, &no_match); |
940 Bind(&match); | 919 Bind(&match); |
941 Jump(delta); | 920 Jump(delta); |
942 Bind(&no_match); | 921 Bind(&no_match); |
943 Dispatch(); | 922 Dispatch(); |
944 } | 923 } |
945 | 924 |
946 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { | 925 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { |
947 JumpConditional(WordEqual(lhs, rhs), delta); | 926 JumpConditional(WordEqual(lhs, rhs), delta); |
948 } | 927 } |
949 | 928 |
950 void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, | 929 void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs, |
951 Node* delta) { | 930 Node* delta) { |
952 JumpConditional(WordNotEqual(lhs, rhs), delta); | 931 JumpConditional(WordNotEqual(lhs, rhs), delta); |
953 } | 932 } |
954 | 933 |
955 Node* InterpreterAssembler::LoadBytecode(compiler::Node* bytecode_offset) { | 934 Node* InterpreterAssembler::LoadBytecode(compiler::Node* bytecode_offset) { |
956 Node* bytecode = | 935 Node* bytecode = |
957 Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), bytecode_offset); | 936 Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), bytecode_offset); |
958 if (kPointerSize == 8) { | 937 return ChangeUint32ToWord(bytecode); |
959 bytecode = ChangeUint32ToUint64(bytecode); | |
960 } | |
961 return bytecode; | |
962 } | 938 } |
963 | 939 |
964 Node* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) { | 940 Node* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) { |
965 Label do_inline_star(this), done(this); | 941 Label do_inline_star(this), done(this); |
966 | 942 |
967 Variable var_bytecode(this, MachineType::PointerRepresentation()); | 943 Variable var_bytecode(this, MachineType::PointerRepresentation()); |
968 var_bytecode.Bind(target_bytecode); | 944 var_bytecode.Bind(target_bytecode); |
969 | 945 |
970 Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar)); | 946 Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar)); |
971 Node* is_star = WordEqual(target_bytecode, star_bytecode); | 947 Node* is_star = WordEqual(target_bytecode, star_bytecode); |
(...skipping 22 matching lines...) Expand all Loading... |
994 StoreRegister(GetAccumulator(), BytecodeOperandReg(0)); | 970 StoreRegister(GetAccumulator(), BytecodeOperandReg(0)); |
995 | 971 |
996 DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_)); | 972 DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_)); |
997 | 973 |
998 Advance(); | 974 Advance(); |
999 bytecode_ = previous_bytecode; | 975 bytecode_ = previous_bytecode; |
1000 accumulator_use_ = previous_acc_use; | 976 accumulator_use_ = previous_acc_use; |
1001 } | 977 } |
1002 | 978 |
1003 Node* InterpreterAssembler::Dispatch() { | 979 Node* InterpreterAssembler::Dispatch() { |
| 980 Comment("========= Dispatch"); |
1004 Node* target_offset = Advance(); | 981 Node* target_offset = Advance(); |
1005 Node* target_bytecode = LoadBytecode(target_offset); | 982 Node* target_bytecode = LoadBytecode(target_offset); |
1006 | 983 |
1007 if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) { | 984 if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) { |
1008 target_bytecode = StarDispatchLookahead(target_bytecode); | 985 target_bytecode = StarDispatchLookahead(target_bytecode); |
1009 } | 986 } |
1010 return DispatchToBytecode(target_bytecode, BytecodeOffset()); | 987 return DispatchToBytecode(target_bytecode, BytecodeOffset()); |
1011 } | 988 } |
1012 | 989 |
1013 Node* InterpreterAssembler::DispatchToBytecode(Node* target_bytecode, | 990 Node* InterpreterAssembler::DispatchToBytecode(Node* target_bytecode, |
1014 Node* new_bytecode_offset) { | 991 Node* new_bytecode_offset) { |
1015 if (FLAG_trace_ignition_dispatches) { | 992 if (FLAG_trace_ignition_dispatches) { |
1016 TraceBytecodeDispatch(target_bytecode); | 993 TraceBytecodeDispatch(target_bytecode); |
1017 } | 994 } |
1018 | 995 |
1019 Node* target_code_entry = | 996 Node* target_code_entry = |
1020 Load(MachineType::Pointer(), DispatchTableRawPointer(), | 997 Load(MachineType::Pointer(), DispatchTableRawPointer(), |
1021 WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2))); | 998 WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2))); |
1022 | 999 |
1023 return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset); | 1000 return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset); |
1024 } | 1001 } |
1025 | 1002 |
1026 Node* InterpreterAssembler::DispatchToBytecodeHandler(Node* handler, | 1003 Node* InterpreterAssembler::DispatchToBytecodeHandler(Node* handler, |
1027 Node* bytecode_offset) { | 1004 Node* bytecode_offset) { |
| 1005 // TODO(ishell): Add CSA::CodeEntryPoint(code). |
1028 Node* handler_entry = | 1006 Node* handler_entry = |
1029 IntPtrAdd(handler, IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); | 1007 IntPtrAdd(BitcastTaggedToWord(handler), |
| 1008 IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); |
1030 return DispatchToBytecodeHandlerEntry(handler_entry, bytecode_offset); | 1009 return DispatchToBytecodeHandlerEntry(handler_entry, bytecode_offset); |
1031 } | 1010 } |
1032 | 1011 |
1033 Node* InterpreterAssembler::DispatchToBytecodeHandlerEntry( | 1012 Node* InterpreterAssembler::DispatchToBytecodeHandlerEntry( |
1034 Node* handler_entry, Node* bytecode_offset) { | 1013 Node* handler_entry, Node* bytecode_offset) { |
1035 InterpreterDispatchDescriptor descriptor(isolate()); | 1014 InterpreterDispatchDescriptor descriptor(isolate()); |
1036 Node* args[] = {GetAccumulatorUnchecked(), bytecode_offset, | 1015 Node* args[] = {GetAccumulatorUnchecked(), bytecode_offset, |
1037 BytecodeArrayTaggedPointer(), DispatchTableRawPointer()}; | 1016 BytecodeArrayTaggedPointer(), DispatchTableRawPointer()}; |
1038 return TailCallBytecodeDispatch(descriptor, handler_entry, args); | 1017 return TailCallBytecodeDispatch(descriptor, handler_entry, args); |
1039 } | 1018 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 } | 1140 } |
1162 | 1141 |
1163 void InterpreterAssembler::UpdateInterruptBudgetOnReturn() { | 1142 void InterpreterAssembler::UpdateInterruptBudgetOnReturn() { |
1164 // TODO(rmcilroy): Investigate whether it is worth supporting self | 1143 // TODO(rmcilroy): Investigate whether it is worth supporting self |
1165 // optimization of primitive functions like FullCodegen. | 1144 // optimization of primitive functions like FullCodegen. |
1166 | 1145 |
1167 // Update profiling count by -BytecodeOffset to simulate backedge to start of | 1146 // Update profiling count by -BytecodeOffset to simulate backedge to start of |
1168 // function. | 1147 // function. |
1169 Node* profiling_weight = | 1148 Node* profiling_weight = |
1170 Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize), | 1149 Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize), |
1171 BytecodeOffset()); | 1150 TruncateWordToWord32(BytecodeOffset())); |
1172 UpdateInterruptBudget(profiling_weight); | 1151 UpdateInterruptBudget(profiling_weight); |
1173 } | 1152 } |
1174 | 1153 |
1175 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() { | 1154 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() { |
1176 Node* sp = LoadStackPointer(); | 1155 Node* sp = LoadStackPointer(); |
1177 Node* stack_limit = Load( | 1156 Node* stack_limit = Load( |
1178 MachineType::Pointer(), | 1157 MachineType::Pointer(), |
1179 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); | 1158 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); |
1180 return UintPtrLessThan(sp, stack_limit); | 1159 return UintPtrLessThan(sp, stack_limit); |
1181 } | 1160 } |
1182 | 1161 |
1183 Node* InterpreterAssembler::LoadOSRNestingLevel() { | 1162 Node* InterpreterAssembler::LoadOSRNestingLevel() { |
1184 Node* offset = | 1163 return LoadObjectField(BytecodeArrayTaggedPointer(), |
1185 IntPtrConstant(BytecodeArray::kOSRNestingLevelOffset - kHeapObjectTag); | 1164 BytecodeArray::kOSRNestingLevelOffset, |
1186 return Load(MachineType::Int8(), BytecodeArrayTaggedPointer(), offset); | 1165 MachineType::Int8()); |
1187 } | 1166 } |
1188 | 1167 |
1189 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { | 1168 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { |
1190 disable_stack_check_across_call_ = true; | 1169 disable_stack_check_across_call_ = true; |
1191 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); | 1170 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); |
1192 CallRuntime(Runtime::kAbort, GetContext(), abort_id); | 1171 CallRuntime(Runtime::kAbort, GetContext(), abort_id); |
1193 disable_stack_check_across_call_ = false; | 1172 disable_stack_check_across_call_ = false; |
1194 } | 1173 } |
1195 | 1174 |
1196 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, | 1175 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 | 1227 V8_TARGET_ARCH_PPC |
1249 return true; | 1228 return true; |
1250 #else | 1229 #else |
1251 #error "Unknown Architecture" | 1230 #error "Unknown Architecture" |
1252 #endif | 1231 #endif |
1253 } | 1232 } |
1254 | 1233 |
1255 Node* InterpreterAssembler::RegisterCount() { | 1234 Node* InterpreterAssembler::RegisterCount() { |
1256 Node* bytecode_array = LoadRegister(Register::bytecode_array()); | 1235 Node* bytecode_array = LoadRegister(Register::bytecode_array()); |
1257 Node* frame_size = LoadObjectField( | 1236 Node* frame_size = LoadObjectField( |
1258 bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32()); | 1237 bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Uint32()); |
1259 return Word32Sar(frame_size, Int32Constant(kPointerSizeLog2)); | 1238 return WordShr(ChangeUint32ToWord(frame_size), |
| 1239 IntPtrConstant(kPointerSizeLog2)); |
1260 } | 1240 } |
1261 | 1241 |
1262 Node* InterpreterAssembler::ExportRegisterFile(Node* array) { | 1242 Node* InterpreterAssembler::ExportRegisterFile(Node* array) { |
| 1243 Node* register_count = RegisterCount(); |
1263 if (FLAG_debug_code) { | 1244 if (FLAG_debug_code) { |
1264 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); | 1245 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); |
1265 AbortIfWordNotEqual( | 1246 AbortIfWordNotEqual(array_size, register_count, |
1266 array_size, RegisterCount(), kInvalidRegisterFileInGenerator); | 1247 kInvalidRegisterFileInGenerator); |
1267 } | 1248 } |
1268 | 1249 |
1269 Variable var_index(this, MachineRepresentation::kWord32); | 1250 Variable var_index(this, MachineType::PointerRepresentation()); |
1270 var_index.Bind(Int32Constant(0)); | 1251 var_index.Bind(IntPtrConstant(0)); |
1271 | 1252 |
1272 // Iterate over register file and write values into array. | 1253 // Iterate over register file and write values into array. |
1273 // The mapping of register to array index must match that used in | 1254 // The mapping of register to array index must match that used in |
1274 // BytecodeGraphBuilder::VisitResumeGenerator. | 1255 // BytecodeGraphBuilder::VisitResumeGenerator. |
1275 Label loop(this, &var_index), done_loop(this); | 1256 Label loop(this, &var_index), done_loop(this); |
1276 Goto(&loop); | 1257 Goto(&loop); |
1277 Bind(&loop); | 1258 Bind(&loop); |
1278 { | 1259 { |
1279 Node* index = var_index.value(); | 1260 Node* index = var_index.value(); |
1280 Node* condition = Int32LessThan(index, RegisterCount()); | 1261 GotoUnless(UintPtrLessThan(index, register_count), &done_loop); |
1281 GotoUnless(condition, &done_loop); | |
1282 | 1262 |
1283 Node* reg_index = | 1263 Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index); |
1284 Int32Sub(Int32Constant(Register(0).ToOperand()), index); | 1264 Node* value = LoadRegister(reg_index); |
1285 Node* value = LoadRegister(ChangeInt32ToIntPtr(reg_index)); | |
1286 | 1265 |
1287 StoreFixedArrayElement(array, index, value); | 1266 StoreFixedArrayElement(array, index, value, UPDATE_WRITE_BARRIER, 0, |
| 1267 INTPTR_PARAMETERS); |
1288 | 1268 |
1289 var_index.Bind(Int32Add(index, Int32Constant(1))); | 1269 var_index.Bind(IntPtrAdd(index, IntPtrConstant(1))); |
1290 Goto(&loop); | 1270 Goto(&loop); |
1291 } | 1271 } |
1292 Bind(&done_loop); | 1272 Bind(&done_loop); |
1293 | 1273 |
1294 return array; | 1274 return array; |
1295 } | 1275 } |
1296 | 1276 |
1297 Node* InterpreterAssembler::ImportRegisterFile(Node* array) { | 1277 Node* InterpreterAssembler::ImportRegisterFile(Node* array) { |
| 1278 Node* register_count = RegisterCount(); |
1298 if (FLAG_debug_code) { | 1279 if (FLAG_debug_code) { |
1299 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); | 1280 Node* array_size = LoadAndUntagFixedArrayBaseLength(array); |
1300 AbortIfWordNotEqual( | 1281 AbortIfWordNotEqual(array_size, register_count, |
1301 array_size, RegisterCount(), kInvalidRegisterFileInGenerator); | 1282 kInvalidRegisterFileInGenerator); |
1302 } | 1283 } |
1303 | 1284 |
1304 Variable var_index(this, MachineRepresentation::kWord32); | 1285 Variable var_index(this, MachineType::PointerRepresentation()); |
1305 var_index.Bind(Int32Constant(0)); | 1286 var_index.Bind(IntPtrConstant(0)); |
1306 | 1287 |
1307 // Iterate over array and write values into register file. Also erase the | 1288 // Iterate over array and write values into register file. Also erase the |
1308 // array contents to not keep them alive artificially. | 1289 // array contents to not keep them alive artificially. |
1309 Label loop(this, &var_index), done_loop(this); | 1290 Label loop(this, &var_index), done_loop(this); |
1310 Goto(&loop); | 1291 Goto(&loop); |
1311 Bind(&loop); | 1292 Bind(&loop); |
1312 { | 1293 { |
1313 Node* index = var_index.value(); | 1294 Node* index = var_index.value(); |
1314 Node* condition = Int32LessThan(index, RegisterCount()); | 1295 GotoUnless(UintPtrLessThan(index, register_count), &done_loop); |
1315 GotoUnless(condition, &done_loop); | |
1316 | 1296 |
1317 Node* value = LoadFixedArrayElement(array, index); | 1297 Node* value = LoadFixedArrayElement(array, index, 0, INTPTR_PARAMETERS); |
1318 | 1298 |
1319 Node* reg_index = | 1299 Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index); |
1320 Int32Sub(Int32Constant(Register(0).ToOperand()), index); | 1300 StoreRegister(value, reg_index); |
1321 StoreRegister(value, ChangeInt32ToIntPtr(reg_index)); | |
1322 | 1301 |
1323 StoreFixedArrayElement(array, index, StaleRegisterConstant()); | 1302 StoreFixedArrayElement(array, index, StaleRegisterConstant(), |
| 1303 UPDATE_WRITE_BARRIER, 0, INTPTR_PARAMETERS); |
1324 | 1304 |
1325 var_index.Bind(Int32Add(index, Int32Constant(1))); | 1305 var_index.Bind(IntPtrAdd(index, IntPtrConstant(1))); |
1326 Goto(&loop); | 1306 Goto(&loop); |
1327 } | 1307 } |
1328 Bind(&done_loop); | 1308 Bind(&done_loop); |
1329 | 1309 |
1330 return array; | 1310 return array; |
1331 } | 1311 } |
1332 | 1312 |
1333 } // namespace interpreter | 1313 } // namespace interpreter |
1334 } // namespace internal | 1314 } // namespace internal |
1335 } // namespace v8 | 1315 } // namespace v8 |
OLD | NEW |