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_PPC | 7 #if V8_TARGET_ARCH_PPC |
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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 } | 403 } |
404 __ beq(&do_store); | 404 __ beq(&do_store); |
405 } | 405 } |
406 __ bind(&do_store); | 406 __ bind(&do_store); |
407 } | 407 } |
408 } | 408 } |
409 | 409 |
410 | 410 |
411 Register PropertyHandlerCompiler::CheckPrototypes( | 411 Register PropertyHandlerCompiler::CheckPrototypes( |
412 Register object_reg, Register holder_reg, Register scratch1, | 412 Register object_reg, Register holder_reg, Register scratch1, |
413 Register scratch2, Handle<Name> name, Label* miss, | 413 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
414 PrototypeCheckType check) { | 414 ReturnHolder return_what) { |
415 Handle<Map> receiver_map = map(); | 415 Handle<Map> receiver_map = map(); |
416 | 416 |
417 // Make sure there's no overlap between holder and object registers. | 417 // Make sure there's no overlap between holder and object registers. |
418 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 418 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
419 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 419 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
420 !scratch2.is(scratch1)); | 420 !scratch2.is(scratch1)); |
421 | 421 |
| 422 if (FLAG_eliminate_prototype_chain_checks) { |
| 423 Handle<Cell> validity_cell = |
| 424 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| 425 if (!validity_cell.is_null()) { |
| 426 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), |
| 427 validity_cell->value()); |
| 428 __ mov(scratch1, Operand(validity_cell)); |
| 429 __ LoadP(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
| 430 __ CmpSmiLiteral(scratch1, Smi::FromInt(Map::kPrototypeChainValid), r0); |
| 431 __ bne(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 __ LoadP(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 440 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 441 __ CmpWeakValue(scratch1, cell, scratch2); |
| 442 __ b(ne, miss); |
| 443 } |
| 444 } |
| 445 |
422 // Keep track of the current object in register reg. | 446 // Keep track of the current object in register reg. |
423 Register reg = object_reg; | 447 Register reg = object_reg; |
424 int depth = 0; | 448 int depth = 0; |
425 | 449 |
426 Handle<JSObject> current = Handle<JSObject>::null(); | 450 Handle<JSObject> current = Handle<JSObject>::null(); |
427 if (receiver_map->IsJSGlobalObjectMap()) { | 451 if (receiver_map->IsJSGlobalObjectMap()) { |
428 current = isolate()->global_object(); | 452 current = isolate()->global_object(); |
429 } | 453 } |
430 // Check access rights to the global object. This has to happen after | 454 // Check access rights to the global object. This has to happen after |
431 // the map check so that we know that the object is actually a global | 455 // the map check so that we know that the object is actually a global |
(...skipping 23 matching lines...) Expand all Loading... |
455 !current_map->IsJSGlobalObjectMap()) { | 479 !current_map->IsJSGlobalObjectMap()) { |
456 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 480 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
457 if (!name->IsUniqueName()) { | 481 if (!name->IsUniqueName()) { |
458 DCHECK(name->IsString()); | 482 DCHECK(name->IsString()); |
459 name = factory()->InternalizeString(Handle<String>::cast(name)); | 483 name = factory()->InternalizeString(Handle<String>::cast(name)); |
460 } | 484 } |
461 DCHECK(current.is_null() || | 485 DCHECK(current.is_null() || |
462 current->property_dictionary()->FindEntry(name) == | 486 current->property_dictionary()->FindEntry(name) == |
463 NameDictionary::kNotFound); | 487 NameDictionary::kNotFound); |
464 | 488 |
| 489 if (FLAG_eliminate_prototype_chain_checks && depth > 1) { |
| 490 // TODO(jkummerow): Cache and re-use weak cell. |
| 491 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 492 } |
465 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 493 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
466 scratch2); | 494 scratch2); |
467 | 495 if (!FLAG_eliminate_prototype_chain_checks) { |
468 __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 496 __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
469 reg = holder_reg; // From now on the object will be in holder_reg. | 497 __ LoadP(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
470 __ LoadP(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 498 } |
471 } else { | 499 } else { |
472 Register map_reg = scratch1; | 500 Register map_reg = scratch1; |
473 __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 501 if (!FLAG_eliminate_prototype_chain_checks) { |
474 | 502 __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 503 } |
475 if (current_map->IsJSGlobalObjectMap()) { | 504 if (current_map->IsJSGlobalObjectMap()) { |
476 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 505 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
477 name, scratch2, miss); | 506 name, scratch2, miss); |
478 } else if (depth != 1 || check == CHECK_ALL_MAPS) { | 507 } else if (!FLAG_eliminate_prototype_chain_checks && |
| 508 (depth != 1 || check == CHECK_ALL_MAPS)) { |
479 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 509 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
480 __ CmpWeakValue(map_reg, cell, scratch2); | 510 __ CmpWeakValue(map_reg, cell, scratch2); |
481 __ bne(miss); | 511 __ bne(miss); |
482 } | 512 } |
483 | 513 if (!FLAG_eliminate_prototype_chain_checks) { |
484 reg = holder_reg; // From now on the object will be in holder_reg. | 514 __ LoadP(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
485 | 515 } |
486 __ LoadP(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | |
487 } | 516 } |
488 | 517 |
| 518 reg = holder_reg; // From now on the object will be in holder_reg. |
489 // Go to the next object in the prototype chain. | 519 // Go to the next object in the prototype chain. |
490 current = prototype; | 520 current = prototype; |
491 current_map = handle(current->map()); | 521 current_map = handle(current->map()); |
492 } | 522 } |
493 | 523 |
| 524 DCHECK(!current_map->IsJSGlobalProxyMap()); |
| 525 |
494 // Log the check depth. | 526 // Log the check depth. |
495 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 527 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
496 | 528 |
497 if (depth != 0 || check == CHECK_ALL_MAPS) { | 529 if (!FLAG_eliminate_prototype_chain_checks && |
| 530 (depth != 0 || check == CHECK_ALL_MAPS)) { |
498 // Check the holder map. | 531 // Check the holder map. |
499 __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 532 __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
500 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 533 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
501 __ CmpWeakValue(scratch1, cell, scratch2); | 534 __ CmpWeakValue(scratch1, cell, scratch2); |
502 __ bne(miss); | 535 __ bne(miss); |
503 } | 536 } |
504 | 537 |
| 538 bool return_holder = return_what == RETURN_HOLDER; |
| 539 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { |
| 540 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 541 } |
| 542 |
505 // Return the register containing the holder. | 543 // Return the register containing the holder. |
506 return reg; | 544 return return_holder ? reg : no_reg; |
507 } | 545 } |
508 | 546 |
509 | 547 |
510 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 548 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
511 if (!miss->is_unused()) { | 549 if (!miss->is_unused()) { |
512 Label success; | 550 Label success; |
513 __ b(&success); | 551 __ b(&success); |
514 __ bind(miss); | 552 __ bind(miss); |
515 if (IC::ICUseVector(kind())) { | 553 if (IC::ICUseVector(kind())) { |
516 DCHECK(kind() == Code::LOAD_IC); | 554 DCHECK(kind() == Code::LOAD_IC); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 return StoreDescriptor::ValueRegister(); | 747 return StoreDescriptor::ValueRegister(); |
710 } | 748 } |
711 | 749 |
712 | 750 |
713 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 751 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
714 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 752 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
715 Label miss; | 753 Label miss; |
716 if (IC::ICUseVector(kind())) { | 754 if (IC::ICUseVector(kind())) { |
717 PushVectorAndSlot(); | 755 PushVectorAndSlot(); |
718 } | 756 } |
719 FrontendHeader(receiver(), name, &miss); | 757 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
720 | 758 |
721 // Get the value from the cell. | 759 // Get the value from the cell. |
722 Register result = StoreDescriptor::ValueRegister(); | 760 Register result = StoreDescriptor::ValueRegister(); |
723 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); | 761 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); |
724 __ LoadWeakValue(result, weak_cell, &miss); | 762 __ LoadWeakValue(result, weak_cell, &miss); |
725 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 763 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
726 | 764 |
727 // Check for deleted property if property can actually be deleted. | 765 // Check for deleted property if property can actually be deleted. |
728 if (is_configurable) { | 766 if (is_configurable) { |
729 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 767 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
(...skipping 13 matching lines...) Expand all Loading... |
743 // Return the generated code. | 781 // Return the generated code. |
744 return GetCode(kind(), Code::NORMAL, name); | 782 return GetCode(kind(), Code::NORMAL, name); |
745 } | 783 } |
746 | 784 |
747 | 785 |
748 #undef __ | 786 #undef __ |
749 } | 787 } |
750 } // namespace v8::internal | 788 } // namespace v8::internal |
751 | 789 |
752 #endif // V8_TARGET_ARCH_ARM | 790 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |