| 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-inl.h" | 9 #include "src/ic/handler-configuration-inl.h" |
| 10 #include "src/ic/ic-inl.h" | 10 #include "src/ic/ic-inl.h" |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 } | 186 } |
| 187 DCHECK(holder().is_null() || | 187 DCHECK(holder().is_null() || |
| 188 holder()->property_dictionary()->FindEntry(name) == | 188 holder()->property_dictionary()->FindEntry(name) == |
| 189 NameDictionary::kNotFound); | 189 NameDictionary::kNotFound); |
| 190 GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, | 190 GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, |
| 191 scratch2); | 191 scratch2); |
| 192 } | 192 } |
| 193 } | 193 } |
| 194 } | 194 } |
| 195 | 195 |
| 196 | |
| 197 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, | |
| 198 FieldIndex field) { | |
| 199 Register reg = Frontend(name); | |
| 200 __ Move(receiver(), reg); | |
| 201 LoadFieldStub stub(isolate(), field); | |
| 202 GenerateTailCall(masm(), stub.GetCode()); | |
| 203 return GetCode(kind(), name); | |
| 204 } | |
| 205 | |
| 206 | |
| 207 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, | |
| 208 int constant_index) { | |
| 209 Register reg = Frontend(name); | |
| 210 __ Move(receiver(), reg); | |
| 211 LoadConstantStub stub(isolate(), constant_index); | |
| 212 GenerateTailCall(masm(), stub.GetCode()); | |
| 213 return GetCode(kind(), name); | |
| 214 } | |
| 215 | |
| 216 | |
| 217 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 196 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 218 Handle<Name> name) { | 197 Handle<Name> name) { |
| 219 Label miss; | 198 Label miss; |
| 220 if (IC::ShouldPushPopSlotAndVector(kind())) { | 199 if (IC::ShouldPushPopSlotAndVector(kind())) { |
| 221 DCHECK(kind() == Code::LOAD_IC); | 200 DCHECK(kind() == Code::LOAD_IC); |
| 222 PushVectorAndSlot(); | 201 PushVectorAndSlot(); |
| 223 } | 202 } |
| 224 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); | 203 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); |
| 225 if (IC::ShouldPushPopSlotAndVector(kind())) { | 204 if (IC::ShouldPushPopSlotAndVector(kind())) { |
| 226 DiscardVectorAndSlot(); | 205 DiscardVectorAndSlot(); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 } | 412 } |
| 434 | 413 |
| 435 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( | 414 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( |
| 436 Handle<Name> name, int accessor_index, int expected_arguments) { | 415 Handle<Name> name, int accessor_index, int expected_arguments) { |
| 437 Register holder = Frontend(name); | 416 Register holder = Frontend(name); |
| 438 GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index, | 417 GenerateLoadViaGetter(masm(), map(), receiver(), holder, accessor_index, |
| 439 expected_arguments, scratch2()); | 418 expected_arguments, scratch2()); |
| 440 return GetCode(kind(), name); | 419 return GetCode(kind(), name); |
| 441 } | 420 } |
| 442 | 421 |
| 443 | |
| 444 // TODO(verwaest): Cleanup. holder() is actually the receiver. | |
| 445 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | |
| 446 Handle<Map> transition, Handle<Name> name) { | |
| 447 Label miss; | |
| 448 | |
| 449 // Ensure that the StoreTransitionStub we are going to call has the same | |
| 450 // number of stack arguments. This means that we don't have to adapt them | |
| 451 // if we decide to call the transition or miss stub. | |
| 452 STATIC_ASSERT(Descriptor::kStackArgumentsCount == | |
| 453 StoreTransitionDescriptor::kStackArgumentsCount); | |
| 454 STATIC_ASSERT(Descriptor::kStackArgumentsCount == 0 || | |
| 455 Descriptor::kStackArgumentsCount == 3); | |
| 456 STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kValue == | |
| 457 StoreTransitionDescriptor::kParameterCount - | |
| 458 StoreTransitionDescriptor::kValue); | |
| 459 STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kSlot == | |
| 460 StoreTransitionDescriptor::kParameterCount - | |
| 461 StoreTransitionDescriptor::kSlot); | |
| 462 STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kVector == | |
| 463 StoreTransitionDescriptor::kParameterCount - | |
| 464 StoreTransitionDescriptor::kVector); | |
| 465 | |
| 466 if (Descriptor::kPassLastArgsOnStack) { | |
| 467 __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); | |
| 468 } | |
| 469 | |
| 470 bool need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); | |
| 471 if (need_save_restore) { | |
| 472 PushVectorAndSlot(); | |
| 473 } | |
| 474 | |
| 475 // Check that we are allowed to write this. | |
| 476 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); | |
| 477 if (is_nonexistent) { | |
| 478 // Find the top object. | |
| 479 Handle<JSObject> last; | |
| 480 PrototypeIterator::WhereToEnd end = | |
| 481 name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN | |
| 482 : PrototypeIterator::END_AT_NULL; | |
| 483 PrototypeIterator iter(isolate(), holder(), kStartAtPrototype, end); | |
| 484 while (!iter.IsAtEnd()) { | |
| 485 last = PrototypeIterator::GetCurrent<JSObject>(iter); | |
| 486 iter.Advance(); | |
| 487 } | |
| 488 if (!last.is_null()) set_holder(last); | |
| 489 NonexistentFrontendHeader(name, &miss, scratch1(), scratch2()); | |
| 490 } else { | |
| 491 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); | |
| 492 DCHECK(holder()->HasFastProperties()); | |
| 493 } | |
| 494 | |
| 495 int descriptor = transition->LastAdded(); | |
| 496 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); | |
| 497 PropertyDetails details = descriptors->GetDetails(descriptor); | |
| 498 Representation representation = details.representation(); | |
| 499 DCHECK(!representation.IsNone()); | |
| 500 | |
| 501 // Stub is never generated for objects that require access checks. | |
| 502 DCHECK(!transition->is_access_check_needed()); | |
| 503 | |
| 504 // Call to respective StoreTransitionStub. | |
| 505 Register map_reg = StoreTransitionDescriptor::MapRegister(); | |
| 506 | |
| 507 if (details.type() == DATA_CONSTANT) { | |
| 508 DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); | |
| 509 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); | |
| 510 GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss); | |
| 511 if (need_save_restore) { | |
| 512 PopVectorAndSlot(); | |
| 513 } | |
| 514 GenerateRestoreName(name); | |
| 515 StoreMapStub stub(isolate()); | |
| 516 GenerateTailCall(masm(), stub.GetCode()); | |
| 517 | |
| 518 } else { | |
| 519 if (representation.IsHeapObject()) { | |
| 520 GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), | |
| 521 &miss); | |
| 522 } | |
| 523 StoreTransitionStub::StoreMode store_mode = | |
| 524 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 | |
| 525 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue | |
| 526 : StoreTransitionStub::StoreMapAndValue; | |
| 527 GenerateRestoreMap(transition, map_reg, scratch1(), &miss); | |
| 528 if (need_save_restore) { | |
| 529 PopVectorAndSlot(); | |
| 530 } | |
| 531 // We need to pass name on the stack. | |
| 532 PopReturnAddress(this->name()); | |
| 533 __ Push(name); | |
| 534 PushReturnAddress(this->name()); | |
| 535 | |
| 536 FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor); | |
| 537 __ Move(StoreNamedTransitionDescriptor::FieldOffsetRegister(), | |
| 538 Smi::FromInt(index.index() << kPointerSizeLog2)); | |
| 539 | |
| 540 StoreTransitionStub stub(isolate(), index.is_inobject(), representation, | |
| 541 store_mode); | |
| 542 GenerateTailCall(masm(), stub.GetCode()); | |
| 543 } | |
| 544 | |
| 545 __ bind(&miss); | |
| 546 if (need_save_restore) { | |
| 547 PopVectorAndSlot(); | |
| 548 } | |
| 549 GenerateRestoreName(name); | |
| 550 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 551 | |
| 552 return GetCode(kind(), name); | |
| 553 } | |
| 554 | |
| 555 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( | 422 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( |
| 556 FieldType* field_type) const { | 423 FieldType* field_type) const { |
| 557 return field_type->IsClass(); | 424 return field_type->IsClass(); |
| 558 } | 425 } |
| 559 | 426 |
| 560 | |
| 561 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { | |
| 562 Label miss; | |
| 563 DCHECK(it->representation().IsHeapObject()); | |
| 564 | |
| 565 FieldType* field_type = *it->GetFieldType(); | |
| 566 bool need_save_restore = false; | |
| 567 if (RequiresFieldTypeChecks(field_type)) { | |
| 568 need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); | |
| 569 if (Descriptor::kPassLastArgsOnStack) { | |
| 570 __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); | |
| 571 } | |
| 572 if (need_save_restore) PushVectorAndSlot(); | |
| 573 GenerateFieldTypeChecks(field_type, value(), &miss); | |
| 574 if (need_save_restore) PopVectorAndSlot(); | |
| 575 } | |
| 576 | |
| 577 StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); | |
| 578 GenerateTailCall(masm(), stub.GetCode()); | |
| 579 | |
| 580 __ bind(&miss); | |
| 581 if (need_save_restore) PopVectorAndSlot(); | |
| 582 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 583 return GetCode(kind(), it->name()); | |
| 584 } | |
| 585 | |
| 586 | |
| 587 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( | 427 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
| 588 Handle<JSObject> object, Handle<Name> name, int accessor_index, | 428 Handle<JSObject> object, Handle<Name> name, int accessor_index, |
| 589 int expected_arguments) { | 429 int expected_arguments) { |
| 590 Register holder = Frontend(name); | 430 Register holder = Frontend(name); |
| 591 GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index, | 431 GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index, |
| 592 expected_arguments, scratch2()); | 432 expected_arguments, scratch2()); |
| 593 | 433 |
| 594 return GetCode(kind(), name); | 434 return GetCode(kind(), name); |
| 595 } | 435 } |
| 596 | 436 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 495 } |
| 656 | 496 |
| 657 void ElementHandlerCompiler::CompileElementHandlers( | 497 void ElementHandlerCompiler::CompileElementHandlers( |
| 658 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { | 498 MapHandleList* receiver_maps, List<Handle<Object>>* handlers) { |
| 659 for (int i = 0; i < receiver_maps->length(); ++i) { | 499 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 660 handlers->Add(GetKeyedLoadHandler(receiver_maps->at(i), isolate())); | 500 handlers->Add(GetKeyedLoadHandler(receiver_maps->at(i), isolate())); |
| 661 } | 501 } |
| 662 } | 502 } |
| 663 } // namespace internal | 503 } // namespace internal |
| 664 } // namespace v8 | 504 } // namespace v8 |
| OLD | NEW |