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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/ic/call-optimization.h" | 9 #include "src/ic/call-optimization.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 } | 404 } |
405 __ b(eq, &do_store); | 405 __ b(eq, &do_store); |
406 } | 406 } |
407 __ bind(&do_store); | 407 __ bind(&do_store); |
408 } | 408 } |
409 } | 409 } |
410 | 410 |
411 | 411 |
412 Register PropertyHandlerCompiler::CheckPrototypes( | 412 Register PropertyHandlerCompiler::CheckPrototypes( |
413 Register object_reg, Register holder_reg, Register scratch1, | 413 Register object_reg, Register holder_reg, Register scratch1, |
414 Register scratch2, Handle<Name> name, Label* miss, | 414 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
415 PrototypeCheckType check) { | 415 ReturnHolder return_what) { |
416 Handle<Map> receiver_map = map(); | 416 Handle<Map> receiver_map = map(); |
417 | 417 |
418 // Make sure there's no overlap between holder and object registers. | 418 // Make sure there's no overlap between holder and object registers. |
419 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 419 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
420 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 420 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
421 !scratch2.is(scratch1)); | 421 !scratch2.is(scratch1)); |
422 | 422 |
423 if (FLAG_eliminate_prototype_chain_checks) { | |
424 Handle<Cell> validity_cell = | |
425 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); | |
426 if (!validity_cell.is_null()) { | |
427 DCHECK(validity_cell->value() == Smi::FromInt(Map::kPrototypeChainValid)); | |
Toon Verwaest
2015/04/07 09:28:37
DCHECK_EQ
Jakob Kummerow
2015/04/14 09:41:57
Done.
| |
428 __ mov(scratch1, Operand(validity_cell)); | |
429 __ ldr(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); | |
430 __ cmp(scratch1, Operand(Smi::FromInt(Map::kPrototypeChainValid))); | |
431 __ b(ne, miss); | |
432 } | |
433 | |
434 // The prototype chain of primitives (and their JSValue wrappers) depends | |
435 // on the native context, which can't be guarded by validity cells. | |
436 // |object_reg| holds the native context specific prototype in this case; | |
437 // we need to check its map. | |
438 if (check == CHECK_ALL_MAPS) { | |
439 __ ldr(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | |
Toon Verwaest
2015/04/07 09:28:38
I think you just want to rewrite this code (and it
Jakob Kummerow
2015/04/14 09:41:57
Acknowledged.
| |
440 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); | |
441 __ CmpWeakValue(scratch1, cell, scratch2); | |
442 __ b(ne, miss); | |
443 } | |
444 } | |
445 | |
423 // Keep track of the current object in register reg. | 446 // Keep track of the current object in register reg. |
424 Register reg = object_reg; | 447 Register reg = object_reg; |
425 int depth = 0; | 448 int depth = 0; |
426 | 449 |
427 Handle<JSObject> current = Handle<JSObject>::null(); | 450 Handle<JSObject> current = Handle<JSObject>::null(); |
428 if (receiver_map->IsJSGlobalObjectMap()) { | 451 if (receiver_map->IsJSGlobalObjectMap()) { |
429 current = isolate()->global_object(); | 452 current = isolate()->global_object(); |
430 } | 453 } |
431 | 454 |
432 // Check access rights to the global object. This has to happen after | 455 // Check access rights to the global object. This has to happen after |
(...skipping 24 matching lines...) Expand all Loading... | |
457 !current_map->IsJSGlobalObjectMap()) { | 480 !current_map->IsJSGlobalObjectMap()) { |
458 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 481 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
459 if (!name->IsUniqueName()) { | 482 if (!name->IsUniqueName()) { |
460 DCHECK(name->IsString()); | 483 DCHECK(name->IsString()); |
461 name = factory()->InternalizeString(Handle<String>::cast(name)); | 484 name = factory()->InternalizeString(Handle<String>::cast(name)); |
462 } | 485 } |
463 DCHECK(current.is_null() || | 486 DCHECK(current.is_null() || |
464 current->property_dictionary()->FindEntry(name) == | 487 current->property_dictionary()->FindEntry(name) == |
465 NameDictionary::kNotFound); | 488 NameDictionary::kNotFound); |
466 | 489 |
490 if (FLAG_eliminate_prototype_chain_checks && depth > 1) { | |
491 // TODO(jkummerow): Cache and re-use weak cell. | |
492 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); | |
Toon Verwaest
2015/04/07 09:28:37
In the (near) future we should just drop support f
Jakob Kummerow
2015/04/14 09:41:57
Acknowledged.
| |
493 } | |
467 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 494 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
468 scratch2); | 495 scratch2); |
469 | 496 if (!FLAG_eliminate_prototype_chain_checks) { |
470 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 497 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
471 reg = holder_reg; // From now on the object will be in holder_reg. | 498 __ ldr(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
472 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 499 } |
473 } else { | 500 } else { |
474 Register map_reg = scratch1; | 501 Register map_reg = scratch1; |
475 __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 502 if (!FLAG_eliminate_prototype_chain_checks) { |
476 | 503 __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
504 } | |
477 if (current_map->IsJSGlobalObjectMap()) { | 505 if (current_map->IsJSGlobalObjectMap()) { |
478 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 506 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
479 name, scratch2, miss); | 507 name, scratch2, miss); |
480 } else if (depth != 1 || check == CHECK_ALL_MAPS) { | 508 } else if (!FLAG_eliminate_prototype_chain_checks && |
509 (depth != 1 || check == CHECK_ALL_MAPS)) { | |
481 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 510 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
482 __ CmpWeakValue(map_reg, cell, scratch2); | 511 __ CmpWeakValue(map_reg, cell, scratch2); |
483 __ b(ne, miss); | 512 __ b(ne, miss); |
484 } | 513 } |
485 | 514 if (!FLAG_eliminate_prototype_chain_checks) { |
486 reg = holder_reg; // From now on the object will be in holder_reg. | 515 __ ldr(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
487 | 516 } |
488 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | |
489 } | 517 } |
490 | 518 |
519 reg = holder_reg; // From now on the object will be in holder_reg. | |
491 // Go to the next object in the prototype chain. | 520 // Go to the next object in the prototype chain. |
492 current = prototype; | 521 current = prototype; |
493 current_map = handle(current->map()); | 522 current_map = handle(current->map()); |
494 } | 523 } |
495 | 524 |
496 DCHECK(!current_map->IsJSGlobalProxyMap()); | 525 DCHECK(!current_map->IsJSGlobalProxyMap()); |
497 | 526 |
498 // Log the check depth. | 527 // Log the check depth. |
499 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 528 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
500 | 529 |
501 if (depth != 0 || check == CHECK_ALL_MAPS) { | 530 if (!FLAG_eliminate_prototype_chain_checks && |
531 (depth != 0 || check == CHECK_ALL_MAPS)) { | |
502 // Check the holder map. | 532 // Check the holder map. |
503 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 533 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
504 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 534 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
505 __ CmpWeakValue(scratch1, cell, scratch2); | 535 __ CmpWeakValue(scratch1, cell, scratch2); |
506 __ b(ne, miss); | 536 __ b(ne, miss); |
507 } | 537 } |
508 | 538 |
539 bool return_holder = return_what == RETURN_HOLDER; | |
540 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { | |
541 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); | |
542 } | |
543 | |
509 // Return the register containing the holder. | 544 // Return the register containing the holder. |
510 return reg; | 545 return return_holder ? reg : no_reg; |
511 } | 546 } |
512 | 547 |
513 | 548 |
514 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 549 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
515 if (!miss->is_unused()) { | 550 if (!miss->is_unused()) { |
516 Label success; | 551 Label success; |
517 __ b(&success); | 552 __ b(&success); |
518 __ bind(miss); | 553 __ bind(miss); |
519 if (IC::ICUseVector(kind())) { | 554 if (IC::ICUseVector(kind())) { |
520 DCHECK(kind() == Code::LOAD_IC); | 555 DCHECK(kind() == Code::LOAD_IC); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
715 return StoreDescriptor::ValueRegister(); | 750 return StoreDescriptor::ValueRegister(); |
716 } | 751 } |
717 | 752 |
718 | 753 |
719 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 754 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
720 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 755 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
721 Label miss; | 756 Label miss; |
722 if (IC::ICUseVector(kind())) { | 757 if (IC::ICUseVector(kind())) { |
723 PushVectorAndSlot(); | 758 PushVectorAndSlot(); |
724 } | 759 } |
725 FrontendHeader(receiver(), name, &miss); | 760 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
726 | 761 |
727 // Get the value from the cell. | 762 // Get the value from the cell. |
728 Register result = StoreDescriptor::ValueRegister(); | 763 Register result = StoreDescriptor::ValueRegister(); |
729 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); | 764 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); |
730 __ LoadWeakValue(result, weak_cell, &miss); | 765 __ LoadWeakValue(result, weak_cell, &miss); |
731 __ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 766 __ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
732 | 767 |
733 // Check for deleted property if property can actually be deleted. | 768 // Check for deleted property if property can actually be deleted. |
734 if (is_configurable) { | 769 if (is_configurable) { |
735 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 770 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
(...skipping 13 matching lines...) Expand all Loading... | |
749 // Return the generated code. | 784 // Return the generated code. |
750 return GetCode(kind(), Code::NORMAL, name); | 785 return GetCode(kind(), Code::NORMAL, name); |
751 } | 786 } |
752 | 787 |
753 | 788 |
754 #undef __ | 789 #undef __ |
755 } | 790 } |
756 } // namespace v8::internal | 791 } // namespace v8::internal |
757 | 792 |
758 #endif // V8_TARGET_ARCH_ARM | 793 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |