| OLD | NEW |
| 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 17 matching lines...) Expand all Loading... |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "accessors.h" | 30 #include "accessors.h" |
| 31 #include "api.h" | 31 #include "api.h" |
| 32 #include "arguments.h" | 32 #include "arguments.h" |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "execution.h" | 34 #include "execution.h" |
| 35 #include "ic-inl.h" | 35 #include "ic-inl.h" |
| 36 #include "runtime.h" | 36 #include "runtime.h" |
| 37 #include "stub-cache.h" | 37 #include "stub-cache.h" |
| 38 #include "v8conversions.h" |
| 38 | 39 |
| 39 namespace v8 { | 40 namespace v8 { |
| 40 namespace internal { | 41 namespace internal { |
| 41 | 42 |
| 42 #ifdef DEBUG | 43 #ifdef DEBUG |
| 43 char IC::TransitionMarkFromState(IC::State state) { | 44 char IC::TransitionMarkFromState(IC::State state) { |
| 44 switch (state) { | 45 switch (state) { |
| 45 case UNINITIALIZED: return '0'; | 46 case UNINITIALIZED: return '0'; |
| 46 case PREMONOMORPHIC: return '.'; | 47 case PREMONOMORPHIC: return '.'; |
| 47 case MONOMORPHIC: return '1'; | 48 case MONOMORPHIC: return '1'; |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 bool was_uninitialized = | 434 bool was_uninitialized = |
| 434 old_state == UNINITIALIZED || old_state == PREMONOMORPHIC; | 435 old_state == UNINITIALIZED || old_state == PREMONOMORPHIC; |
| 435 bool is_uninitialized = | 436 bool is_uninitialized = |
| 436 new_state == UNINITIALIZED || new_state == PREMONOMORPHIC; | 437 new_state == UNINITIALIZED || new_state == PREMONOMORPHIC; |
| 437 return (was_uninitialized && !is_uninitialized) ? 1 : | 438 return (was_uninitialized && !is_uninitialized) ? 1 : |
| 438 (!was_uninitialized && is_uninitialized) ? -1 : 0; | 439 (!was_uninitialized && is_uninitialized) ? -1 : 0; |
| 439 } | 440 } |
| 440 | 441 |
| 441 | 442 |
| 442 void IC::PostPatching(Address address, Code* target, Code* old_target) { | 443 void IC::PostPatching(Address address, Code* target, Code* old_target) { |
| 443 if (FLAG_type_info_threshold == 0 && !FLAG_watch_ic_patching) { | |
| 444 return; | |
| 445 } | |
| 446 Isolate* isolate = target->GetHeap()->isolate(); | 444 Isolate* isolate = target->GetHeap()->isolate(); |
| 447 Code* host = isolate-> | 445 Code* host = isolate-> |
| 448 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; | 446 inner_pointer_to_code_cache()->GetCacheEntry(address)->code; |
| 449 if (host->kind() != Code::FUNCTION) return; | 447 if (host->kind() != Code::FUNCTION) return; |
| 450 | 448 |
| 451 if (FLAG_type_info_threshold > 0 && | 449 if (FLAG_type_info_threshold > 0 && |
| 452 old_target->is_inline_cache_stub() && | 450 old_target->is_inline_cache_stub() && |
| 453 target->is_inline_cache_stub()) { | 451 target->is_inline_cache_stub()) { |
| 454 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), | 452 int delta = ComputeTypeInfoCountDelta(old_target->ic_state(), |
| 455 target->ic_state()); | 453 target->ic_state()); |
| 456 // Not all Code objects have TypeFeedbackInfo. | 454 // Not all Code objects have TypeFeedbackInfo. |
| 457 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { | 455 if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) { |
| 458 TypeFeedbackInfo* info = | 456 TypeFeedbackInfo* info = |
| 459 TypeFeedbackInfo::cast(host->type_feedback_info()); | 457 TypeFeedbackInfo::cast(host->type_feedback_info()); |
| 460 info->change_ic_with_type_info_count(delta); | 458 info->change_ic_with_type_info_count(delta); |
| 461 } | 459 } |
| 462 } | 460 } |
| 463 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { | 461 if (host->type_feedback_info()->IsTypeFeedbackInfo()) { |
| 464 TypeFeedbackInfo* info = | 462 TypeFeedbackInfo* info = |
| 465 TypeFeedbackInfo::cast(host->type_feedback_info()); | 463 TypeFeedbackInfo::cast(host->type_feedback_info()); |
| 466 info->change_own_type_change_checksum(); | 464 info->change_own_type_change_checksum(); |
| 467 } | 465 } |
| 468 if (FLAG_watch_ic_patching) { | 466 host->set_profiler_ticks(0); |
| 469 host->set_profiler_ticks(0); | 467 isolate->runtime_profiler()->NotifyICChanged(); |
| 470 isolate->runtime_profiler()->NotifyICChanged(); | |
| 471 } | |
| 472 // TODO(2029): When an optimized function is patched, it would | 468 // TODO(2029): When an optimized function is patched, it would |
| 473 // be nice to propagate the corresponding type information to its | 469 // be nice to propagate the corresponding type information to its |
| 474 // unoptimized version for the benefit of later inlining. | 470 // unoptimized version for the benefit of later inlining. |
| 475 } | 471 } |
| 476 | 472 |
| 477 | 473 |
| 478 void IC::Clear(Isolate* isolate, Address address) { | 474 void IC::Clear(Isolate* isolate, Address address) { |
| 479 Code* target = GetTargetAtAddress(address); | 475 Code* target = GetTargetAtAddress(address); |
| 480 | 476 |
| 481 // Don't clear debug break inline cache as it will remove the break point. | 477 // Don't clear debug break inline cache as it will remove the break point. |
| (...skipping 1569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2051 if (!maybe_result->To(&raw_function)) return maybe_result; | 2047 if (!maybe_result->To(&raw_function)) return maybe_result; |
| 2052 | 2048 |
| 2053 // The first time the inline cache is updated may be the first time the | 2049 // The first time the inline cache is updated may be the first time the |
| 2054 // function it references gets called. If the function is lazily compiled | 2050 // function it references gets called. If the function is lazily compiled |
| 2055 // then the first call will trigger a compilation. We check for this case | 2051 // then the first call will trigger a compilation. We check for this case |
| 2056 // and we do the compilation immediately, instead of waiting for the stub | 2052 // and we do the compilation immediately, instead of waiting for the stub |
| 2057 // currently attached to the JSFunction object to trigger compilation. | 2053 // currently attached to the JSFunction object to trigger compilation. |
| 2058 if (raw_function->is_compiled()) return raw_function; | 2054 if (raw_function->is_compiled()) return raw_function; |
| 2059 | 2055 |
| 2060 Handle<JSFunction> function(raw_function); | 2056 Handle<JSFunction> function(raw_function); |
| 2061 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2057 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); |
| 2062 return *function; | 2058 return *function; |
| 2063 } | 2059 } |
| 2064 | 2060 |
| 2065 | 2061 |
| 2066 // Used from ic-<arch>.cc. | 2062 // Used from ic-<arch>.cc. |
| 2067 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { | 2063 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { |
| 2068 HandleScope scope(isolate); | 2064 HandleScope scope(isolate); |
| 2069 ASSERT(args.length() == 2); | 2065 ASSERT(args.length() == 2); |
| 2070 KeyedCallIC ic(isolate); | 2066 KeyedCallIC ic(isolate); |
| 2071 Handle<Object> receiver = args.at<Object>(0); | 2067 Handle<Object> receiver = args.at<Object>(0); |
| 2072 Handle<Object> key = args.at<Object>(1); | 2068 Handle<Object> key = args.at<Object>(1); |
| 2073 ic.UpdateState(receiver, key); | 2069 ic.UpdateState(receiver, key); |
| 2074 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); | 2070 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); |
| 2075 // Result could be a function or a failure. | 2071 // Result could be a function or a failure. |
| 2076 JSFunction* raw_function = NULL; | 2072 JSFunction* raw_function = NULL; |
| 2077 if (!maybe_result->To(&raw_function)) return maybe_result; | 2073 if (!maybe_result->To(&raw_function)) return maybe_result; |
| 2078 | 2074 |
| 2079 if (raw_function->is_compiled()) return raw_function; | 2075 if (raw_function->is_compiled()) return raw_function; |
| 2080 | 2076 |
| 2081 Handle<JSFunction> function(raw_function, isolate); | 2077 Handle<JSFunction> function(raw_function, isolate); |
| 2082 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2078 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); |
| 2083 return *function; | 2079 return *function; |
| 2084 } | 2080 } |
| 2085 | 2081 |
| 2086 | 2082 |
| 2087 // Used from ic-<arch>.cc. | 2083 // Used from ic-<arch>.cc. |
| 2088 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 2084 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
| 2089 HandleScope scope(isolate); | 2085 HandleScope scope(isolate); |
| 2090 ASSERT(args.length() == 2); | 2086 ASSERT(args.length() == 2); |
| 2091 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 2087 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2092 Handle<Object> receiver = args.at<Object>(0); | 2088 Handle<Object> receiver = args.at<Object>(0); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2152 | 2148 |
| 2153 ic.UpdateState(receiver, key); | 2149 ic.UpdateState(receiver, key); |
| 2154 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); | 2150 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); |
| 2155 // Result could be a function or a failure. | 2151 // Result could be a function or a failure. |
| 2156 JSFunction* raw_function = NULL; | 2152 JSFunction* raw_function = NULL; |
| 2157 if (!maybe_result->To(&raw_function)) return maybe_result; | 2153 if (!maybe_result->To(&raw_function)) return maybe_result; |
| 2158 | 2154 |
| 2159 if (raw_function->is_compiled()) return raw_function; | 2155 if (raw_function->is_compiled()) return raw_function; |
| 2160 | 2156 |
| 2161 Handle<JSFunction> function(raw_function, isolate); | 2157 Handle<JSFunction> function(raw_function, isolate); |
| 2162 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); | 2158 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); |
| 2163 return *function; | 2159 return *function; |
| 2164 } | 2160 } |
| 2165 | 2161 |
| 2166 | 2162 |
| 2167 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { | 2163 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { |
| 2168 SealHandleScope shs(isolate); | 2164 SealHandleScope shs(isolate); |
| 2169 | 2165 |
| 2170 ASSERT(args.length() == 2); | 2166 ASSERT(args.length() == 2); |
| 2171 JSArray* receiver = JSArray::cast(args[0]); | 2167 JSArray* receiver = JSArray::cast(args[0]); |
| 2172 Object* len = args[1]; | 2168 Object* len = args[1]; |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 } | 2590 } |
| 2595 ASSERT_NE(GENERIC, result_kind); | 2591 ASSERT_NE(GENERIC, result_kind); |
| 2596 return KindToType(result_kind, isolate); | 2592 return KindToType(result_kind, isolate); |
| 2597 } | 2593 } |
| 2598 | 2594 |
| 2599 | 2595 |
| 2600 void BinaryOpIC::State::Print(StringStream* stream) const { | 2596 void BinaryOpIC::State::Print(StringStream* stream) const { |
| 2601 stream->Add("(%s", Token::Name(op_)); | 2597 stream->Add("(%s", Token::Name(op_)); |
| 2602 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); | 2598 if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft"); |
| 2603 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); | 2599 else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight"); |
| 2600 if (CouldCreateAllocationMementos()) stream->Add("_CreateAllocationMementos"); |
| 2604 stream->Add(":%s*", KindToString(left_kind_)); | 2601 stream->Add(":%s*", KindToString(left_kind_)); |
| 2605 if (fixed_right_arg_.has_value) { | 2602 if (fixed_right_arg_.has_value) { |
| 2606 stream->Add("%d", fixed_right_arg_.value); | 2603 stream->Add("%d", fixed_right_arg_.value); |
| 2607 } else { | 2604 } else { |
| 2608 stream->Add("%s", KindToString(right_kind_)); | 2605 stream->Add("%s", KindToString(right_kind_)); |
| 2609 } | 2606 } |
| 2610 stream->Add("->%s)", KindToString(result_kind_)); | 2607 stream->Add("->%s)", KindToString(result_kind_)); |
| 2611 } | 2608 } |
| 2612 | 2609 |
| 2613 | 2610 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2633 | 2630 |
| 2634 result_kind_ = UpdateKind(result, result_kind_); | 2631 result_kind_ = UpdateKind(result, result_kind_); |
| 2635 | 2632 |
| 2636 if (!Token::IsTruncatingBinaryOp(op_)) { | 2633 if (!Token::IsTruncatingBinaryOp(op_)) { |
| 2637 Kind input_kind = Max(left_kind_, right_kind_); | 2634 Kind input_kind = Max(left_kind_, right_kind_); |
| 2638 if (result_kind_ < input_kind && input_kind <= NUMBER) { | 2635 if (result_kind_ < input_kind && input_kind <= NUMBER) { |
| 2639 result_kind_ = input_kind; | 2636 result_kind_ = input_kind; |
| 2640 } | 2637 } |
| 2641 } | 2638 } |
| 2642 | 2639 |
| 2640 // We don't want to distinguish INT32 and NUMBER for string add (because |
| 2641 // NumberToString can't make use of this anyway). |
| 2642 if (left_kind_ == STRING && right_kind_ == INT32) { |
| 2643 ASSERT_EQ(STRING, result_kind_); |
| 2644 ASSERT_EQ(Token::ADD, op_); |
| 2645 right_kind_ = NUMBER; |
| 2646 } else if (right_kind_ == STRING && left_kind_ == INT32) { |
| 2647 ASSERT_EQ(STRING, result_kind_); |
| 2648 ASSERT_EQ(Token::ADD, op_); |
| 2649 left_kind_ = NUMBER; |
| 2650 } |
| 2651 |
| 2643 // Reset overwrite mode unless we can actually make use of it, or may be able | 2652 // Reset overwrite mode unless we can actually make use of it, or may be able |
| 2644 // to make use of it at some point in the future. | 2653 // to make use of it at some point in the future. |
| 2645 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) || | 2654 if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) || |
| 2646 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) || | 2655 (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) || |
| 2647 result_kind_ > NUMBER) { | 2656 result_kind_ > NUMBER) { |
| 2648 mode_ = NO_OVERWRITE; | 2657 mode_ = NO_OVERWRITE; |
| 2649 } | 2658 } |
| 2650 | 2659 |
| 2651 if (old_extra_ic_state == GetExtraICState()) { | 2660 if (old_extra_ic_state == GetExtraICState()) { |
| 2652 // Tagged operations can lead to non-truncating HChanges | 2661 // Tagged operations can lead to non-truncating HChanges |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2672 if (object->IsBoolean() && is_truncating) { | 2681 if (object->IsBoolean() && is_truncating) { |
| 2673 // Booleans will be automatically truncated by HChange. | 2682 // Booleans will be automatically truncated by HChange. |
| 2674 new_kind = INT32; | 2683 new_kind = INT32; |
| 2675 } else if (object->IsUndefined()) { | 2684 } else if (object->IsUndefined()) { |
| 2676 // Undefined will be automatically truncated by HChange. | 2685 // Undefined will be automatically truncated by HChange. |
| 2677 new_kind = is_truncating ? INT32 : NUMBER; | 2686 new_kind = is_truncating ? INT32 : NUMBER; |
| 2678 } else if (object->IsSmi()) { | 2687 } else if (object->IsSmi()) { |
| 2679 new_kind = SMI; | 2688 new_kind = SMI; |
| 2680 } else if (object->IsHeapNumber()) { | 2689 } else if (object->IsHeapNumber()) { |
| 2681 double value = Handle<HeapNumber>::cast(object)->value(); | 2690 double value = Handle<HeapNumber>::cast(object)->value(); |
| 2682 new_kind = TypeInfo::IsInt32Double(value) ? INT32 : NUMBER; | 2691 new_kind = IsInt32Double(value) ? INT32 : NUMBER; |
| 2683 } else if (object->IsString() && op() == Token::ADD) { | 2692 } else if (object->IsString() && op() == Token::ADD) { |
| 2684 new_kind = STRING; | 2693 new_kind = STRING; |
| 2685 } | 2694 } |
| 2686 if (new_kind == INT32 && SmiValuesAre32Bits()) { | 2695 if (new_kind == INT32 && SmiValuesAre32Bits()) { |
| 2687 new_kind = NUMBER; | 2696 new_kind = NUMBER; |
| 2688 } | 2697 } |
| 2689 if (kind != NONE && | 2698 if (kind != NONE && |
| 2690 ((new_kind <= NUMBER && kind > NUMBER) || | 2699 ((new_kind <= NUMBER && kind > NUMBER) || |
| 2691 (new_kind > NUMBER && kind <= NUMBER))) { | 2700 (new_kind > NUMBER && kind <= NUMBER))) { |
| 2692 new_kind = GENERIC; | 2701 new_kind = GENERIC; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2718 case SMI: type = Type::Smi(); break; | 2727 case SMI: type = Type::Smi(); break; |
| 2719 case INT32: type = Type::Signed32(); break; | 2728 case INT32: type = Type::Signed32(); break; |
| 2720 case NUMBER: type = Type::Number(); break; | 2729 case NUMBER: type = Type::Number(); break; |
| 2721 case STRING: type = Type::String(); break; | 2730 case STRING: type = Type::String(); break; |
| 2722 case GENERIC: type = Type::Any(); break; | 2731 case GENERIC: type = Type::Any(); break; |
| 2723 } | 2732 } |
| 2724 return handle(type, isolate); | 2733 return handle(type, isolate); |
| 2725 } | 2734 } |
| 2726 | 2735 |
| 2727 | 2736 |
| 2728 MaybeObject* BinaryOpIC::Transition(Handle<Object> left, Handle<Object> right) { | 2737 MaybeObject* BinaryOpIC::Transition(Handle<AllocationSite> allocation_site, |
| 2738 Handle<Object> left, |
| 2739 Handle<Object> right) { |
| 2729 State state(target()->extended_extra_ic_state()); | 2740 State state(target()->extended_extra_ic_state()); |
| 2730 | 2741 |
| 2731 // Compute the actual result using the builtin for the binary operation. | 2742 // Compute the actual result using the builtin for the binary operation. |
| 2732 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( | 2743 Object* builtin = isolate()->js_builtins_object()->javascript_builtin( |
| 2733 TokenToJSBuiltin(state.op())); | 2744 TokenToJSBuiltin(state.op())); |
| 2734 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); | 2745 Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate()); |
| 2735 bool caught_exception; | 2746 bool caught_exception; |
| 2736 Handle<Object> result = Execution::Call( | 2747 Handle<Object> result = Execution::Call( |
| 2737 isolate(), function, left, 1, &right, &caught_exception); | 2748 isolate(), function, left, 1, &right, &caught_exception); |
| 2738 if (caught_exception) return Failure::Exception(); | 2749 if (caught_exception) return Failure::Exception(); |
| 2739 | 2750 |
| 2740 // Compute the new state. | 2751 // Compute the new state. |
| 2741 State old_state = state; | 2752 State old_state = state; |
| 2742 state.Update(left, right, result); | 2753 state.Update(left, right, result); |
| 2743 | 2754 |
| 2744 // Install the new stub. | 2755 // Check if we have a string operation here. |
| 2745 BinaryOpICStub stub(state); | 2756 Handle<Code> target; |
| 2746 set_target(*stub.GetCode(isolate())); | 2757 if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) { |
| 2758 // Setup the allocation site on-demand. |
| 2759 if (allocation_site.is_null()) { |
| 2760 allocation_site = isolate()->factory()->NewAllocationSite(); |
| 2761 } |
| 2762 |
| 2763 // Install the stub with an allocation site. |
| 2764 BinaryOpICWithAllocationSiteStub stub(state); |
| 2765 target = stub.GetCodeCopyFromTemplate(isolate(), allocation_site); |
| 2766 |
| 2767 // Sanity check the trampoline stub. |
| 2768 ASSERT_EQ(*allocation_site, target->FindFirstAllocationSite()); |
| 2769 } else { |
| 2770 // Install the generic stub. |
| 2771 BinaryOpICStub stub(state); |
| 2772 target = stub.GetCode(isolate()); |
| 2773 |
| 2774 // Sanity check the generic stub. |
| 2775 ASSERT_EQ(NULL, target->FindFirstAllocationSite()); |
| 2776 } |
| 2777 set_target(*target); |
| 2747 | 2778 |
| 2748 if (FLAG_trace_ic) { | 2779 if (FLAG_trace_ic) { |
| 2749 char buffer[150]; | 2780 char buffer[150]; |
| 2750 NoAllocationStringAllocator allocator( | 2781 NoAllocationStringAllocator allocator( |
| 2751 buffer, static_cast<unsigned>(sizeof(buffer))); | 2782 buffer, static_cast<unsigned>(sizeof(buffer))); |
| 2752 StringStream stream(&allocator); | 2783 StringStream stream(&allocator); |
| 2753 stream.Add("[BinaryOpIC"); | 2784 stream.Add("[BinaryOpIC"); |
| 2754 old_state.Print(&stream); | 2785 old_state.Print(&stream); |
| 2755 stream.Add(" => "); | 2786 stream.Add(" => "); |
| 2756 state.Print(&stream); | 2787 state.Print(&stream); |
| 2757 stream.Add(" @ %p <- ", static_cast<void*>(*target())); | 2788 stream.Add(" @ %p <- ", static_cast<void*>(*target)); |
| 2758 stream.OutputToStdOut(); | 2789 stream.OutputToStdOut(); |
| 2759 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 2790 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); |
| 2791 if (!allocation_site.is_null()) { |
| 2792 PrintF(" using allocation site %p", static_cast<void*>(*allocation_site)); |
| 2793 } |
| 2760 PrintF("]\n"); | 2794 PrintF("]\n"); |
| 2761 } | 2795 } |
| 2762 | 2796 |
| 2763 // Patch the inlined smi code as necessary. | 2797 // Patch the inlined smi code as necessary. |
| 2764 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) { | 2798 if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) { |
| 2765 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); | 2799 PatchInlinedSmiCode(address(), ENABLE_INLINED_SMI_CHECK); |
| 2766 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) { | 2800 } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) { |
| 2767 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); | 2801 PatchInlinedSmiCode(address(), DISABLE_INLINED_SMI_CHECK); |
| 2768 } | 2802 } |
| 2769 | 2803 |
| 2770 return *result; | 2804 return *result; |
| 2771 } | 2805 } |
| 2772 | 2806 |
| 2773 | 2807 |
| 2774 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { | 2808 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) { |
| 2775 HandleScope scope(isolate); | 2809 HandleScope scope(isolate); |
| 2810 ASSERT_EQ(2, args.length()); |
| 2776 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); | 2811 Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft); |
| 2777 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); | 2812 Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight); |
| 2778 BinaryOpIC ic(isolate); | 2813 BinaryOpIC ic(isolate); |
| 2779 return ic.Transition(left, right); | 2814 return ic.Transition(Handle<AllocationSite>::null(), left, right); |
| 2780 } | 2815 } |
| 2781 | 2816 |
| 2782 | 2817 |
| 2818 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite) { |
| 2819 HandleScope scope(isolate); |
| 2820 ASSERT_EQ(3, args.length()); |
| 2821 Handle<AllocationSite> allocation_site = args.at<AllocationSite>( |
| 2822 BinaryOpWithAllocationSiteStub::kAllocationSite); |
| 2823 Handle<Object> left = args.at<Object>( |
| 2824 BinaryOpWithAllocationSiteStub::kLeft); |
| 2825 Handle<Object> right = args.at<Object>( |
| 2826 BinaryOpWithAllocationSiteStub::kRight); |
| 2827 BinaryOpIC ic(isolate); |
| 2828 return ic.Transition(allocation_site, left, right); |
| 2829 } |
| 2830 |
| 2831 |
| 2783 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { | 2832 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) { |
| 2784 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2833 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
| 2785 Code* code = NULL; | 2834 Code* code = NULL; |
| 2786 CHECK(stub.FindCodeInCache(&code, isolate)); | 2835 CHECK(stub.FindCodeInCache(&code, isolate)); |
| 2787 return code; | 2836 return code; |
| 2788 } | 2837 } |
| 2789 | 2838 |
| 2790 | 2839 |
| 2791 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { | 2840 Handle<Code> CompareIC::GetUninitialized(Isolate* isolate, Token::Value op) { |
| 2792 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); | 2841 ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED); |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3143 #undef ADDR | 3192 #undef ADDR |
| 3144 }; | 3193 }; |
| 3145 | 3194 |
| 3146 | 3195 |
| 3147 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3196 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3148 return IC_utilities[id]; | 3197 return IC_utilities[id]; |
| 3149 } | 3198 } |
| 3150 | 3199 |
| 3151 | 3200 |
| 3152 } } // namespace v8::internal | 3201 } } // namespace v8::internal |
| OLD | NEW |