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 |