| 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 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 DCHECK(!value_reg.is(scratch)); | 430 DCHECK(!value_reg.is(scratch)); |
| 431 __ JumpIfSmi(value_reg, miss_label); | 431 __ JumpIfSmi(value_reg, miss_label); |
| 432 if (field_type->IsClass()) { | 432 if (field_type->IsClass()) { |
| 433 __ Ldr(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 433 __ Ldr(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
| 434 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), | 434 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), |
| 435 scratch); | 435 scratch); |
| 436 __ B(ne, miss_label); | 436 __ B(ne, miss_label); |
| 437 } | 437 } |
| 438 } | 438 } |
| 439 | 439 |
| 440 | |
| 441 Register PropertyHandlerCompiler::CheckPrototypes( | 440 Register PropertyHandlerCompiler::CheckPrototypes( |
| 442 Register object_reg, Register holder_reg, Register scratch1, | 441 Register object_reg, Register holder_reg, Register scratch1, |
| 443 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, | 442 Register scratch2, Handle<Name> name, Label* miss, |
| 444 ReturnHolder return_what) { | 443 ReturnHolder return_what) { |
| 445 Handle<Map> receiver_map = map(); | 444 Handle<Map> receiver_map = map(); |
| 446 | 445 |
| 447 // object_reg and holder_reg registers can alias. | 446 // object_reg and holder_reg registers can alias. |
| 448 DCHECK(!AreAliased(object_reg, scratch1, scratch2)); | 447 DCHECK(!AreAliased(object_reg, scratch1, scratch2)); |
| 449 DCHECK(!AreAliased(holder_reg, scratch1, scratch2)); | 448 DCHECK(!AreAliased(holder_reg, scratch1, scratch2)); |
| 450 | 449 |
| 451 Handle<Cell> validity_cell = | 450 Handle<Cell> validity_cell = |
| 452 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | 451 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| 453 if (!validity_cell.is_null()) { | 452 if (!validity_cell.is_null()) { |
| 454 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); | 453 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); |
| 455 __ Mov(scratch1, Operand(validity_cell)); | 454 __ Mov(scratch1, Operand(validity_cell)); |
| 456 __ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); | 455 __ Ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
| 457 __ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid))); | 456 __ Cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid))); |
| 458 __ B(ne, miss); | 457 __ B(ne, miss); |
| 459 } | 458 } |
| 460 | 459 |
| 461 // The prototype chain of primitives (and their JSValue wrappers) depends | |
| 462 // on the native context, which can't be guarded by validity cells. | |
| 463 // |object_reg| holds the native context specific prototype in this case; | |
| 464 // we need to check its map. | |
| 465 if (check == CHECK_ALL_MAPS) { | |
| 466 __ Ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | |
| 467 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | |
| 468 __ CmpWeakValue(scratch1, cell, scratch2); | |
| 469 __ B(ne, miss); | |
| 470 } | |
| 471 | |
| 472 // Keep track of the current object in register reg. | 460 // Keep track of the current object in register reg. |
| 473 Register reg = object_reg; | 461 Register reg = object_reg; |
| 474 int depth = 0; | 462 int depth = 0; |
| 475 | 463 |
| 476 Handle<JSObject> current = Handle<JSObject>::null(); | 464 Handle<JSObject> current = Handle<JSObject>::null(); |
| 477 if (receiver_map->IsJSGlobalObjectMap()) { | 465 if (receiver_map->IsJSGlobalObjectMap()) { |
| 478 current = isolate()->global_object(); | 466 current = isolate()->global_object(); |
| 479 } | 467 } |
| 480 | 468 |
| 481 Handle<JSObject> prototype = Handle<JSObject>::null(); | 469 Handle<Map> current_map(receiver_map->GetPrototypeChainRootMap(isolate()), |
| 482 Handle<Map> current_map = receiver_map; | 470 isolate()); |
| 483 Handle<Map> holder_map(holder()->map()); | 471 Handle<Map> holder_map(holder()->map()); |
| 484 // Traverse the prototype chain and check the maps in the prototype chain for | 472 // Traverse the prototype chain and check the maps in the prototype chain for |
| 485 // fast and global objects or do negative lookup for normal objects. | 473 // fast and global objects or do negative lookup for normal objects. |
| 486 while (!current_map.is_identical_to(holder_map)) { | 474 while (!current_map.is_identical_to(holder_map)) { |
| 487 ++depth; | 475 ++depth; |
| 488 | 476 |
| 489 prototype = handle(JSObject::cast(current_map->prototype())); | |
| 490 if (current_map->IsJSGlobalObjectMap()) { | 477 if (current_map->IsJSGlobalObjectMap()) { |
| 491 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 478 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
| 492 name, scratch2, miss); | 479 name, scratch2, miss); |
| 493 } else if (current_map->is_dictionary_map()) { | 480 } else if (current_map->is_dictionary_map()) { |
| 494 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 481 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
| 495 DCHECK(name->IsUniqueName()); | 482 DCHECK(name->IsUniqueName()); |
| 496 DCHECK(current.is_null() || (current->property_dictionary()->FindEntry( | 483 DCHECK(current.is_null() || (current->property_dictionary()->FindEntry( |
| 497 name) == NameDictionary::kNotFound)); | 484 name) == NameDictionary::kNotFound)); |
| 498 | 485 |
| 499 if (depth > 1) { | 486 if (depth > 1) { |
| 500 Handle<WeakCell> weak_cell = | 487 Handle<WeakCell> weak_cell = |
| 501 Map::GetOrCreatePrototypeWeakCell(current, isolate()); | 488 Map::GetOrCreatePrototypeWeakCell(current, isolate()); |
| 502 __ LoadWeakValue(reg, weak_cell, miss); | 489 __ LoadWeakValue(reg, weak_cell, miss); |
| 503 } | 490 } |
| 504 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 491 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
| 505 scratch2); | 492 scratch2); |
| 506 } | 493 } |
| 507 | 494 |
| 508 reg = holder_reg; // From now on the object will be in holder_reg. | 495 reg = holder_reg; // From now on the object will be in holder_reg. |
| 509 // Go to the next object in the prototype chain. | 496 // Go to the next object in the prototype chain. |
| 510 current = prototype; | 497 current = handle(JSObject::cast(current_map->prototype())); |
| 511 current_map = handle(current->map()); | 498 current_map = handle(current->map()); |
| 512 } | 499 } |
| 513 | 500 |
| 514 DCHECK(!current_map->IsJSGlobalProxyMap()); | 501 DCHECK(!current_map->IsJSGlobalProxyMap()); |
| 515 | 502 |
| 516 // Log the check depth. | 503 // Log the check depth. |
| 517 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 504 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 518 | 505 |
| 519 bool return_holder = return_what == RETURN_HOLDER; | 506 bool return_holder = return_what == RETURN_HOLDER; |
| 520 if (return_holder && depth != 0) { | 507 if (return_holder && depth != 0) { |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 // Return the generated code. | 657 // Return the generated code. |
| 671 return GetCode(kind(), name); | 658 return GetCode(kind(), name); |
| 672 } | 659 } |
| 673 | 660 |
| 674 | 661 |
| 675 #undef __ | 662 #undef __ |
| 676 } // namespace internal | 663 } // namespace internal |
| 677 } // namespace v8 | 664 } // namespace v8 |
| 678 | 665 |
| 679 #endif // V8_TARGET_ARCH_IA32 | 666 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |