| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/ic/handler-compiler.h" | 7 #include "src/ic/handler-compiler.h" |
| 8 | 8 |
| 9 #include "src/api-arguments.h" | 9 #include "src/api-arguments.h" |
| 10 #include "src/field-type.h" | 10 #include "src/field-type.h" |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 Register PropertyHandlerCompiler::CheckPrototypes( | 460 Register PropertyHandlerCompiler::CheckPrototypes( |
| 461 Register object_reg, Register holder_reg, Register scratch1, | 461 Register object_reg, Register holder_reg, Register scratch1, |
| 462 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, | 462 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
| 463 ReturnHolder return_what) { | 463 ReturnHolder return_what) { |
| 464 Handle<Map> receiver_map = map(); | 464 Handle<Map> receiver_map = map(); |
| 465 | 465 |
| 466 // object_reg and holder_reg registers can alias. | 466 // object_reg and holder_reg registers can alias. |
| 467 DCHECK(!AreAliased(object_reg, scratch1, scratch2)); | 467 DCHECK(!AreAliased(object_reg, scratch1, scratch2)); |
| 468 DCHECK(!AreAliased(holder_reg, scratch1, scratch2)); | 468 DCHECK(!AreAliased(holder_reg, scratch1, scratch2)); |
| 469 | 469 |
| 470 if (FLAG_eliminate_prototype_chain_checks) { | 470 Handle<Cell> validity_cell = |
| 471 Handle<Cell> validity_cell = | 471 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| 472 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | 472 if (!validity_cell.is_null()) { |
| 473 if (!validity_cell.is_null()) { | 473 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); |
| 474 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), | 474 __ Mov(scratch1, Operand(validity_cell)); |
| 475 validity_cell->value()); | 475 __ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
| 476 __ Mov(scratch1, Operand(validity_cell)); | 476 __ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid))); |
| 477 __ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); | 477 __ B(ne, miss); |
| 478 __ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid))); | 478 } |
| 479 __ B(ne, miss); | |
| 480 } | |
| 481 | 479 |
| 482 // The prototype chain of primitives (and their JSValue wrappers) depends | 480 // The prototype chain of primitives (and their JSValue wrappers) depends |
| 483 // on the native context, which can't be guarded by validity cells. | 481 // on the native context, which can't be guarded by validity cells. |
| 484 // |object_reg| holds the native context specific prototype in this case; | 482 // |object_reg| holds the native context specific prototype in this case; |
| 485 // we need to check its map. | 483 // we need to check its map. |
| 486 if (check == CHECK_ALL_MAPS) { | 484 if (check == CHECK_ALL_MAPS) { |
| 487 __ Ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 485 __ Ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 488 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | 486 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 489 __ CmpWeakValue(scratch1, cell, scratch2); | 487 __ CmpWeakValue(scratch1, cell, scratch2); |
| 490 __ B(ne, miss); | 488 __ B(ne, miss); |
| 491 } | |
| 492 } | 489 } |
| 493 | 490 |
| 494 // Keep track of the current object in register reg. | 491 // Keep track of the current object in register reg. |
| 495 Register reg = object_reg; | 492 Register reg = object_reg; |
| 496 int depth = 0; | 493 int depth = 0; |
| 497 | 494 |
| 498 Handle<JSObject> current = Handle<JSObject>::null(); | 495 Handle<JSObject> current = Handle<JSObject>::null(); |
| 499 if (receiver_map->IsJSGlobalObjectMap()) { | 496 if (receiver_map->IsJSGlobalObjectMap()) { |
| 500 current = isolate()->global_object(); | 497 current = isolate()->global_object(); |
| 501 } | 498 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 518 // fast and global objects or do negative lookup for normal objects. | 515 // fast and global objects or do negative lookup for normal objects. |
| 519 while (!current_map.is_identical_to(holder_map)) { | 516 while (!current_map.is_identical_to(holder_map)) { |
| 520 ++depth; | 517 ++depth; |
| 521 | 518 |
| 522 // Only global objects and objects that do not require access | 519 // Only global objects and objects that do not require access |
| 523 // checks are allowed in stubs. | 520 // checks are allowed in stubs. |
| 524 DCHECK(current_map->IsJSGlobalProxyMap() || | 521 DCHECK(current_map->IsJSGlobalProxyMap() || |
| 525 !current_map->is_access_check_needed()); | 522 !current_map->is_access_check_needed()); |
| 526 | 523 |
| 527 prototype = handle(JSObject::cast(current_map->prototype())); | 524 prototype = handle(JSObject::cast(current_map->prototype())); |
| 528 if (current_map->is_dictionary_map() && | 525 if (current_map->IsJSGlobalObjectMap()) { |
| 529 !current_map->IsJSGlobalObjectMap()) { | 526 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
| 527 name, scratch2, miss); |
| 528 } else if (current_map->is_dictionary_map()) { |
| 530 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 529 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
| 531 if (!name->IsUniqueName()) { | 530 if (!name->IsUniqueName()) { |
| 532 DCHECK(name->IsString()); | 531 DCHECK(name->IsString()); |
| 533 name = factory()->InternalizeString(Handle<String>::cast(name)); | 532 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 534 } | 533 } |
| 535 DCHECK(current.is_null() || (current->property_dictionary()->FindEntry( | 534 DCHECK(current.is_null() || (current->property_dictionary()->FindEntry( |
| 536 name) == NameDictionary::kNotFound)); | 535 name) == NameDictionary::kNotFound)); |
| 537 | 536 |
| 538 if (FLAG_eliminate_prototype_chain_checks && depth > 1) { | 537 if (depth > 1) { |
| 539 // TODO(jkummerow): Cache and re-use weak cell. | 538 // TODO(jkummerow): Cache and re-use weak cell. |
| 540 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); | 539 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 541 } | 540 } |
| 542 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 541 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
| 543 scratch2); | 542 scratch2); |
| 544 | |
| 545 if (!FLAG_eliminate_prototype_chain_checks) { | |
| 546 __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 547 __ Ldr(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
| 548 } | |
| 549 } else { | |
| 550 Register map_reg = scratch1; | |
| 551 if (!FLAG_eliminate_prototype_chain_checks) { | |
| 552 __ Ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 553 } | |
| 554 if (current_map->IsJSGlobalObjectMap()) { | |
| 555 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | |
| 556 name, scratch2, miss); | |
| 557 } else if (!FLAG_eliminate_prototype_chain_checks && | |
| 558 (depth != 1 || check == CHECK_ALL_MAPS)) { | |
| 559 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | |
| 560 __ CmpWeakValue(map_reg, cell, scratch2); | |
| 561 __ B(ne, miss); | |
| 562 } | |
| 563 if (!FLAG_eliminate_prototype_chain_checks) { | |
| 564 __ Ldr(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | |
| 565 } | |
| 566 } | 543 } |
| 567 | 544 |
| 568 reg = holder_reg; // From now on the object will be in holder_reg. | 545 reg = holder_reg; // From now on the object will be in holder_reg. |
| 569 // Go to the next object in the prototype chain. | 546 // Go to the next object in the prototype chain. |
| 570 current = prototype; | 547 current = prototype; |
| 571 current_map = handle(current->map()); | 548 current_map = handle(current->map()); |
| 572 } | 549 } |
| 573 | 550 |
| 574 DCHECK(!current_map->IsJSGlobalProxyMap()); | 551 DCHECK(!current_map->IsJSGlobalProxyMap()); |
| 575 | 552 |
| 576 // Log the check depth. | 553 // Log the check depth. |
| 577 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 554 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 578 | 555 |
| 579 if (!FLAG_eliminate_prototype_chain_checks && | |
| 580 (depth != 0 || check == CHECK_ALL_MAPS)) { | |
| 581 // Check the holder map. | |
| 582 __ Ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 583 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | |
| 584 __ CmpWeakValue(scratch1, cell, scratch2); | |
| 585 __ B(ne, miss); | |
| 586 } | |
| 587 | |
| 588 bool return_holder = return_what == RETURN_HOLDER; | 556 bool return_holder = return_what == RETURN_HOLDER; |
| 589 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { | 557 if (return_holder && depth != 0) { |
| 590 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); | 558 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 591 } | 559 } |
| 592 | 560 |
| 593 // Return the register containing the holder. | 561 // Return the register containing the holder. |
| 594 return return_holder ? reg : no_reg; | 562 return return_holder ? reg : no_reg; |
| 595 } | 563 } |
| 596 | 564 |
| 597 | 565 |
| 598 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 566 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 599 if (!miss->is_unused()) { | 567 if (!miss->is_unused()) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 // Return the generated code. | 702 // Return the generated code. |
| 735 return GetCode(kind(), name); | 703 return GetCode(kind(), name); |
| 736 } | 704 } |
| 737 | 705 |
| 738 | 706 |
| 739 #undef __ | 707 #undef __ |
| 740 } // namespace internal | 708 } // namespace internal |
| 741 } // namespace v8 | 709 } // namespace v8 |
| 742 | 710 |
| 743 #endif // V8_TARGET_ARCH_IA32 | 711 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |