| 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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 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 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 } | 395 } |
| 396 __ Branch(&do_store, eq, map_reg, Operand(scratch)); | 396 __ Branch(&do_store, eq, map_reg, Operand(scratch)); |
| 397 } | 397 } |
| 398 __ bind(&do_store); | 398 __ bind(&do_store); |
| 399 } | 399 } |
| 400 } | 400 } |
| 401 | 401 |
| 402 | 402 |
| 403 Register PropertyHandlerCompiler::CheckPrototypes( | 403 Register PropertyHandlerCompiler::CheckPrototypes( |
| 404 Register object_reg, Register holder_reg, Register scratch1, | 404 Register object_reg, Register holder_reg, Register scratch1, |
| 405 Register scratch2, Handle<Name> name, Label* miss, | 405 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
| 406 PrototypeCheckType check) { | 406 ReturnHolder return_what) { |
| 407 Handle<Map> receiver_map = map(); | 407 Handle<Map> receiver_map = map(); |
| 408 | 408 |
| 409 // Make sure there's no overlap between holder and object registers. | 409 // Make sure there's no overlap between holder and object registers. |
| 410 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 410 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 411 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 411 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
| 412 !scratch2.is(scratch1)); | 412 !scratch2.is(scratch1)); |
| 413 | 413 |
| 414 if (FLAG_eliminate_prototype_chain_checks) { |
| 415 Handle<Cell> validity_cell = |
| 416 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); |
| 417 if (!validity_cell.is_null()) { |
| 418 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), |
| 419 validity_cell->value()); |
| 420 __ li(scratch1, Operand(validity_cell)); |
| 421 __ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); |
| 422 __ Branch(miss, ne, scratch1, |
| 423 Operand(Smi::FromInt(Map::kPrototypeChainValid))); |
| 424 } |
| 425 |
| 426 // The prototype chain of primitives (and their JSValue wrappers) depends |
| 427 // on the native context, which can't be guarded by validity cells. |
| 428 // |object_reg| holds the native context specific prototype in this case; |
| 429 // we need to check its map. |
| 430 if (check == CHECK_ALL_MAPS) { |
| 431 __ ld(scratch1, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
| 432 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map); |
| 433 __ GetWeakValue(scratch2, cell); |
| 434 __ Branch(miss, ne, scratch1, Operand(scratch2)); |
| 435 } |
| 436 } |
| 437 |
| 414 // Keep track of the current object in register reg. | 438 // Keep track of the current object in register reg. |
| 415 Register reg = object_reg; | 439 Register reg = object_reg; |
| 416 int depth = 0; | 440 int depth = 0; |
| 417 | 441 |
| 418 Handle<JSObject> current = Handle<JSObject>::null(); | 442 Handle<JSObject> current = Handle<JSObject>::null(); |
| 419 if (receiver_map->IsJSGlobalObjectMap()) { | 443 if (receiver_map->IsJSGlobalObjectMap()) { |
| 420 current = isolate()->global_object(); | 444 current = isolate()->global_object(); |
| 421 } | 445 } |
| 422 | 446 |
| 423 // Check access rights to the global object. This has to happen after | 447 // Check access rights to the global object. This has to happen after |
| (...skipping 24 matching lines...) Expand all Loading... |
| 448 !current_map->IsJSGlobalObjectMap()) { | 472 !current_map->IsJSGlobalObjectMap()) { |
| 449 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. | 473 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. |
| 450 if (!name->IsUniqueName()) { | 474 if (!name->IsUniqueName()) { |
| 451 DCHECK(name->IsString()); | 475 DCHECK(name->IsString()); |
| 452 name = factory()->InternalizeString(Handle<String>::cast(name)); | 476 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 453 } | 477 } |
| 454 DCHECK(current.is_null() || | 478 DCHECK(current.is_null() || |
| 455 current->property_dictionary()->FindEntry(name) == | 479 current->property_dictionary()->FindEntry(name) == |
| 456 NameDictionary::kNotFound); | 480 NameDictionary::kNotFound); |
| 457 | 481 |
| 482 if (FLAG_eliminate_prototype_chain_checks && depth > 1) { |
| 483 // TODO(jkummerow): Cache and re-use weak cell. |
| 484 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 485 } |
| 458 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 486 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
| 459 scratch2); | 487 scratch2); |
| 460 | 488 if (!FLAG_eliminate_prototype_chain_checks) { |
| 461 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 489 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 462 reg = holder_reg; // From now on the object will be in holder_reg. | 490 __ ld(holder_reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
| 463 __ ld(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 491 } |
| 464 } else { | 492 } else { |
| 465 Register map_reg = scratch1; | 493 Register map_reg = scratch1; |
| 466 __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 494 if (!FLAG_eliminate_prototype_chain_checks) { |
| 467 | 495 __ ld(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 496 } |
| 468 if (current_map->IsJSGlobalObjectMap()) { | 497 if (current_map->IsJSGlobalObjectMap()) { |
| 469 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 498 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
| 470 name, scratch2, miss); | 499 name, scratch2, miss); |
| 471 } else if (depth != 1 || check == CHECK_ALL_MAPS) { | 500 } else if (!FLAG_eliminate_prototype_chain_checks && |
| 501 (depth != 1 || check == CHECK_ALL_MAPS)) { |
| 472 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 502 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
| 473 __ GetWeakValue(scratch2, cell); | 503 __ GetWeakValue(scratch2, cell); |
| 474 __ Branch(miss, ne, scratch2, Operand(map_reg)); | 504 __ Branch(miss, ne, scratch2, Operand(map_reg)); |
| 475 } | 505 } |
| 476 | 506 if (!FLAG_eliminate_prototype_chain_checks) { |
| 477 reg = holder_reg; // From now on the object will be in holder_reg. | 507 __ ld(holder_reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
| 478 | 508 } |
| 479 __ ld(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | |
| 480 } | 509 } |
| 481 | 510 |
| 511 reg = holder_reg; // From now on the object will be in holder_reg. |
| 482 // Go to the next object in the prototype chain. | 512 // Go to the next object in the prototype chain. |
| 483 current = prototype; | 513 current = prototype; |
| 484 current_map = handle(current->map()); | 514 current_map = handle(current->map()); |
| 485 } | 515 } |
| 486 | 516 |
| 487 DCHECK(!current_map->IsJSGlobalProxyMap()); | 517 DCHECK(!current_map->IsJSGlobalProxyMap()); |
| 488 | 518 |
| 489 // Log the check depth. | 519 // Log the check depth. |
| 490 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 520 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 491 | 521 |
| 492 if (depth != 0 || check == CHECK_ALL_MAPS) { | 522 if (!FLAG_eliminate_prototype_chain_checks && |
| 523 (depth != 0 || check == CHECK_ALL_MAPS)) { |
| 493 // Check the holder map. | 524 // Check the holder map. |
| 494 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 525 __ ld(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 495 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); | 526 Handle<WeakCell> cell = Map::WeakCellForMap(current_map); |
| 496 __ GetWeakValue(scratch2, cell); | 527 __ GetWeakValue(scratch2, cell); |
| 497 __ Branch(miss, ne, scratch2, Operand(scratch1)); | 528 __ Branch(miss, ne, scratch2, Operand(scratch1)); |
| 498 } | 529 } |
| 499 | 530 |
| 531 bool return_holder = return_what == RETURN_HOLDER; |
| 532 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { |
| 533 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
| 534 } |
| 535 |
| 500 // Return the register containing the holder. | 536 // Return the register containing the holder. |
| 501 return reg; | 537 return return_holder ? reg : no_reg; |
| 502 } | 538 } |
| 503 | 539 |
| 504 | 540 |
| 505 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 541 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
| 506 if (!miss->is_unused()) { | 542 if (!miss->is_unused()) { |
| 507 Label success; | 543 Label success; |
| 508 __ Branch(&success); | 544 __ Branch(&success); |
| 509 __ bind(miss); | 545 __ bind(miss); |
| 510 if (IC::ICUseVector(kind())) { | 546 if (IC::ICUseVector(kind())) { |
| 511 DCHECK(kind() == Code::LOAD_IC); | 547 DCHECK(kind() == Code::LOAD_IC); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 } | 742 } |
| 707 | 743 |
| 708 | 744 |
| 709 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 745 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 710 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 746 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
| 711 Label miss; | 747 Label miss; |
| 712 if (IC::ICUseVector(kind())) { | 748 if (IC::ICUseVector(kind())) { |
| 713 PushVectorAndSlot(); | 749 PushVectorAndSlot(); |
| 714 } | 750 } |
| 715 | 751 |
| 716 FrontendHeader(receiver(), name, &miss); | 752 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
| 717 | 753 |
| 718 // Get the value from the cell. | 754 // Get the value from the cell. |
| 719 Register result = StoreDescriptor::ValueRegister(); | 755 Register result = StoreDescriptor::ValueRegister(); |
| 720 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); | 756 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); |
| 721 __ LoadWeakValue(result, weak_cell, &miss); | 757 __ LoadWeakValue(result, weak_cell, &miss); |
| 722 __ ld(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 758 __ ld(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
| 723 | 759 |
| 724 // Check for deleted property if property can actually be deleted. | 760 // Check for deleted property if property can actually be deleted. |
| 725 if (is_configurable) { | 761 if (is_configurable) { |
| 726 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 762 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 740 // Return the generated code. | 776 // Return the generated code. |
| 741 return GetCode(kind(), Code::NORMAL, name); | 777 return GetCode(kind(), Code::NORMAL, name); |
| 742 } | 778 } |
| 743 | 779 |
| 744 | 780 |
| 745 #undef __ | 781 #undef __ |
| 746 } | 782 } |
| 747 } // namespace v8::internal | 783 } // namespace v8::internal |
| 748 | 784 |
| 749 #endif // V8_TARGET_ARCH_MIPS64 | 785 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |