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/ic/handler-compiler.h" | 5 #include "src/ic/handler-compiler.h" |
6 | 6 |
7 #include "src/field-type.h" | 7 #include "src/field-type.h" |
8 #include "src/ic/call-optimization.h" | 8 #include "src/ic/call-optimization.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/ic-inl.h" | 10 #include "src/ic/ic-inl.h" |
(...skipping 420 matching lines...) Loading... |
431 expected_arguments, scratch2()); | 431 expected_arguments, scratch2()); |
432 return GetCode(kind(), name); | 432 return GetCode(kind(), name); |
433 } | 433 } |
434 | 434 |
435 | 435 |
436 // TODO(verwaest): Cleanup. holder() is actually the receiver. | 436 // TODO(verwaest): Cleanup. holder() is actually the receiver. |
437 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | 437 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
438 Handle<Map> transition, Handle<Name> name) { | 438 Handle<Map> transition, Handle<Name> name) { |
439 Label miss; | 439 Label miss; |
440 | 440 |
441 PushVectorAndSlot(); | 441 bool vector_and_slot_on_stack = |
| 442 StoreTransitionDescriptor::PassVectorAndSlotOnStack(); |
| 443 if (vector_and_slot_on_stack) { |
| 444 // Speculatively prepare for calling StoreTransitionStub by converting |
| 445 // StoreWithVectorDescriptor arguments to StoreTransitionDescriptor |
| 446 // arguments. |
| 447 PopReturnAddress(this->name()); |
| 448 PushVectorAndSlot(); |
| 449 PushReturnAddress(this->name()); |
| 450 } else { |
| 451 PushVectorAndSlot(); |
| 452 } |
442 | 453 |
443 // Check that we are allowed to write this. | 454 // Check that we are allowed to write this. |
444 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); | 455 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); |
445 if (is_nonexistent) { | 456 if (is_nonexistent) { |
446 // Find the top object. | 457 // Find the top object. |
447 Handle<JSObject> last; | 458 Handle<JSObject> last; |
448 PrototypeIterator::WhereToEnd end = | 459 PrototypeIterator::WhereToEnd end = |
449 name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN | 460 name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN |
450 : PrototypeIterator::END_AT_NULL; | 461 : PrototypeIterator::END_AT_NULL; |
451 PrototypeIterator iter(isolate(), holder(), kStartAtPrototype, end); | 462 PrototypeIterator iter(isolate(), holder(), kStartAtPrototype, end); |
(...skipping 11 matching lines...) Loading... |
463 int descriptor = transition->LastAdded(); | 474 int descriptor = transition->LastAdded(); |
464 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); | 475 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); |
465 PropertyDetails details = descriptors->GetDetails(descriptor); | 476 PropertyDetails details = descriptors->GetDetails(descriptor); |
466 Representation representation = details.representation(); | 477 Representation representation = details.representation(); |
467 DCHECK(!representation.IsNone()); | 478 DCHECK(!representation.IsNone()); |
468 | 479 |
469 // Stub is never generated for objects that require access checks. | 480 // Stub is never generated for objects that require access checks. |
470 DCHECK(!transition->is_access_check_needed()); | 481 DCHECK(!transition->is_access_check_needed()); |
471 | 482 |
472 // Call to respective StoreTransitionStub. | 483 // Call to respective StoreTransitionStub. |
473 bool virtual_args = StoreTransitionHelper::HasVirtualSlotArg(); | 484 Register map_reg = StoreTransitionDescriptor::MapRegister(); |
474 Register map_reg = StoreTransitionHelper::MapRegister(); | |
475 | 485 |
476 if (details.type() == DATA_CONSTANT) { | 486 if (details.type() == DATA_CONSTANT) { |
477 DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); | 487 DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); |
478 Register tmp = | 488 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); |
479 virtual_args ? StoreWithVectorDescriptor::VectorRegister() : map_reg; | 489 GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss); |
480 GenerateRestoreMap(transition, tmp, scratch2(), &miss); | 490 if (!vector_and_slot_on_stack) { |
481 GenerateConstantCheck(tmp, descriptor, value(), scratch2(), &miss); | |
482 if (virtual_args) { | |
483 // This will move the map from tmp into map_reg. | |
484 RearrangeVectorAndSlot(tmp, map_reg); | |
485 } else { | |
486 PopVectorAndSlot(); | 491 PopVectorAndSlot(); |
487 } | 492 } |
488 GenerateRestoreName(name); | 493 GenerateRestoreName(name); |
489 StoreTransitionStub stub(isolate()); | 494 StoreTransitionStub stub(isolate()); |
490 GenerateTailCall(masm(), stub.GetCode()); | 495 GenerateTailCall(masm(), stub.GetCode()); |
491 | 496 |
492 } else { | 497 } else { |
493 if (representation.IsHeapObject()) { | 498 if (representation.IsHeapObject()) { |
494 GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), | 499 GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), |
495 &miss); | 500 &miss); |
496 } | 501 } |
497 StoreTransitionStub::StoreMode store_mode = | 502 StoreTransitionStub::StoreMode store_mode = |
498 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 | 503 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 |
499 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue | 504 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue |
500 : StoreTransitionStub::StoreMapAndValue; | 505 : StoreTransitionStub::StoreMapAndValue; |
501 | 506 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); |
502 Register tmp = | 507 if (!vector_and_slot_on_stack) { |
503 virtual_args ? StoreWithVectorDescriptor::VectorRegister() : map_reg; | |
504 GenerateRestoreMap(transition, tmp, scratch2(), &miss); | |
505 if (virtual_args) { | |
506 RearrangeVectorAndSlot(tmp, map_reg); | |
507 } else { | |
508 PopVectorAndSlot(); | 508 PopVectorAndSlot(); |
509 } | 509 } |
510 GenerateRestoreName(name); | 510 GenerateRestoreName(name); |
511 StoreTransitionStub stub(isolate(), | 511 StoreTransitionStub stub(isolate(), |
512 FieldIndex::ForDescriptor(*transition, descriptor), | 512 FieldIndex::ForDescriptor(*transition, descriptor), |
513 representation, store_mode); | 513 representation, store_mode); |
514 GenerateTailCall(masm(), stub.GetCode()); | 514 GenerateTailCall(masm(), stub.GetCode()); |
515 } | 515 } |
516 | 516 |
517 GenerateRestoreName(&miss, name); | 517 __ bind(&miss); |
518 PopVectorAndSlot(); | 518 if (vector_and_slot_on_stack) { |
| 519 // Prepare for calling miss builtin with StoreWithVectorDescriptor. |
| 520 PopReturnAddress(this->name()); |
| 521 PopVectorAndSlot(); |
| 522 PushReturnAddress(this->name()); |
| 523 } else { |
| 524 PopVectorAndSlot(); |
| 525 } |
| 526 GenerateRestoreName(name); |
519 TailCallBuiltin(masm(), MissBuiltin(kind())); | 527 TailCallBuiltin(masm(), MissBuiltin(kind())); |
520 | 528 |
521 return GetCode(kind(), name); | 529 return GetCode(kind(), name); |
522 } | 530 } |
523 | 531 |
524 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( | 532 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( |
525 FieldType* field_type) const { | 533 FieldType* field_type) const { |
526 return field_type->IsClass(); | 534 return field_type->IsClass(); |
527 } | 535 } |
528 | 536 |
(...skipping 105 matching lines...) Loading... |
634 } | 642 } |
635 | 643 |
636 void ElementHandlerCompiler::CompileElementHandlers( | 644 void ElementHandlerCompiler::CompileElementHandlers( |
637 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { | 645 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { |
638 for (int i = 0; i < receiver_maps->length(); ++i) { | 646 for (int i = 0; i < receiver_maps->length(); ++i) { |
639 handlers->Add(GetKeyedLoadHandler(receiver_maps->at(i), isolate())); | 647 handlers->Add(GetKeyedLoadHandler(receiver_maps->at(i), isolate())); |
640 } | 648 } |
641 } | 649 } |
642 } // namespace internal | 650 } // namespace internal |
643 } // namespace v8 | 651 } // namespace v8 |
OLD | NEW |