Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(169)

Side by Side Diff: src/ic.cc

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 #ifdef DEBUG 141 #ifdef DEBUG
142 StackFrameIterator it(isolate); 142 StackFrameIterator it(isolate);
143 for (int i = 0; i < depth + 1; i++) it.Advance(); 143 for (int i = 0; i < depth + 1; i++) it.Advance();
144 StackFrame* frame = it.frame(); 144 StackFrame* frame = it.frame();
145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address()); 145 ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
146 #endif 146 #endif
147 fp_ = fp; 147 fp_ = fp;
148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address); 148 pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
149 target_ = handle(raw_target(), isolate); 149 target_ = handle(raw_target(), isolate);
150 state_ = target_->ic_state(); 150 state_ = target_->ic_state();
151 extra_ic_state_ = target_->needs_extended_extra_ic_state(target_->kind()) 151 extra_ic_state_ = target_->extra_ic_state();
152 ? target_->extended_extra_ic_state()
153 : target_->extra_ic_state();
154 } 152 }
155 153
156 154
157 #ifdef ENABLE_DEBUGGER_SUPPORT 155 #ifdef ENABLE_DEBUGGER_SUPPORT
158 Address IC::OriginalCodeAddress() const { 156 Address IC::OriginalCodeAddress() const {
159 HandleScope scope(isolate()); 157 HandleScope scope(isolate());
160 // Compute the JavaScript frame for the frame pointer of this IC 158 // Compute the JavaScript frame for the frame pointer of this IC
161 // structure. We need this to be able to find the function 159 // structure. We need this to be able to find the function
162 // corresponding to the frame. 160 // corresponding to the frame.
163 StackFrameIterator it(isolate()); 161 StackFrameIterator it(isolate());
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 // Don't clear debug break inline cache as it will remove the break point. 415 // Don't clear debug break inline cache as it will remove the break point.
418 if (target->is_debug_stub()) return; 416 if (target->is_debug_stub()) return;
419 417
420 switch (target->kind()) { 418 switch (target->kind()) {
421 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); 419 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target);
422 case Code::KEYED_LOAD_IC: 420 case Code::KEYED_LOAD_IC:
423 return KeyedLoadIC::Clear(isolate, address, target); 421 return KeyedLoadIC::Clear(isolate, address, target);
424 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); 422 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target);
425 case Code::KEYED_STORE_IC: 423 case Code::KEYED_STORE_IC:
426 return KeyedStoreIC::Clear(isolate, address, target); 424 return KeyedStoreIC::Clear(isolate, address, target);
427 case Code::CALL_IC: return CallIC::Clear(address, target);
428 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
429 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); 425 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target);
430 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); 426 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target);
431 case Code::BINARY_OP_IC: 427 case Code::BINARY_OP_IC:
432 case Code::TO_BOOLEAN_IC: 428 case Code::TO_BOOLEAN_IC:
433 // Clearing these is tricky and does not 429 // Clearing these is tricky and does not
434 // make any performance difference. 430 // make any performance difference.
435 return; 431 return;
436 default: UNREACHABLE(); 432 default: UNREACHABLE();
437 } 433 }
438 } 434 }
439 435
440 436
441 void CallICBase::Clear(Address address, Code* target) {
442 if (IsCleared(target)) return;
443 Code* code = target->GetIsolate()->stub_cache()->FindCallInitialize(
444 target->arguments_count(), target->kind());
445 SetTargetAtAddress(address, code);
446 }
447
448
449 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { 437 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) {
450 if (IsCleared(target)) return; 438 if (IsCleared(target)) return;
451 // Make sure to also clear the map used in inline fast cases. If we 439 // Make sure to also clear the map used in inline fast cases. If we
452 // do not clear these maps, cached code can keep objects alive 440 // do not clear these maps, cached code can keep objects alive
453 // through the embedded maps. 441 // through the embedded maps.
454 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); 442 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
455 } 443 }
456 444
457 445
458 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { 446 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) {
(...skipping 26 matching lines...) Expand all
485 Token::Value op; 473 Token::Value op;
486 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, 474 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
487 &handler_state, &op); 475 &handler_state, &op);
488 // Only clear CompareICs that can retain objects. 476 // Only clear CompareICs that can retain objects.
489 if (handler_state != KNOWN_OBJECT) return; 477 if (handler_state != KNOWN_OBJECT) return;
490 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); 478 SetTargetAtAddress(address, GetRawUninitialized(isolate, op));
491 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); 479 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
492 } 480 }
493 481
494 482
495 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
496 Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object);
497
498 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
499 // Patch the receiver and use the delegate as the function to
500 // invoke. This is used for invoking objects as if they were functions.
501 const int argc = target()->arguments_count();
502 StackFrameLocator locator(isolate());
503 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
504 int index = frame->ComputeExpressionsCount() - (argc + 1);
505 frame->SetExpression(index, *object);
506 }
507
508 return delegate;
509 }
510
511
512 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
513 Handle<Object> object) {
514 while (callee->IsJSFunctionProxy()) {
515 callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap(),
516 isolate());
517 }
518
519 if (callee->IsJSFunction()) {
520 Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
521 if (!function->shared()->is_classic_mode() || function->IsBuiltin()) {
522 // Do not wrap receiver for strict mode functions or for builtins.
523 return;
524 }
525 }
526
527 // And only wrap string, number or boolean.
528 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
529 // Change the receiver to the result of calling ToObject on it.
530 const int argc = this->target()->arguments_count();
531 StackFrameLocator locator(isolate());
532 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
533 int index = frame->ComputeExpressionsCount() - (argc + 1);
534 frame->SetExpression(index, *isolate()->factory()->ToObject(object));
535 }
536 }
537
538
539 static bool MigrateDeprecated(Handle<Object> object) { 483 static bool MigrateDeprecated(Handle<Object> object) {
540 if (!object->IsJSObject()) return false; 484 if (!object->IsJSObject()) return false;
541 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 485 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
542 if (!receiver->map()->is_deprecated()) return false; 486 if (!receiver->map()->is_deprecated()) return false;
543 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); 487 JSObject::MigrateInstance(Handle<JSObject>::cast(object));
544 return true; 488 return true;
545 } 489 }
546 490
547 491
548 MaybeObject* CallICBase::LoadFunction(Handle<Object> object,
549 Handle<String> name) {
550 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
551
552 // If the object is undefined or null it's illegal to try to get any
553 // of its properties; throw a TypeError in that case.
554 if (object->IsUndefined() || object->IsNull()) {
555 return TypeError("non_object_property_call", object, name);
556 }
557
558 // Check if the name is trivially convertible to an index and get
559 // the element if so.
560 uint32_t index;
561 if (name->AsArrayIndex(&index)) {
562 Handle<Object> result = Object::GetElement(isolate(), object, index);
563 RETURN_IF_EMPTY_HANDLE(isolate(), result);
564 if (result->IsJSFunction()) return *result;
565
566 // Try to find a suitable function delegate for the object at hand.
567 result = TryCallAsFunction(result);
568 if (result->IsJSFunction()) return *result;
569
570 // Otherwise, it will fail in the lookup step.
571 }
572
573 // Lookup the property in the object.
574 LookupResult lookup(isolate());
575 LookupForRead(object, name, &lookup);
576
577 if (!lookup.IsFound()) {
578 // If the object does not have the requested property, check which
579 // exception we need to throw.
580 return object->IsGlobalObject()
581 ? ReferenceError("not_defined", name)
582 : TypeError("undefined_method", object, name);
583 }
584
585 // Lookup is valid: Update inline cache and stub cache.
586 if (use_ic) UpdateCaches(&lookup, object, name);
587
588 // Get the property.
589 PropertyAttributes attr;
590 Handle<Object> result =
591 Object::GetProperty(object, object, &lookup, name, &attr);
592 RETURN_IF_EMPTY_HANDLE(isolate(), result);
593
594 if (lookup.IsInterceptor() && attr == ABSENT) {
595 // If the object does not have the requested property, check which
596 // exception we need to throw.
597 return object->IsGlobalObject()
598 ? ReferenceError("not_defined", name)
599 : TypeError("undefined_method", object, name);
600 }
601
602 ASSERT(!result->IsTheHole());
603
604 // Make receiver an object if the callee requires it. Strict mode or builtin
605 // functions do not wrap the receiver, non-strict functions and objects
606 // called as functions do.
607 ReceiverToObjectIfRequired(result, object);
608
609 if (result->IsJSFunction()) {
610 Handle<JSFunction> function = Handle<JSFunction>::cast(result);
611 #ifdef ENABLE_DEBUGGER_SUPPORT
612 // Handle stepping into a function if step into is active.
613 Debug* debug = isolate()->debug();
614 if (debug->StepInActive()) {
615 // Protect the result in a handle as the debugger can allocate and might
616 // cause GC.
617 debug->HandleStepIn(function, object, fp(), false);
618 }
619 #endif
620 return *function;
621 }
622
623 // Try to find a suitable function delegate for the object at hand.
624 result = TryCallAsFunction(result);
625 if (result->IsJSFunction()) return *result;
626
627 return TypeError("property_not_function", object, name);
628 }
629
630
631 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
632 Handle<Object> object,
633 Handle<String> name) {
634 int argc = target()->arguments_count();
635 Handle<JSObject> holder(lookup->holder(), isolate());
636 switch (lookup->type()) {
637 case FIELD: {
638 PropertyIndex index = lookup->GetFieldIndex();
639 return isolate()->stub_cache()->ComputeCallField(
640 argc, kind_, extra_ic_state(), name, object, holder, index);
641 }
642 case CONSTANT: {
643 if (!lookup->IsConstantFunction()) return Handle<Code>::null();
644 // Get the constant function and compute the code stub for this
645 // call; used for rewriting to monomorphic state and making sure
646 // that the code stub is in the stub cache.
647 Handle<JSFunction> function(lookup->GetConstantFunction(), isolate());
648 return isolate()->stub_cache()->ComputeCallConstant(
649 argc, kind_, extra_ic_state(), name, object, holder, function);
650 }
651 case NORMAL: {
652 // If we return a null handle, the IC will not be patched.
653 if (!object->IsJSObject()) return Handle<Code>::null();
654 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
655
656 if (holder->IsGlobalObject()) {
657 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
658 Handle<PropertyCell> cell(
659 global->GetPropertyCell(lookup), isolate());
660 if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
661 Handle<JSFunction> function(JSFunction::cast(cell->value()));
662 return isolate()->stub_cache()->ComputeCallGlobal(
663 argc, kind_, extra_ic_state(), name,
664 receiver, global, cell, function);
665 } else {
666 // There is only one shared stub for calling normalized
667 // properties. It does not traverse the prototype chain, so the
668 // property must be found in the receiver for the stub to be
669 // applicable.
670 if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
671 return isolate()->stub_cache()->ComputeCallNormal(
672 argc, kind_, extra_ic_state());
673 }
674 break;
675 }
676 case INTERCEPTOR:
677 ASSERT(HasInterceptorGetter(*holder));
678 return isolate()->stub_cache()->ComputeCallInterceptor(
679 argc, kind_, extra_ic_state(), name, object, holder);
680 default:
681 return Handle<Code>::null();
682 }
683 }
684
685
686 Handle<Code> CallICBase::megamorphic_stub() {
687 return isolate()->stub_cache()->ComputeCallMegamorphic(
688 target()->arguments_count(), kind_, extra_ic_state());
689 }
690
691
692 Handle<Code> CallICBase::pre_monomorphic_stub() {
693 return isolate()->stub_cache()->ComputeCallPreMonomorphic(
694 target()->arguments_count(), kind_, extra_ic_state());
695 }
696
697
698 void CallICBase::UpdateCaches(LookupResult* lookup,
699 Handle<Object> object,
700 Handle<String> name) {
701 // Bail out if we didn't find a result.
702 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
703
704 if (state() == UNINITIALIZED) {
705 set_target(*pre_monomorphic_stub());
706 TRACE_IC("CallIC", name);
707 return;
708 }
709
710 Handle<Code> code = ComputeMonomorphicStub(lookup, object, name);
711 // If there's no appropriate stub we simply avoid updating the caches.
712 // TODO(verwaest): Install a slow fallback in this case to avoid not learning,
713 // and deopting Crankshaft code.
714 if (code.is_null()) return;
715
716 Handle<JSObject> cache_object = object->IsJSObject()
717 ? Handle<JSObject>::cast(object)
718 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
719 isolate());
720
721 PatchCache(CurrentTypeOf(cache_object, isolate()), name, code);
722 TRACE_IC("CallIC", name);
723 }
724
725
726 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object,
727 Handle<Object> key) {
728 if (key->IsInternalizedString()) {
729 return CallICBase::LoadFunction(object, Handle<String>::cast(key));
730 }
731
732 if (object->IsUndefined() || object->IsNull()) {
733 return TypeError("non_object_property_call", object, key);
734 }
735
736 bool use_ic = MigrateDeprecated(object)
737 ? false : FLAG_use_ic && !object->IsAccessCheckNeeded();
738
739 if (use_ic && state() != MEGAMORPHIC) {
740 ASSERT(!object->IsJSGlobalProxy());
741 int argc = target()->arguments_count();
742 Handle<Code> stub;
743
744 // Use the KeyedArrayCallStub if the call is of the form array[smi](...),
745 // where array is an instance of one of the initial array maps (without
746 // extra named properties).
747 // TODO(verwaest): Also support keyed calls on instances of other maps.
748 if (object->IsJSArray() && key->IsSmi()) {
749 Handle<JSArray> array = Handle<JSArray>::cast(object);
750 ElementsKind kind = array->map()->elements_kind();
751 if (IsFastObjectElementsKind(kind) &&
752 array->map() == isolate()->get_initial_js_array_map(kind)) {
753 KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc);
754 stub = stub_gen.GetCode(isolate());
755 }
756 }
757
758 if (stub.is_null()) {
759 stub = isolate()->stub_cache()->ComputeCallMegamorphic(
760 argc, Code::KEYED_CALL_IC, kNoExtraICState);
761 if (object->IsJSObject()) {
762 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
763 if (receiver->elements()->map() ==
764 isolate()->heap()->non_strict_arguments_elements_map()) {
765 stub = isolate()->stub_cache()->ComputeCallArguments(argc);
766 }
767 }
768 ASSERT(!stub.is_null());
769 }
770 set_target(*stub);
771 TRACE_IC("CallIC", key);
772 }
773
774 Handle<Object> result = GetProperty(isolate(), object, key);
775 RETURN_IF_EMPTY_HANDLE(isolate(), result);
776
777 // Make receiver an object if the callee requires it. Strict mode or builtin
778 // functions do not wrap the receiver, non-strict functions and objects
779 // called as functions do.
780 ReceiverToObjectIfRequired(result, object);
781 if (result->IsJSFunction()) return *result;
782
783 result = TryCallAsFunction(result);
784 if (result->IsJSFunction()) return *result;
785
786 return TypeError("property_not_function", object, key);
787 }
788
789
790 MaybeObject* LoadIC::Load(Handle<Object> object, 492 MaybeObject* LoadIC::Load(Handle<Object> object,
791 Handle<String> name) { 493 Handle<String> name) {
792 // If the object is undefined or null it's illegal to try to get any 494 // If the object is undefined or null it's illegal to try to get any
793 // of its properties; throw a TypeError in that case. 495 // of its properties; throw a TypeError in that case.
794 if (object->IsUndefined() || object->IsNull()) { 496 if (object->IsUndefined() || object->IsNull()) {
795 return TypeError("non_object_property_load", object, name); 497 return TypeError("non_object_property_load", object, name);
796 } 498 }
797 499
798 if (FLAG_use_ic) { 500 if (FLAG_use_ic) {
799 // Use specialized code for getting the length of strings and 501 // Use specialized code for getting the length of strings and
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 // Get the property. 575 // Get the property.
874 Handle<Object> result = 576 Handle<Object> result =
875 Object::GetProperty(object, object, &lookup, name, &attr); 577 Object::GetProperty(object, object, &lookup, name, &attr);
876 RETURN_IF_EMPTY_HANDLE(isolate(), result); 578 RETURN_IF_EMPTY_HANDLE(isolate(), result);
877 // If the property is not present, check if we need to throw an 579 // If the property is not present, check if we need to throw an
878 // exception. 580 // exception.
879 if ((lookup.IsInterceptor() || lookup.IsHandler()) && 581 if ((lookup.IsInterceptor() || lookup.IsHandler()) &&
880 attr == ABSENT && IsUndeclaredGlobal(object)) { 582 attr == ABSENT && IsUndeclaredGlobal(object)) {
881 return ReferenceError("not_defined", name); 583 return ReferenceError("not_defined", name);
882 } 584 }
585
883 return *result; 586 return *result;
884 } 587 }
885 588
886 589
887 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, 590 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
888 Handle<Map> new_receiver_map) { 591 Handle<Map> new_receiver_map) {
889 ASSERT(!new_receiver_map.is_null()); 592 ASSERT(!new_receiver_map.is_null());
890 for (int current = 0; current < receiver_maps->length(); ++current) { 593 for (int current = 0; current < receiver_maps->length(); ++current) {
891 if (!receiver_maps->at(current).is_null() && 594 if (!receiver_maps->at(current).is_null() &&
892 receiver_maps->at(current).is_identical_to(new_receiver_map)) { 595 receiver_maps->at(current).is_identical_to(new_receiver_map)) {
893 return false; 596 return false;
894 } 597 }
895 } 598 }
896 receiver_maps->Add(new_receiver_map); 599 receiver_maps->Add(new_receiver_map);
897 return true; 600 return true;
898 } 601 }
899 602
900 603
901 bool IC::UpdatePolymorphicIC(Handle<Type> type, 604 bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
902 Handle<String> name, 605 Handle<String> name,
903 Handle<Code> code) { 606 Handle<Code> code) {
904 if (!code->is_handler()) return false; 607 if (!code->is_handler()) return false;
905 TypeHandleList types; 608 TypeHandleList types;
906 CodeHandleList handlers; 609 CodeHandleList handlers;
907 610
908 int number_of_valid_types; 611 int number_of_valid_types;
909 int handler_to_overwrite = -1; 612 int handler_to_overwrite = -1;
910 613
911 target()->FindAllTypes(&types); 614 target()->FindAllTypes(&types);
912 int number_of_types = types.length(); 615 int number_of_types = types.length();
913 number_of_valid_types = number_of_types; 616 number_of_valid_types = number_of_types;
914 617
915 for (int i = 0; i < number_of_types; i++) { 618 for (int i = 0; i < number_of_types; i++) {
916 Handle<Type> current_type = types.at(i); 619 Handle<HeapType> current_type = types.at(i);
917 // Filter out deprecated maps to ensure their instances get migrated. 620 // Filter out deprecated maps to ensure their instances get migrated.
918 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) { 621 if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
919 number_of_valid_types--; 622 number_of_valid_types--;
920 // If the receiver type is already in the polymorphic IC, this indicates 623 // If the receiver type is already in the polymorphic IC, this indicates
921 // there was a prototoype chain failure. In that case, just overwrite the 624 // there was a prototoype chain failure. In that case, just overwrite the
922 // handler. 625 // handler.
923 } else if (type->IsCurrently(current_type)) { 626 } else if (type->IsCurrently(current_type)) {
924 ASSERT(handler_to_overwrite == -1); 627 ASSERT(handler_to_overwrite == -1);
925 number_of_valid_types--; 628 number_of_valid_types--;
926 handler_to_overwrite = i; 629 handler_to_overwrite = i;
927 } 630 }
928 } 631 }
929 632
930 if (number_of_valid_types >= 4) return false; 633 if (number_of_valid_types >= 4) return false;
931 if (number_of_types == 0) return false; 634 if (number_of_types == 0) return false;
932 if (!target()->FindHandlers(&handlers, types.length())) return false; 635 if (!target()->FindHandlers(&handlers, types.length())) return false;
933 636
934 number_of_valid_types++; 637 number_of_valid_types++;
935 if (handler_to_overwrite >= 0) { 638 if (handler_to_overwrite >= 0) {
936 handlers.Set(handler_to_overwrite, code); 639 handlers.Set(handler_to_overwrite, code);
937 } else { 640 } else {
938 types.Add(type); 641 types.Add(type);
939 handlers.Add(code); 642 handlers.Add(code);
940 } 643 }
941 644
942 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( 645 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
943 &types, &handlers, number_of_valid_types, name, extra_ic_state()); 646 kind(), &types, &handlers, number_of_valid_types, name, extra_ic_state());
944 set_target(*ic); 647 set_target(*ic);
945 return true; 648 return true;
946 } 649 }
947 650
948 651
949 Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) { 652 Handle<HeapType> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) {
950 return object->IsJSGlobalObject() 653 return object->IsJSGlobalObject()
951 ? Type::Constant(Handle<JSGlobalObject>::cast(object), isolate) 654 ? HeapType::Constant(Handle<JSGlobalObject>::cast(object), isolate)
952 : Type::OfCurrently(object, isolate); 655 : HeapType::OfCurrently(object, isolate);
953 } 656 }
954 657
955 658
956 Handle<Map> IC::TypeToMap(Type* type, Isolate* isolate) { 659 Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) {
957 if (type->Is(Type::Number())) return isolate->factory()->heap_number_map(); 660 if (type->Is(HeapType::Number()))
958 if (type->Is(Type::Boolean())) return isolate->factory()->oddball_map(); 661 return isolate->factory()->heap_number_map();
662 if (type->Is(HeapType::Boolean())) return isolate->factory()->oddball_map();
959 if (type->IsConstant()) { 663 if (type->IsConstant()) {
960 return handle(Handle<JSGlobalObject>::cast(type->AsConstant())->map()); 664 return handle(Handle<JSGlobalObject>::cast(type->AsConstant())->map());
961 } 665 }
962 ASSERT(type->IsClass()); 666 ASSERT(type->IsClass());
963 return type->AsClass(); 667 return type->AsClass();
964 } 668 }
965 669
966 670
967 Handle<Type> IC::MapToType(Handle<Map> map) { 671 template <class T>
968 Isolate* isolate = map->GetIsolate(); 672 typename T::TypeHandle IC::MapToType(Handle<Map> map,
969 if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(isolate); 673 typename T::Region* region) {
970 // The only oddballs that can be recorded in ICs are booleans. 674 if (map->instance_type() == HEAP_NUMBER_TYPE) {
971 if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(isolate); 675 return T::Number(region);
972 return Type::Class(map, isolate); 676 } else if (map->instance_type() == ODDBALL_TYPE) {
677 // The only oddballs that can be recorded in ICs are booleans.
678 return T::Boolean(region);
679 } else {
680 return T::Class(map, region);
681 }
973 } 682 }
974 683
975 684
976 void IC::UpdateMonomorphicIC(Handle<Type> type, 685 template
686 Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone);
687
688
689 template
690 Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region);
691
692
693 void IC::UpdateMonomorphicIC(Handle<HeapType> type,
977 Handle<Code> handler, 694 Handle<Code> handler,
978 Handle<String> name) { 695 Handle<String> name) {
979 if (!handler->is_handler()) return set_target(*handler); 696 if (!handler->is_handler()) return set_target(*handler);
980 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( 697 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
981 name, type, handler, extra_ic_state()); 698 kind(), name, type, handler, extra_ic_state());
982 set_target(*ic); 699 set_target(*ic);
983 } 700 }
984 701
985 702
986 void IC::CopyICToMegamorphicCache(Handle<String> name) { 703 void IC::CopyICToMegamorphicCache(Handle<String> name) {
987 TypeHandleList types; 704 TypeHandleList types;
988 CodeHandleList handlers; 705 CodeHandleList handlers;
989 target()->FindAllTypes(&types); 706 target()->FindAllTypes(&types);
990 if (!target()->FindHandlers(&handlers, types.length())) return; 707 if (!target()->FindHandlers(&handlers, types.length())) return;
991 for (int i = 0; i < types.length(); i++) { 708 for (int i = 0; i < types.length(); i++) {
992 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i)); 709 UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
993 } 710 }
994 } 711 }
995 712
996 713
997 bool IC::IsTransitionOfMonomorphicTarget(Handle<Type> type) { 714 bool IC::IsTransitionOfMonomorphicTarget(Handle<HeapType> type) {
998 if (!type->IsClass()) return false; 715 if (!type->IsClass()) return false;
999 Map* receiver_map = *type->AsClass(); 716 Map* receiver_map = *type->AsClass();
1000 Map* current_map = target()->FindFirstMap(); 717 Map* current_map = target()->FindFirstMap();
1001 ElementsKind receiver_elements_kind = receiver_map->elements_kind(); 718 ElementsKind receiver_elements_kind = receiver_map->elements_kind();
1002 bool more_general_transition = 719 bool more_general_transition =
1003 IsMoreGeneralElementsKindTransition( 720 IsMoreGeneralElementsKindTransition(
1004 current_map->elements_kind(), receiver_elements_kind); 721 current_map->elements_kind(), receiver_elements_kind);
1005 Map* transitioned_map = more_general_transition 722 Map* transitioned_map = more_general_transition
1006 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) 723 ? current_map->LookupElementsTransitionMap(receiver_elements_kind)
1007 : NULL; 724 : NULL;
1008 725
1009 return transitioned_map == receiver_map; 726 return transitioned_map == receiver_map;
1010 } 727 }
1011 728
1012 729
1013 void IC::PatchCache(Handle<Type> type, 730 void IC::PatchCache(Handle<HeapType> type,
1014 Handle<String> name, 731 Handle<String> name,
1015 Handle<Code> code) { 732 Handle<Code> code) {
1016 switch (state()) { 733 switch (state()) {
1017 case UNINITIALIZED: 734 case UNINITIALIZED:
1018 case PREMONOMORPHIC: 735 case PREMONOMORPHIC:
1019 case MONOMORPHIC_PROTOTYPE_FAILURE: 736 case MONOMORPHIC_PROTOTYPE_FAILURE:
1020 UpdateMonomorphicIC(type, code, name); 737 UpdateMonomorphicIC(type, code, name);
1021 break; 738 break;
1022 case MONOMORPHIC: { 739 case MONOMORPHIC: {
1023 // For now, call stubs are allowed to rewrite to the same stub. This 740 // For now, call stubs are allowed to rewrite to the same stub. This
1024 // happens e.g., when the field does not contain a function. 741 // happens e.g., when the field does not contain a function.
1025 ASSERT(target()->is_call_stub() || 742 ASSERT(!target().is_identical_to(code));
1026 target()->is_keyed_call_stub() ||
1027 !target().is_identical_to(code));
1028 Code* old_handler = target()->FindFirstHandler(); 743 Code* old_handler = target()->FindFirstHandler();
1029 if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { 744 if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) {
1030 UpdateMonomorphicIC(type, code, name); 745 UpdateMonomorphicIC(type, code, name);
1031 break; 746 break;
1032 } 747 }
1033 // Fall through. 748 // Fall through.
1034 } 749 }
1035 case POLYMORPHIC: 750 case POLYMORPHIC:
1036 if (!target()->is_keyed_stub()) { 751 if (!target()->is_keyed_stub()) {
1037 if (UpdatePolymorphicIC(type, name, code)) break; 752 if (UpdatePolymorphicIC(type, name, code)) break;
1038 CopyICToMegamorphicCache(name); 753 CopyICToMegamorphicCache(name);
1039 } 754 }
1040 set_target(*megamorphic_stub()); 755 set_target(*megamorphic_stub());
1041 // Fall through. 756 // Fall through.
1042 case MEGAMORPHIC: 757 case MEGAMORPHIC:
1043 UpdateMegamorphicCache(*type, *name, *code); 758 UpdateMegamorphicCache(*type, *name, *code);
1044 break; 759 break;
1045 case DEBUG_STUB: 760 case DEBUG_STUB:
1046 break; 761 break;
1047 case GENERIC: 762 case GENERIC:
1048 UNREACHABLE(); 763 UNREACHABLE();
1049 break; 764 break;
1050 } 765 }
1051 } 766 }
1052 767
1053 768
1054 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { 769 Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
1055 Handle<Code> ic = isolate->stub_cache()->ComputeLoad( 770 ExtraICState extra_state) {
1056 UNINITIALIZED, ComputeExtraICState(mode)); 771 return isolate->stub_cache()->ComputeLoad(UNINITIALIZED, extra_state);
1057 return ic;
1058 } 772 }
1059 773
1060 774
1061 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, 775 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
1062 ContextualMode mode) { 776 ExtraICState extra_state) {
1063 return isolate->stub_cache()->ComputeLoad( 777 return isolate->stub_cache()->ComputeLoad(PREMONOMORPHIC, extra_state);
1064 PREMONOMORPHIC, ComputeExtraICState(mode));
1065 } 778 }
1066 779
1067 780
1068 Handle<Code> LoadIC::megamorphic_stub() { 781 Handle<Code> LoadIC::megamorphic_stub() {
1069 return isolate()->stub_cache()->ComputeLoad( 782 return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state());
1070 MEGAMORPHIC, extra_ic_state());
1071 } 783 }
1072 784
1073 785
1074 Handle<Code> LoadIC::SimpleFieldLoad(int offset, 786 Handle<Code> LoadIC::SimpleFieldLoad(int offset,
1075 bool inobject, 787 bool inobject,
1076 Representation representation) { 788 Representation representation) {
1077 if (kind() == Code::LOAD_IC) { 789 if (kind() == Code::LOAD_IC) {
1078 LoadFieldStub stub(inobject, offset, representation); 790 LoadFieldStub stub(inobject, offset, representation);
1079 return stub.GetCode(isolate()); 791 return stub.GetCode(isolate());
1080 } else { 792 } else {
1081 KeyedLoadFieldStub stub(inobject, offset, representation); 793 KeyedLoadFieldStub stub(inobject, offset, representation);
1082 return stub.GetCode(isolate()); 794 return stub.GetCode(isolate());
1083 } 795 }
1084 } 796 }
1085 797
1086 798
1087 void LoadIC::UpdateCaches(LookupResult* lookup, 799 void LoadIC::UpdateCaches(LookupResult* lookup,
1088 Handle<Object> object, 800 Handle<Object> object,
1089 Handle<String> name) { 801 Handle<String> name) {
1090 if (state() == UNINITIALIZED) { 802 if (state() == UNINITIALIZED) {
1091 // This is the first time we execute this inline cache. 803 // This is the first time we execute this inline cache.
1092 // Set the target to the pre monomorphic stub to delay 804 // Set the target to the pre monomorphic stub to delay
1093 // setting the monomorphic state. 805 // setting the monomorphic state.
1094 set_target(*pre_monomorphic_stub()); 806 set_target(*pre_monomorphic_stub());
1095 TRACE_IC("LoadIC", name); 807 TRACE_IC("LoadIC", name);
1096 return; 808 return;
1097 } 809 }
1098 810
1099 Handle<Type> type = CurrentTypeOf(object, isolate()); 811 Handle<HeapType> type = CurrentTypeOf(object, isolate());
1100 Handle<Code> code; 812 Handle<Code> code;
1101 if (!lookup->IsCacheable()) { 813 if (!lookup->IsCacheable()) {
1102 // Bail out if the result is not cacheable. 814 // Bail out if the result is not cacheable.
1103 code = slow_stub(); 815 code = slow_stub();
1104 } else if (!lookup->IsProperty()) { 816 } else if (!lookup->IsProperty()) {
1105 if (kind() == Code::LOAD_IC) { 817 if (kind() == Code::LOAD_IC) {
1106 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, type); 818 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, type);
1107 } else { 819 } else {
1108 code = slow_stub(); 820 code = slow_stub();
1109 } 821 }
1110 } else { 822 } else {
1111 code = ComputeHandler(lookup, object, name); 823 code = ComputeHandler(lookup, object, name);
1112 } 824 }
1113 825
1114 PatchCache(type, name, code); 826 PatchCache(type, name, code);
1115 TRACE_IC("LoadIC", name); 827 TRACE_IC("LoadIC", name);
1116 } 828 }
1117 829
1118 830
1119 void IC::UpdateMegamorphicCache(Type* type, Name* name, Code* code) { 831 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {
1120 // Cache code holding map should be consistent with 832 // Cache code holding map should be consistent with
1121 // GenerateMonomorphicCacheProbe. 833 // GenerateMonomorphicCacheProbe.
1122 Map* map = *TypeToMap(type, isolate()); 834 Map* map = *TypeToMap(type, isolate());
1123 isolate()->stub_cache()->Set(name, map, code); 835 isolate()->stub_cache()->Set(name, map, code);
1124 } 836 }
1125 837
1126 838
1127 Handle<Code> IC::ComputeHandler(LookupResult* lookup, 839 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1128 Handle<Object> object, 840 Handle<Object> object,
1129 Handle<String> name, 841 Handle<String> name,
1130 Handle<Object> value) { 842 Handle<Object> value) {
1131 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object); 843 InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object);
1132 Handle<HeapObject> stub_holder(GetCodeCacheHolder( 844 Handle<HeapObject> stub_holder(GetCodeCacheHolder(
1133 isolate(), *object, cache_holder)); 845 isolate(), *object, cache_holder));
1134 846
1135 Handle<Code> code = isolate()->stub_cache()->FindHandler( 847 Handle<Code> code = isolate()->stub_cache()->FindHandler(
1136 name, handle(stub_holder->map()), kind(), cache_holder); 848 name, handle(stub_holder->map()), kind(), cache_holder,
1137 if (!code.is_null()) return code; 849 lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL);
850 if (!code.is_null()) {
851 return code;
852 }
1138 853
1139 code = CompileHandler(lookup, object, name, value, cache_holder); 854 code = CompileHandler(lookup, object, name, value, cache_holder);
1140 ASSERT(code->is_handler()); 855 ASSERT(code->is_handler());
1141 856
1142 if (code->type() != Code::NORMAL) { 857 if (code->type() != Code::NORMAL) {
1143 HeapObject::UpdateMapCodeCache(stub_holder, name, code); 858 HeapObject::UpdateMapCodeCache(stub_holder, name, code);
1144 } 859 }
1145 860
1146 return code; 861 return code;
1147 } 862 }
1148 863
1149 864
1150 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, 865 Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1151 Handle<Object> object, 866 Handle<Object> object,
1152 Handle<String> name, 867 Handle<String> name,
1153 Handle<Object> unused, 868 Handle<Object> unused,
1154 InlineCacheHolderFlag cache_holder) { 869 InlineCacheHolderFlag cache_holder) {
1155 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) { 870 if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
1156 int length_index = String::kLengthOffset / kPointerSize; 871 int length_index = String::kLengthOffset / kPointerSize;
1157 return SimpleFieldLoad(length_index); 872 return SimpleFieldLoad(length_index);
1158 } 873 }
1159 874
1160 Handle<Type> type = CurrentTypeOf(object, isolate()); 875 Handle<HeapType> type = CurrentTypeOf(object, isolate());
1161 Handle<JSObject> holder(lookup->holder()); 876 Handle<JSObject> holder(lookup->holder());
1162 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind()); 877 LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind());
1163 878
1164 switch (lookup->type()) { 879 switch (lookup->type()) {
1165 case FIELD: { 880 case FIELD: {
1166 PropertyIndex field = lookup->GetFieldIndex(); 881 PropertyIndex field = lookup->GetFieldIndex();
1167 if (object.is_identical_to(holder)) { 882 if (object.is_identical_to(holder)) {
1168 return SimpleFieldLoad(field.translate(holder), 883 return SimpleFieldLoad(field.translate(holder),
1169 field.is_inobject(holder), 884 field.is_inobject(holder),
1170 lookup->representation()); 885 lookup->representation());
(...skipping 25 matching lines...) Expand all
1196 // There is only one shared stub for loading normalized 911 // There is only one shared stub for loading normalized
1197 // properties. It does not traverse the prototype chain, so the 912 // properties. It does not traverse the prototype chain, so the
1198 // property must be found in the object for the stub to be 913 // property must be found in the object for the stub to be
1199 // applicable. 914 // applicable.
1200 if (!object.is_identical_to(holder)) break; 915 if (!object.is_identical_to(holder)) break;
1201 return isolate()->builtins()->LoadIC_Normal(); 916 return isolate()->builtins()->LoadIC_Normal();
1202 case CALLBACKS: { 917 case CALLBACKS: {
1203 // Use simple field loads for some well-known callback properties. 918 // Use simple field loads for some well-known callback properties.
1204 if (object->IsJSObject()) { 919 if (object->IsJSObject()) {
1205 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 920 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1206 Handle<Map> map(receiver->map()); 921 Handle<HeapType> type = IC::MapToType<HeapType>(
922 handle(receiver->map()), isolate());
1207 int object_offset; 923 int object_offset;
1208 if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { 924 if (Accessors::IsJSObjectFieldAccessor<HeapType>(
925 type, name, &object_offset)) {
1209 return SimpleFieldLoad(object_offset / kPointerSize); 926 return SimpleFieldLoad(object_offset / kPointerSize);
1210 } 927 }
1211 } 928 }
1212 929
1213 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 930 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1214 if (callback->IsExecutableAccessorInfo()) { 931 if (callback->IsExecutableAccessorInfo()) {
1215 Handle<ExecutableAccessorInfo> info = 932 Handle<ExecutableAccessorInfo> info =
1216 Handle<ExecutableAccessorInfo>::cast(callback); 933 Handle<ExecutableAccessorInfo>::cast(callback);
1217 if (v8::ToCData<Address>(info->getter()) == 0) break; 934 if (v8::ToCData<Address>(info->getter()) == 0) break;
1218 if (!info->IsCompatibleReceiver(*object)) break; 935 if (!info->IsCompatibleReceiver(*object)) break;
1219 return compiler.CompileLoadCallback(type, holder, name, info); 936 return compiler.CompileLoadCallback(type, holder, name, info);
1220 } else if (callback->IsAccessorPair()) { 937 } else if (callback->IsAccessorPair()) {
1221 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), 938 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1222 isolate()); 939 isolate());
1223 if (!getter->IsJSFunction()) break; 940 if (!getter->IsJSFunction()) break;
1224 if (holder->IsGlobalObject()) break; 941 if (holder->IsGlobalObject()) break;
1225 if (!holder->HasFastProperties()) break; 942 if (!holder->HasFastProperties()) break;
1226 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); 943 Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1227 if (!object->IsJSObject() && 944 if (!object->IsJSObject() &&
1228 !function->IsBuiltin() && 945 !function->IsBuiltin() &&
1229 function->shared()->is_classic_mode()) { 946 function->shared()->is_classic_mode()) {
1230 // Calling non-strict non-builtins with a value as the receiver 947 // Calling non-strict non-builtins with a value as the receiver
1231 // requires boxing. 948 // requires boxing.
1232 break; 949 break;
1233 } 950 }
1234 CallOptimization call_optimization(function); 951 CallOptimization call_optimization(function);
1235 if (call_optimization.is_simple_api_call() && 952 if (call_optimization.is_simple_api_call() &&
1236 call_optimization.IsCompatibleReceiver(*object)) { 953 call_optimization.IsCompatibleReceiver(object, holder)) {
1237 return compiler.CompileLoadCallback( 954 return compiler.CompileLoadCallback(
1238 type, holder, name, call_optimization); 955 type, holder, name, call_optimization);
1239 } 956 }
1240 return compiler.CompileLoadViaGetter(type, holder, name, function); 957 return compiler.CompileLoadViaGetter(type, holder, name, function);
1241 } 958 }
1242 // TODO(dcarney): Handle correctly. 959 // TODO(dcarney): Handle correctly.
1243 if (callback->IsDeclaredAccessorInfo()) break; 960 if (callback->IsDeclaredAccessorInfo()) break;
1244 ASSERT(callback->IsForeign()); 961 ASSERT(callback->IsForeign());
1245 // No IC support for old-style native accessors. 962 // No IC support for old-style native accessors.
1246 break; 963 break;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1340 1057
1341 1058
1342 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, Handle<Object> key) { 1059 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, Handle<Object> key) {
1343 if (MigrateDeprecated(object)) { 1060 if (MigrateDeprecated(object)) {
1344 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); 1061 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1345 } 1062 }
1346 1063
1347 MaybeObject* maybe_object = NULL; 1064 MaybeObject* maybe_object = NULL;
1348 Handle<Code> stub = generic_stub(); 1065 Handle<Code> stub = generic_stub();
1349 1066
1350 // Check for values that can be converted into an internalized string directly 1067 // Check for non-string values that can be converted into an
1351 // or is representable as a smi. 1068 // internalized string directly or is representable as a smi.
1352 key = TryConvertKey(key, isolate()); 1069 key = TryConvertKey(key, isolate());
1353 1070
1354 if (key->IsInternalizedString()) { 1071 if (key->IsInternalizedString()) {
1355 maybe_object = LoadIC::Load(object, Handle<String>::cast(key)); 1072 maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
1356 if (maybe_object->IsFailure()) return maybe_object; 1073 if (maybe_object->IsFailure()) return maybe_object;
1357 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { 1074 } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1358 ASSERT(!object->IsJSGlobalProxy()); 1075 ASSERT(!object->IsJSGlobalProxy());
1359 if (object->IsString() && key->IsNumber()) { 1076 if (object->IsString() && key->IsNumber()) {
1360 if (state() == UNINITIALIZED) stub = string_stub(); 1077 if (state() == UNINITIALIZED) stub = string_stub();
1361 } else if (object->IsJSObject()) { 1078 } else if (object->IsJSObject()) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); 1134 holder = Handle<JSObject>(lookup->holder(), lookup->isolate());
1418 } 1135 }
1419 1136
1420 // While normally LookupTransition gets passed the receiver, in this case we 1137 // While normally LookupTransition gets passed the receiver, in this case we
1421 // pass the holder of the property that we overwrite. This keeps the holder in 1138 // pass the holder of the property that we overwrite. This keeps the holder in
1422 // the LookupResult intact so we can later use it to generate a prototype 1139 // the LookupResult intact so we can later use it to generate a prototype
1423 // chain check. This avoids a double lookup, but requires us to pass in the 1140 // chain check. This avoids a double lookup, but requires us to pass in the
1424 // receiver when trying to fetch extra information from the transition. 1141 // receiver when trying to fetch extra information from the transition.
1425 receiver->map()->LookupTransition(*holder, *name, lookup); 1142 receiver->map()->LookupTransition(*holder, *name, lookup);
1426 if (!lookup->IsTransition()) return false; 1143 if (!lookup->IsTransition()) return false;
1427 PropertyDetails target_details = 1144 PropertyDetails target_details = lookup->GetTransitionDetails();
1428 lookup->GetTransitionDetails(receiver->map());
1429 if (target_details.IsReadOnly()) return false; 1145 if (target_details.IsReadOnly()) return false;
1430 1146
1431 // If the value that's being stored does not fit in the field that the 1147 // If the value that's being stored does not fit in the field that the
1432 // instance would transition to, create a new transition that fits the value. 1148 // instance would transition to, create a new transition that fits the value.
1433 // This has to be done before generating the IC, since that IC will embed the 1149 // This has to be done before generating the IC, since that IC will embed the
1434 // transition target. 1150 // transition target.
1435 // Ensure the instance and its map were migrated before trying to update the 1151 // Ensure the instance and its map were migrated before trying to update the
1436 // transition target. 1152 // transition target.
1437 ASSERT(!receiver->map()->is_deprecated()); 1153 ASSERT(!receiver->map()->is_deprecated());
1438 if (!value->FitsRepresentation(target_details.representation())) { 1154 if (!value->FitsRepresentation(target_details.representation())) {
1439 Handle<Map> target(lookup->GetTransitionMapFromMap(receiver->map())); 1155 Handle<Map> target(lookup->GetTransitionTarget());
1440 Map::GeneralizeRepresentation( 1156 Map::GeneralizeRepresentation(
1441 target, target->LastAdded(), 1157 target, target->LastAdded(),
1442 value->OptimalRepresentation(), FORCE_FIELD); 1158 value->OptimalRepresentation(), FORCE_FIELD);
1443 // Lookup the transition again since the transition tree may have changed 1159 // Lookup the transition again since the transition tree may have changed
1444 // entirely by the migration above. 1160 // entirely by the migration above.
1445 receiver->map()->LookupTransition(*holder, *name, lookup); 1161 receiver->map()->LookupTransition(*holder, *name, lookup);
1446 if (!lookup->IsTransition()) return false; 1162 if (!lookup->IsTransition()) return false;
1447 ic->MarkMonomorphicPrototypeFailure(); 1163 ic->MarkMonomorphicPrototypeFailure();
1448 } 1164 }
1449 return true; 1165 return true;
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 1318
1603 Handle<JSObject> holder(lookup->holder()); 1319 Handle<JSObject> holder(lookup->holder());
1604 // Handlers do not use strict mode. 1320 // Handlers do not use strict mode.
1605 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind()); 1321 StoreStubCompiler compiler(isolate(), kNonStrictMode, kind());
1606 switch (lookup->type()) { 1322 switch (lookup->type()) {
1607 case FIELD: 1323 case FIELD:
1608 return compiler.CompileStoreField(receiver, lookup, name); 1324 return compiler.CompileStoreField(receiver, lookup, name);
1609 case TRANSITION: { 1325 case TRANSITION: {
1610 // Explicitly pass in the receiver map since LookupForWrite may have 1326 // Explicitly pass in the receiver map since LookupForWrite may have
1611 // stored something else than the receiver in the holder. 1327 // stored something else than the receiver in the holder.
1612 Handle<Map> transition( 1328 Handle<Map> transition(lookup->GetTransitionTarget());
1613 lookup->GetTransitionTarget(receiver->map()), isolate()); 1329 PropertyDetails details = transition->GetLastDescriptorDetails();
1614 int descriptor = transition->LastAdded();
1615
1616 DescriptorArray* target_descriptors = transition->instance_descriptors();
1617 PropertyDetails details = target_descriptors->GetDetails(descriptor);
1618 1330
1619 if (details.type() == CALLBACKS || details.attributes() != NONE) break; 1331 if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1620 1332
1621 return compiler.CompileStoreTransition( 1333 return compiler.CompileStoreTransition(
1622 receiver, lookup, transition, name); 1334 receiver, lookup, transition, name);
1623 } 1335 }
1624 case NORMAL: 1336 case NORMAL:
1625 if (kind() == Code::KEYED_STORE_IC) break; 1337 if (kind() == Code::KEYED_STORE_IC) break;
1626 if (receiver->IsGlobalObject()) { 1338 if (receiver->IsGlobalObject()) {
1627 // The stub generated for the global object picks the value directly 1339 // The stub generated for the global object picks the value directly
1628 // from the property cell. So the property must be directly on the 1340 // from the property cell. So the property must be directly on the
1629 // global object. 1341 // global object.
1630 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1342 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1631 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate()); 1343 Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate());
1632 Handle<Type> union_type = PropertyCell::UpdatedType(cell, value); 1344 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
1633 StoreGlobalStub stub(union_type->IsConstant()); 1345 StoreGlobalStub stub(union_type->IsConstant());
1634 1346
1635 Handle<Code> code = stub.GetCodeCopyFromTemplate( 1347 Handle<Code> code = stub.GetCodeCopyFromTemplate(
1636 isolate(), receiver->map(), *cell); 1348 isolate(), receiver->map(), *cell);
1637 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. 1349 // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1638 HeapObject::UpdateMapCodeCache(receiver, name, code); 1350 HeapObject::UpdateMapCodeCache(receiver, name, code);
1639 return code; 1351 return code;
1640 } 1352 }
1641 ASSERT(holder.is_identical_to(receiver)); 1353 ASSERT(holder.is_identical_to(receiver));
1642 return isolate()->builtins()->StoreIC_Normal(); 1354 return isolate()->builtins()->StoreIC_Normal();
1643 case CALLBACKS: { 1355 case CALLBACKS: {
1644 if (kind() == Code::KEYED_STORE_IC) break; 1356 if (kind() == Code::KEYED_STORE_IC) break;
1645 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); 1357 Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1646 if (callback->IsExecutableAccessorInfo()) { 1358 if (callback->IsExecutableAccessorInfo()) {
1647 Handle<ExecutableAccessorInfo> info = 1359 Handle<ExecutableAccessorInfo> info =
1648 Handle<ExecutableAccessorInfo>::cast(callback); 1360 Handle<ExecutableAccessorInfo>::cast(callback);
1649 if (v8::ToCData<Address>(info->setter()) == 0) break; 1361 if (v8::ToCData<Address>(info->setter()) == 0) break;
1650 if (!holder->HasFastProperties()) break; 1362 if (!holder->HasFastProperties()) break;
1651 if (!info->IsCompatibleReceiver(*receiver)) break; 1363 if (!info->IsCompatibleReceiver(*receiver)) break;
1652 return compiler.CompileStoreCallback(receiver, holder, name, info); 1364 return compiler.CompileStoreCallback(receiver, holder, name, info);
1653 } else if (callback->IsAccessorPair()) { 1365 } else if (callback->IsAccessorPair()) {
1654 Handle<Object> setter( 1366 Handle<Object> setter(
1655 Handle<AccessorPair>::cast(callback)->setter(), isolate()); 1367 Handle<AccessorPair>::cast(callback)->setter(), isolate());
1656 if (!setter->IsJSFunction()) break; 1368 if (!setter->IsJSFunction()) break;
1657 if (holder->IsGlobalObject()) break; 1369 if (holder->IsGlobalObject()) break;
1658 if (!holder->HasFastProperties()) break; 1370 if (!holder->HasFastProperties()) break;
1659 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); 1371 Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
1660 CallOptimization call_optimization(function); 1372 CallOptimization call_optimization(function);
1661 if (call_optimization.is_simple_api_call() && 1373 if (call_optimization.is_simple_api_call() &&
1662 call_optimization.IsCompatibleReceiver(*receiver)) { 1374 call_optimization.IsCompatibleReceiver(receiver, holder)) {
1663 return compiler.CompileStoreCallback( 1375 return compiler.CompileStoreCallback(
1664 receiver, holder, name, call_optimization); 1376 receiver, holder, name, call_optimization);
1665 } 1377 }
1666 return compiler.CompileStoreViaSetter( 1378 return compiler.CompileStoreViaSetter(
1667 receiver, holder, name, Handle<JSFunction>::cast(setter)); 1379 receiver, holder, name, Handle<JSFunction>::cast(setter));
1668 } 1380 }
1669 // TODO(dcarney): Handle correctly. 1381 // TODO(dcarney): Handle correctly.
1670 if (callback->IsDeclaredAccessorInfo()) break; 1382 if (callback->IsDeclaredAccessorInfo()) break;
1671 ASSERT(callback->IsForeign()); 1383 ASSERT(callback->IsForeign());
1672 // No IC support for old-style native accessors. 1384 // No IC support for old-style native accessors.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1724 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); 1436 KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state());
1725 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); 1437 Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1726 if (state() == MONOMORPHIC) { 1438 if (state() == MONOMORPHIC) {
1727 // If the "old" and "new" maps are in the same elements map family, stay 1439 // If the "old" and "new" maps are in the same elements map family, stay
1728 // MONOMORPHIC and use the map for the most generic ElementsKind. 1440 // MONOMORPHIC and use the map for the most generic ElementsKind.
1729 Handle<Map> transitioned_receiver_map = receiver_map; 1441 Handle<Map> transitioned_receiver_map = receiver_map;
1730 if (IsTransitionStoreMode(store_mode)) { 1442 if (IsTransitionStoreMode(store_mode)) {
1731 transitioned_receiver_map = 1443 transitioned_receiver_map =
1732 ComputeTransitionedMap(receiver, store_mode); 1444 ComputeTransitionedMap(receiver, store_mode);
1733 } 1445 }
1734 if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) { 1446 if (IsTransitionOfMonomorphicTarget(
1447 MapToType<HeapType>(transitioned_receiver_map, isolate()))) {
1735 // Element family is the same, use the "worst" case map. 1448 // Element family is the same, use the "worst" case map.
1736 store_mode = GetNonTransitioningStoreMode(store_mode); 1449 store_mode = GetNonTransitioningStoreMode(store_mode);
1737 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1450 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1738 transitioned_receiver_map, strict_mode(), store_mode); 1451 transitioned_receiver_map, strict_mode(), store_mode);
1739 } else if (*previous_receiver_map == receiver->map() && 1452 } else if (*previous_receiver_map == receiver->map() &&
1740 old_store_mode == STANDARD_STORE && 1453 old_store_mode == STANDARD_STORE &&
1741 (IsGrowStoreMode(store_mode) || 1454 (IsGrowStoreMode(store_mode) ||
1742 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || 1455 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1743 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { 1456 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1744 // A "normal" IC that handles stores can switch to a version that can 1457 // A "normal" IC that handles stores can switch to a version that can
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1936 if (MigrateDeprecated(object)) { 1649 if (MigrateDeprecated(object)) {
1937 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, 1650 Handle<Object> result = Runtime::SetObjectProperty(isolate(), object,
1938 key, 1651 key,
1939 value, 1652 value,
1940 NONE, 1653 NONE,
1941 strict_mode()); 1654 strict_mode());
1942 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1655 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1943 return *result; 1656 return *result;
1944 } 1657 }
1945 1658
1946 // Check for values that can be converted into an internalized string directly 1659 // Check for non-string values that can be converted into an
1947 // or is representable as a smi. 1660 // internalized string directly or is representable as a smi.
1948 key = TryConvertKey(key, isolate()); 1661 key = TryConvertKey(key, isolate());
1949 1662
1950 MaybeObject* maybe_object = NULL; 1663 MaybeObject* maybe_object = NULL;
1951 Handle<Code> stub = generic_stub(); 1664 Handle<Code> stub = generic_stub();
1952 1665
1953 if (key->IsInternalizedString()) { 1666 if (key->IsInternalizedString()) {
1954 maybe_object = StoreIC::Store(object, 1667 maybe_object = StoreIC::Store(object,
1955 Handle<String>::cast(key), 1668 Handle<String>::cast(key),
1956 value, 1669 value,
1957 JSReceiver::MAY_BE_STORE_FROM_KEYED); 1670 JSReceiver::MAY_BE_STORE_FROM_KEYED);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2013 1726
2014 1727
2015 #undef TRACE_IC 1728 #undef TRACE_IC
2016 1729
2017 1730
2018 // ---------------------------------------------------------------------------- 1731 // ----------------------------------------------------------------------------
2019 // Static IC stub generators. 1732 // Static IC stub generators.
2020 // 1733 //
2021 1734
2022 // Used from ic-<arch>.cc. 1735 // Used from ic-<arch>.cc.
2023 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2024 HandleScope scope(isolate);
2025 ASSERT(args.length() == 2);
2026 CallIC ic(isolate);
2027 Handle<Object> receiver = args.at<Object>(0);
2028 Handle<String> key = args.at<String>(1);
2029 ic.UpdateState(receiver, key);
2030 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2031 JSFunction* raw_function;
2032 if (!maybe_result->To(&raw_function)) return maybe_result;
2033
2034 // The first time the inline cache is updated may be the first time the
2035 // function it references gets called. If the function is lazily compiled
2036 // then the first call will trigger a compilation. We check for this case
2037 // and we do the compilation immediately, instead of waiting for the stub
2038 // currently attached to the JSFunction object to trigger compilation.
2039 if (raw_function->is_compiled()) return raw_function;
2040
2041 Handle<JSFunction> function(raw_function);
2042 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
2043 return *function;
2044 }
2045
2046
2047 // Used from ic-<arch>.cc.
2048 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
2049 HandleScope scope(isolate);
2050 ASSERT(args.length() == 2);
2051 KeyedCallIC ic(isolate);
2052 Handle<Object> receiver = args.at<Object>(0);
2053 Handle<Object> key = args.at<Object>(1);
2054 ic.UpdateState(receiver, key);
2055 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2056 // Result could be a function or a failure.
2057 JSFunction* raw_function = NULL;
2058 if (!maybe_result->To(&raw_function)) return maybe_result;
2059
2060 if (raw_function->is_compiled()) return raw_function;
2061
2062 Handle<JSFunction> function(raw_function, isolate);
2063 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
2064 return *function;
2065 }
2066
2067
2068 // Used from ic-<arch>.cc. 1736 // Used from ic-<arch>.cc.
2069 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { 1737 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
2070 HandleScope scope(isolate); 1738 HandleScope scope(isolate);
2071 ASSERT(args.length() == 2); 1739 ASSERT(args.length() == 2);
2072 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); 1740 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2073 Handle<Object> receiver = args.at<Object>(0); 1741 Handle<Object> receiver = args.at<Object>(0);
2074 Handle<String> key = args.at<String>(1); 1742 Handle<String> key = args.at<String>(1);
2075 ic.UpdateState(receiver, key); 1743 ic.UpdateState(receiver, key);
2076 return ic.Load(receiver, key); 1744 return ic.Load(receiver, key);
2077 } 1745 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2116 HandleScope scope(isolate); 1784 HandleScope scope(isolate);
2117 ASSERT(args.length() == 3); 1785 ASSERT(args.length() == 3);
2118 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 1786 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2119 Handle<Object> receiver = args.at<Object>(0); 1787 Handle<Object> receiver = args.at<Object>(0);
2120 Handle<String> key = args.at<String>(1); 1788 Handle<String> key = args.at<String>(1);
2121 ic.UpdateState(receiver, key); 1789 ic.UpdateState(receiver, key);
2122 return ic.Store(receiver, key, args.at<Object>(2)); 1790 return ic.Store(receiver, key, args.at<Object>(2));
2123 } 1791 }
2124 1792
2125 1793
2126 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure) {
2127 HandleScope scope(isolate);
2128 ASSERT(args.length() == 2);
2129 KeyedCallIC ic(isolate);
2130 Arguments* caller_args = reinterpret_cast<Arguments*>(args[0]);
2131 Handle<Object> key = args.at<Object>(1);
2132 Handle<Object> receiver((*caller_args)[0], isolate);
2133
2134 ic.UpdateState(receiver, key);
2135 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2136 // Result could be a function or a failure.
2137 JSFunction* raw_function = NULL;
2138 if (!maybe_result->To(&raw_function)) return maybe_result;
2139
2140 if (raw_function->is_compiled()) return raw_function;
2141
2142 Handle<JSFunction> function(raw_function, isolate);
2143 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
2144 return *function;
2145 }
2146
2147
2148 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { 1794 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
2149 SealHandleScope shs(isolate); 1795 SealHandleScope shs(isolate);
2150 1796
2151 ASSERT(args.length() == 2); 1797 ASSERT(args.length() == 2);
2152 JSArray* receiver = JSArray::cast(args[0]); 1798 JSArray* receiver = JSArray::cast(args[0]);
2153 Object* len = args[1]; 1799 Object* len = args[1];
2154 1800
2155 // The generated code should filter out non-Smis before we get here. 1801 // The generated code should filter out non-Smis before we get here.
2156 ASSERT(len->IsSmi()); 1802 ASSERT(len->IsSmi());
2157 1803
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
2556 GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE); 2202 GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE);
2557 GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT); 2203 GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT);
2558 GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE); 2204 GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE);
2559 GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT); 2205 GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT);
2560 GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE); 2206 GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE);
2561 GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE); 2207 GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE);
2562 #undef GENERATE 2208 #undef GENERATE
2563 } 2209 }
2564 2210
2565 2211
2566 Handle<Type> BinaryOpIC::State::GetResultType(Isolate* isolate) const { 2212 Type* BinaryOpIC::State::GetResultType(Zone* zone) const {
2567 Kind result_kind = result_kind_; 2213 Kind result_kind = result_kind_;
2568 if (HasSideEffects()) { 2214 if (HasSideEffects()) {
2569 result_kind = NONE; 2215 result_kind = NONE;
2570 } else if (result_kind == GENERIC && op_ == Token::ADD) { 2216 } else if (result_kind == GENERIC && op_ == Token::ADD) {
2571 return Type::Union(Type::Number(isolate), Type::String(isolate), isolate); 2217 return Type::Union(Type::Number(zone), Type::String(zone), zone);
2572 } else if (result_kind == NUMBER && op_ == Token::SHR) { 2218 } else if (result_kind == NUMBER && op_ == Token::SHR) {
2573 return Type::Unsigned32(isolate); 2219 return Type::Unsigned32(zone);
2574 } 2220 }
2575 ASSERT_NE(GENERIC, result_kind); 2221 ASSERT_NE(GENERIC, result_kind);
2576 return KindToType(result_kind, isolate); 2222 return KindToType(result_kind, zone);
2577 } 2223 }
2578 2224
2579 2225
2580 void BinaryOpIC::State::Print(StringStream* stream) const { 2226 void BinaryOpIC::State::Print(StringStream* stream) const {
2581 stream->Add("(%s", Token::Name(op_)); 2227 stream->Add("(%s", Token::Name(op_));
2582 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); 2228 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft");
2583 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); 2229 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight");
2584 if (CouldCreateAllocationMementos()) stream->Add("_CreateAllocationMementos"); 2230 if (CouldCreateAllocationMementos()) stream->Add("_CreateAllocationMementos");
2585 stream->Add(":%s*", KindToString(left_kind_)); 2231 stream->Add(":%s*", KindToString(left_kind_));
2586 if (fixed_right_arg_.has_value) { 2232 if (fixed_right_arg_.has_value) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2697 case NUMBER: return "Number"; 2343 case NUMBER: return "Number";
2698 case STRING: return "String"; 2344 case STRING: return "String";
2699 case GENERIC: return "Generic"; 2345 case GENERIC: return "Generic";
2700 } 2346 }
2701 UNREACHABLE(); 2347 UNREACHABLE();
2702 return NULL; 2348 return NULL;
2703 } 2349 }
2704 2350
2705 2351
2706 // static 2352 // static
2707 Handle<Type> BinaryOpIC::State::KindToType(Kind kind, Isolate* isolate) { 2353 Type* BinaryOpIC::State::KindToType(Kind kind, Zone* zone) {
2708 switch (kind) { 2354 switch (kind) {
2709 case NONE: return Type::None(isolate); 2355 case NONE: return Type::None(zone);
2710 case SMI: return Type::Smi(isolate); 2356 case SMI: return Type::Smi(zone);
2711 case INT32: return Type::Signed32(isolate); 2357 case INT32: return Type::Signed32(zone);
2712 case NUMBER: return Type::Number(isolate); 2358 case NUMBER: return Type::Number(zone);
2713 case STRING: return Type::String(isolate); 2359 case STRING: return Type::String(zone);
2714 case GENERIC: return Type::Any(isolate); 2360 case GENERIC: return Type::Any(zone);
2715 } 2361 }
2716 UNREACHABLE(); 2362 UNREACHABLE();
2717 return Handle<Type>(); 2363 return NULL;
2718 } 2364 }
2719 2365
2720 2366
2721 MaybeObject* BinaryOpIC::Transition(Handle<AllocationSite> allocation_site, 2367 MaybeObject* BinaryOpIC::Transition(Handle<AllocationSite> allocation_site,
2722 Handle<Object> left, 2368 Handle<Object> left,
2723 Handle<Object> right) { 2369 Handle<Object> right) {
2724 State state(target()->extended_extra_ic_state()); 2370 State state(target()->extra_ic_state());
2725 2371
2726 // Compute the actual result using the builtin for the binary operation. 2372 // Compute the actual result using the builtin for the binary operation.
2727 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( 2373 Object* builtin = isolate()->js_builtins_object()->javascript_builtin(
2728 TokenToJSBuiltin(state.op())); 2374 TokenToJSBuiltin(state.op()));
2729 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); 2375 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
2730 bool caught_exception; 2376 bool caught_exception;
2731 Handle<Object> result = Execution::Call( 2377 Handle<Object> result = Execution::Call(
2732 isolate(), function, left, 1, &right, &caught_exception); 2378 isolate(), function, left, 1, &right, &caught_exception);
2733 if (caught_exception) return Failure::Exception(); 2379 if (caught_exception) return Failure::Exception();
2734 2380
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 case UNIQUE_NAME: return "UNIQUE_NAME"; 2483 case UNIQUE_NAME: return "UNIQUE_NAME";
2838 case OBJECT: return "OBJECT"; 2484 case OBJECT: return "OBJECT";
2839 case KNOWN_OBJECT: return "KNOWN_OBJECT"; 2485 case KNOWN_OBJECT: return "KNOWN_OBJECT";
2840 case GENERIC: return "GENERIC"; 2486 case GENERIC: return "GENERIC";
2841 } 2487 }
2842 UNREACHABLE(); 2488 UNREACHABLE();
2843 return NULL; 2489 return NULL;
2844 } 2490 }
2845 2491
2846 2492
2847 Handle<Type> CompareIC::StateToType( 2493 Type* CompareIC::StateToType(
2848 Isolate* isolate, 2494 Zone* zone,
2849 CompareIC::State state, 2495 CompareIC::State state,
2850 Handle<Map> map) { 2496 Handle<Map> map) {
2851 switch (state) { 2497 switch (state) {
2852 case CompareIC::UNINITIALIZED: return Type::None(isolate); 2498 case CompareIC::UNINITIALIZED: return Type::None(zone);
2853 case CompareIC::SMI: return Type::Smi(isolate); 2499 case CompareIC::SMI: return Type::Smi(zone);
2854 case CompareIC::NUMBER: return Type::Number(isolate); 2500 case CompareIC::NUMBER: return Type::Number(zone);
2855 case CompareIC::STRING: return Type::String(isolate); 2501 case CompareIC::STRING: return Type::String(zone);
2856 case CompareIC::INTERNALIZED_STRING: 2502 case CompareIC::INTERNALIZED_STRING: return Type::InternalizedString(zone);
2857 return Type::InternalizedString(isolate); 2503 case CompareIC::UNIQUE_NAME: return Type::UniqueName(zone);
2858 case CompareIC::UNIQUE_NAME: return Type::UniqueName(isolate); 2504 case CompareIC::OBJECT: return Type::Receiver(zone);
2859 case CompareIC::OBJECT: return Type::Receiver(isolate);
2860 case CompareIC::KNOWN_OBJECT: 2505 case CompareIC::KNOWN_OBJECT:
2861 return map.is_null() 2506 return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone);
2862 ? Type::Receiver(isolate) : Type::Class(map, isolate); 2507 case CompareIC::GENERIC: return Type::Any(zone);
2863 case CompareIC::GENERIC: return Type::Any(isolate);
2864 } 2508 }
2865 UNREACHABLE(); 2509 UNREACHABLE();
2866 return Handle<Type>(); 2510 return NULL;
2867 } 2511 }
2868 2512
2869 2513
2870 void CompareIC::StubInfoToType(int stub_minor_key, 2514 void CompareIC::StubInfoToType(int stub_minor_key,
2871 Handle<Type>* left_type, 2515 Type** left_type,
2872 Handle<Type>* right_type, 2516 Type** right_type,
2873 Handle<Type>* overall_type, 2517 Type** overall_type,
2874 Handle<Map> map, 2518 Handle<Map> map,
2875 Isolate* isolate) { 2519 Zone* zone) {
2876 State left_state, right_state, handler_state; 2520 State left_state, right_state, handler_state;
2877 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state, 2521 ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
2878 &handler_state, NULL); 2522 &handler_state, NULL);
2879 *left_type = StateToType(isolate, left_state); 2523 *left_type = StateToType(zone, left_state);
2880 *right_type = StateToType(isolate, right_state); 2524 *right_type = StateToType(zone, right_state);
2881 *overall_type = StateToType(isolate, handler_state, map); 2525 *overall_type = StateToType(zone, handler_state, map);
2882 } 2526 }
2883 2527
2884 2528
2885 CompareIC::State CompareIC::NewInputState(State old_state, 2529 CompareIC::State CompareIC::NewInputState(State old_state,
2886 Handle<Object> value) { 2530 Handle<Object> value) {
2887 switch (old_state) { 2531 switch (old_state) {
2888 case UNINITIALIZED: 2532 case UNINITIALIZED:
2889 if (value->IsSmi()) return SMI; 2533 if (value->IsSmi()) return SMI;
2890 if (value->IsHeapNumber()) return NUMBER; 2534 if (value->IsHeapNumber()) return NUMBER;
2891 if (value->IsInternalizedString()) return INTERNALIZED_STRING; 2535 if (value->IsInternalizedString()) return INTERNALIZED_STRING;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
3032 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2676 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
3033 HandleScope scope(isolate); 2677 HandleScope scope(isolate);
3034 ASSERT(args.length() == 3); 2678 ASSERT(args.length() == 3);
3035 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2))); 2679 CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
3036 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); 2680 return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
3037 } 2681 }
3038 2682
3039 2683
3040 void CompareNilIC::Clear(Address address, Code* target) { 2684 void CompareNilIC::Clear(Address address, Code* target) {
3041 if (IsCleared(target)) return; 2685 if (IsCleared(target)) return;
3042 ExtraICState state = target->extended_extra_ic_state(); 2686 ExtraICState state = target->extra_ic_state();
3043 2687
3044 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); 2688 CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
3045 stub.ClearState(); 2689 stub.ClearState();
3046 2690
3047 Code* code = NULL; 2691 Code* code = NULL;
3048 CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); 2692 CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
3049 2693
3050 SetTargetAtAddress(address, code); 2694 SetTargetAtAddress(address, code);
3051 } 2695 }
3052 2696
3053 2697
3054 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil, 2698 MaybeObject* CompareNilIC::DoCompareNilSlow(NilValue nil,
3055 Handle<Object> object) { 2699 Handle<Object> object) {
3056 if (object->IsNull() || object->IsUndefined()) { 2700 if (object->IsNull() || object->IsUndefined()) {
3057 return Smi::FromInt(true); 2701 return Smi::FromInt(true);
3058 } 2702 }
3059 return Smi::FromInt(object->IsUndetectableObject()); 2703 return Smi::FromInt(object->IsUndetectableObject());
3060 } 2704 }
3061 2705
3062 2706
3063 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) { 2707 MaybeObject* CompareNilIC::CompareNil(Handle<Object> object) {
3064 ExtraICState extra_ic_state = target()->extended_extra_ic_state(); 2708 ExtraICState extra_ic_state = target()->extra_ic_state();
3065 2709
3066 CompareNilICStub stub(extra_ic_state); 2710 CompareNilICStub stub(extra_ic_state);
3067 2711
3068 // Extract the current supported types from the patched IC and calculate what 2712 // Extract the current supported types from the patched IC and calculate what
3069 // types must be supported as a result of the miss. 2713 // types must be supported as a result of the miss.
3070 bool already_monomorphic = stub.IsMonomorphic(); 2714 bool already_monomorphic = stub.IsMonomorphic();
3071 2715
3072 stub.UpdateStatus(object); 2716 stub.UpdateStatus(object);
3073 2717
3074 NilValue nil = stub.GetNilValue(); 2718 NilValue nil = stub.GetNilValue();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3138 return Builtins::SHR; 2782 return Builtins::SHR;
3139 break; 2783 break;
3140 case Token::SHL: 2784 case Token::SHL:
3141 return Builtins::SHL; 2785 return Builtins::SHL;
3142 break; 2786 break;
3143 } 2787 }
3144 } 2788 }
3145 2789
3146 2790
3147 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object) { 2791 MaybeObject* ToBooleanIC::ToBoolean(Handle<Object> object) {
3148 ToBooleanStub stub(target()->extended_extra_ic_state()); 2792 ToBooleanStub stub(target()->extra_ic_state());
3149 bool to_boolean_value = stub.UpdateStatus(object); 2793 bool to_boolean_value = stub.UpdateStatus(object);
3150 Handle<Code> code = stub.GetCode(isolate()); 2794 Handle<Code> code = stub.GetCode(isolate());
3151 set_target(*code); 2795 set_target(*code);
3152 return Smi::FromInt(to_boolean_value ? 1 : 0); 2796 return Smi::FromInt(to_boolean_value ? 1 : 0);
3153 } 2797 }
3154 2798
3155 2799
3156 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) { 2800 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
3157 ASSERT(args.length() == 1); 2801 ASSERT(args.length() == 1);
3158 HandleScope scope(isolate); 2802 HandleScope scope(isolate);
(...skipping 10 matching lines...) Expand all
3169 #undef ADDR 2813 #undef ADDR
3170 }; 2814 };
3171 2815
3172 2816
3173 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2817 Address IC::AddressFromUtilityId(IC::UtilityId id) {
3174 return IC_utilities[id]; 2818 return IC_utilities[id];
3175 } 2819 }
3176 2820
3177 2821
3178 } } // namespace v8::internal 2822 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698