| 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/cpu-profiler.h" | 7 #include "src/cpu-profiler.h" |
| 8 #include "src/ic/call-optimization.h" | 8 #include "src/ic/call-optimization.h" |
| 9 #include "src/ic/ic.h" | 9 #include "src/ic/ic.h" |
| 10 #include "src/ic/ic-inl.h" | 10 #include "src/ic/ic-inl.h" |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 expected_arguments, scratch2()); | 417 expected_arguments, scratch2()); |
| 418 return GetCode(kind(), Code::FAST, name); | 418 return GetCode(kind(), Code::FAST, name); |
| 419 } | 419 } |
| 420 | 420 |
| 421 | 421 |
| 422 // TODO(verwaest): Cleanup. holder() is actually the receiver. | 422 // TODO(verwaest): Cleanup. holder() is actually the receiver. |
| 423 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | 423 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
| 424 Handle<Map> transition, Handle<Name> name) { | 424 Handle<Map> transition, Handle<Name> name) { |
| 425 Label miss; | 425 Label miss; |
| 426 | 426 |
| 427 if (FLAG_vector_stores) PushVectorAndSlot(); |
| 428 |
| 427 // Check that we are allowed to write this. | 429 // Check that we are allowed to write this. |
| 428 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); | 430 bool is_nonexistent = holder()->map() == transition->GetBackPointer(); |
| 429 if (is_nonexistent) { | 431 if (is_nonexistent) { |
| 430 // Find the top object. | 432 // Find the top object. |
| 431 Handle<JSObject> last; | 433 Handle<JSObject> last; |
| 432 PrototypeIterator::WhereToEnd end = | 434 PrototypeIterator::WhereToEnd end = |
| 433 name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN | 435 name->IsPrivate() ? PrototypeIterator::END_AT_NON_HIDDEN |
| 434 : PrototypeIterator::END_AT_NULL; | 436 : PrototypeIterator::END_AT_NULL; |
| 435 PrototypeIterator iter(isolate(), holder()); | 437 PrototypeIterator iter(isolate(), holder()); |
| 436 while (!iter.IsAtEnd(end)) { | 438 while (!iter.IsAtEnd(end)) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 447 int descriptor = transition->LastAdded(); | 449 int descriptor = transition->LastAdded(); |
| 448 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); | 450 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); |
| 449 PropertyDetails details = descriptors->GetDetails(descriptor); | 451 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 450 Representation representation = details.representation(); | 452 Representation representation = details.representation(); |
| 451 DCHECK(!representation.IsNone()); | 453 DCHECK(!representation.IsNone()); |
| 452 | 454 |
| 453 // Stub is never generated for objects that require access checks. | 455 // Stub is never generated for objects that require access checks. |
| 454 DCHECK(!transition->is_access_check_needed()); | 456 DCHECK(!transition->is_access_check_needed()); |
| 455 | 457 |
| 456 // Call to respective StoreTransitionStub. | 458 // Call to respective StoreTransitionStub. |
| 457 Register transition_map_reg = StoreTransitionDescriptor::MapRegister(); | 459 Register transition_map_reg = StoreTransitionHelper::MapRegister(); |
| 458 bool push_map_on_stack = transition_map_reg.is(no_reg); | 460 bool stack_args = StoreTransitionHelper::UsesStackArgs(); |
| 459 Register map_reg = push_map_on_stack ? scratch1() : transition_map_reg; | 461 Register map_reg = stack_args ? scratch1() : transition_map_reg; |
| 460 | 462 |
| 461 if (details.type() == DATA_CONSTANT) { | 463 if (details.type() == DATA_CONSTANT) { |
| 462 DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); | 464 DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); |
| 463 GenerateRestoreMap(transition, map_reg, scratch2(), &miss); | 465 GenerateRestoreMap(transition, map_reg, scratch2(), &miss); |
| 464 GenerateConstantCheck(map_reg, descriptor, value(), scratch2(), &miss); | 466 GenerateConstantCheck(map_reg, descriptor, value(), scratch2(), &miss); |
| 465 if (push_map_on_stack) { | 467 if (stack_args) { |
| 468 // Also pushes vector and slot. |
| 466 GeneratePushMap(map_reg, scratch2()); | 469 GeneratePushMap(map_reg, scratch2()); |
| 470 } else if (FLAG_vector_stores) { |
| 471 PopVectorAndSlot(); |
| 467 } | 472 } |
| 468 GenerateRestoreName(name); | 473 GenerateRestoreName(name); |
| 469 StoreTransitionStub stub(isolate()); | 474 StoreTransitionStub stub(isolate()); |
| 470 GenerateTailCall(masm(), stub.GetCode()); | 475 GenerateTailCall(masm(), stub.GetCode()); |
| 471 | 476 |
| 472 } else { | 477 } else { |
| 473 if (representation.IsHeapObject()) { | 478 if (representation.IsHeapObject()) { |
| 474 GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), | 479 GenerateFieldTypeChecks(descriptors->GetFieldType(descriptor), value(), |
| 475 &miss); | 480 &miss); |
| 476 } | 481 } |
| 477 StoreTransitionStub::StoreMode store_mode = | 482 StoreTransitionStub::StoreMode store_mode = |
| 478 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 | 483 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 |
| 479 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue | 484 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue |
| 480 : StoreTransitionStub::StoreMapAndValue; | 485 : StoreTransitionStub::StoreMapAndValue; |
| 481 | 486 |
| 482 GenerateRestoreMap(transition, map_reg, scratch2(), &miss); | 487 GenerateRestoreMap(transition, map_reg, scratch2(), &miss); |
| 483 if (push_map_on_stack) { | 488 if (stack_args) { |
| 489 // Also pushes vector and slot. |
| 484 GeneratePushMap(map_reg, scratch2()); | 490 GeneratePushMap(map_reg, scratch2()); |
| 491 } else if (FLAG_vector_stores) { |
| 492 PopVectorAndSlot(); |
| 485 } | 493 } |
| 486 GenerateRestoreName(name); | 494 GenerateRestoreName(name); |
| 487 StoreTransitionStub stub(isolate(), | 495 StoreTransitionStub stub(isolate(), |
| 488 FieldIndex::ForDescriptor(*transition, descriptor), | 496 FieldIndex::ForDescriptor(*transition, descriptor), |
| 489 representation, store_mode); | 497 representation, store_mode); |
| 490 GenerateTailCall(masm(), stub.GetCode()); | 498 GenerateTailCall(masm(), stub.GetCode()); |
| 491 } | 499 } |
| 492 | 500 |
| 493 GenerateRestoreName(&miss, name); | 501 GenerateRestoreName(&miss, name); |
| 502 if (FLAG_vector_stores) PopVectorAndSlot(); |
| 494 TailCallBuiltin(masm(), MissBuiltin(kind())); | 503 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 495 | 504 |
| 496 return GetCode(kind(), Code::FAST, name); | 505 return GetCode(kind(), Code::FAST, name); |
| 497 } | 506 } |
| 498 | 507 |
| 499 | 508 |
| 509 bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks( |
| 510 HeapType* field_type) const { |
| 511 return !field_type->Classes().Done(); |
| 512 } |
| 513 |
| 514 |
| 500 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { | 515 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { |
| 501 Label miss; | 516 Label miss; |
| 502 DCHECK(it->representation().IsHeapObject()); | 517 DCHECK(it->representation().IsHeapObject()); |
| 503 | 518 |
| 504 GenerateFieldTypeChecks(*it->GetFieldType(), value(), &miss); | 519 HeapType* field_type = *it->GetFieldType(); |
| 520 bool need_save_restore = false; |
| 521 if (RequiresFieldTypeChecks(field_type)) { |
| 522 need_save_restore = IC::ICUseVector(kind()); |
| 523 if (need_save_restore) PushVectorAndSlot(); |
| 524 GenerateFieldTypeChecks(field_type, value(), &miss); |
| 525 if (need_save_restore) PopVectorAndSlot(); |
| 526 } |
| 527 |
| 505 StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); | 528 StoreFieldStub stub(isolate(), it->GetFieldIndex(), it->representation()); |
| 506 GenerateTailCall(masm(), stub.GetCode()); | 529 GenerateTailCall(masm(), stub.GetCode()); |
| 507 | 530 |
| 508 __ bind(&miss); | 531 __ bind(&miss); |
| 532 if (need_save_restore) PopVectorAndSlot(); |
| 509 TailCallBuiltin(masm(), MissBuiltin(kind())); | 533 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 510 return GetCode(kind(), Code::FAST, it->name()); | 534 return GetCode(kind(), Code::FAST, it->name()); |
| 511 } | 535 } |
| 512 | 536 |
| 513 | 537 |
| 514 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( | 538 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
| 515 Handle<JSObject> object, Handle<Name> name, int accessor_index, | 539 Handle<JSObject> object, Handle<Name> name, int accessor_index, |
| 516 int expected_arguments) { | 540 int expected_arguments) { |
| 517 Register holder = Frontend(name); | 541 Register holder = Frontend(name); |
| 518 GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index, | 542 GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 : kNoExtraICState); | 600 : kNoExtraICState); |
| 577 cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode(); | 601 cached_stub = LoadDictionaryElementStub(isolate(), state).GetCode(); |
| 578 } | 602 } |
| 579 } | 603 } |
| 580 | 604 |
| 581 handlers->Add(cached_stub); | 605 handlers->Add(cached_stub); |
| 582 } | 606 } |
| 583 } | 607 } |
| 584 } // namespace internal | 608 } // namespace internal |
| 585 } // namespace v8 | 609 } // namespace v8 |
| OLD | NEW |