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 |