OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
11 #include "src/conversions.h" | 11 #include "src/conversions.h" |
12 #include "src/execution.h" | 12 #include "src/execution.h" |
13 #include "src/ic-inl.h" | 13 #include "src/ic-inl.h" |
14 #include "src/runtime.h" | 14 #include "src/runtime.h" |
15 #include "src/stub-cache.h" | 15 #include "src/stub-cache.h" |
16 | 16 |
17 namespace v8 { | 17 namespace v8 { |
18 namespace internal { | 18 namespace internal { |
19 | 19 |
20 #ifdef DEBUG | |
21 char IC::TransitionMarkFromState(IC::State state) { | 20 char IC::TransitionMarkFromState(IC::State state) { |
22 switch (state) { | 21 switch (state) { |
23 case UNINITIALIZED: return '0'; | 22 case UNINITIALIZED: return '0'; |
24 case PREMONOMORPHIC: return '.'; | 23 case PREMONOMORPHIC: return '.'; |
25 case MONOMORPHIC: return '1'; | 24 case MONOMORPHIC: return '1'; |
26 case MONOMORPHIC_PROTOTYPE_FAILURE: return '^'; | 25 case MONOMORPHIC_PROTOTYPE_FAILURE: return '^'; |
27 case POLYMORPHIC: return 'P'; | 26 case POLYMORPHIC: return 'P'; |
28 case MEGAMORPHIC: return 'N'; | 27 case MEGAMORPHIC: return 'N'; |
29 case GENERIC: return 'G'; | 28 case GENERIC: return 'G'; |
30 | 29 |
(...skipping 10 matching lines...) Expand all Loading... | |
41 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { | 40 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) { |
42 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW"; | 41 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW"; |
43 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 42 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
44 return ".IGNORE_OOB"; | 43 return ".IGNORE_OOB"; |
45 } | 44 } |
46 if (IsGrowStoreMode(mode)) return ".GROW"; | 45 if (IsGrowStoreMode(mode)) return ".GROW"; |
47 return ""; | 46 return ""; |
48 } | 47 } |
49 | 48 |
50 | 49 |
51 void IC::TraceIC(const char* type, | 50 #ifdef DEBUG |
52 Handle<Object> name) { | 51 |
52 #define TRACE_GENERIC_IC(isolate, type, reason) \ | |
53 do { \ | |
54 if (FLAG_trace_ic) { \ | |
55 PrintF("[%s patching generic stub in ", type); \ | |
56 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ | |
57 PrintF(" (%s)]\n", reason); \ | |
58 } \ | |
59 } while (false) | |
60 | |
61 #else | |
62 | |
63 #define TRACE_GENERIC_IC(isolate, type, reason) | |
64 | |
65 #endif // DEBUG | |
66 | |
67 void IC::TraceIC(const char* type, Handle<Object> name) { | |
53 if (FLAG_trace_ic) { | 68 if (FLAG_trace_ic) { |
54 Code* new_target = raw_target(); | 69 Code* new_target = raw_target(); |
55 State new_state = new_target->ic_state(); | 70 State new_state = new_target->ic_state(); |
56 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type); | 71 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type); |
57 StackFrameIterator it(isolate()); | 72 |
58 while (it.frame()->fp() != this->fp()) it.Advance(); | 73 // TODO(jkummerow): Add support for "apply". The logic is roughly: |
Sven Panne
2014/07/08 06:37:11
Hmmm, can we extract the body of the while loop in
Jakob Kummerow
2014/07/08 07:47:40
Done.
| |
59 StackFrame* raw_frame = it.frame(); | 74 // marker = [fp_ + kMarkerOffset]; |
60 if (raw_frame->is_internal()) { | 75 // if marker is smi and marker.value == INTERNAL and |
61 Code* apply_builtin = isolate()->builtins()->builtin( | 76 // the frame's code == builtin(Builtins::kFunctionApply): |
62 Builtins::kFunctionApply); | 77 // then print "apply from" and advance one frame |
63 if (raw_frame->unchecked_code() == apply_builtin) { | 78 |
64 PrintF("apply from "); | 79 Object* maybe_function = |
65 it.Advance(); | 80 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset); |
66 raw_frame = it.frame(); | 81 if (maybe_function->IsJSFunction()) { |
82 JSFunction* function = JSFunction::cast(maybe_function); | |
83 PrintF("%s", function->IsOptimized() ? "*" : "~"); | |
84 function->PrintName(); | |
85 Code* js_code = function->code(); | |
86 int code_offset = static_cast<int>(pc() - js_code->instruction_start()); | |
87 PrintF("+%d", code_offset); | |
88 | |
89 int source_pos = js_code->SourcePosition(pc()); | |
90 SharedFunctionInfo* shared = function->shared(); | |
91 Object* maybe_script = shared->script(); | |
92 if (maybe_script->IsScript()) { | |
93 Script* script = Script::cast(maybe_script); | |
94 int line = script->GetLineNumber(source_pos) + 1; | |
95 Object* script_name_raw = script->name(); | |
96 if (script_name_raw->IsString()) { | |
97 String* script_name = String::cast(script->name()); | |
98 SmartArrayPointer<char> c_script_name = | |
99 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); | |
100 PrintF(stdout, " at %s:%d", c_script_name.get(), line); | |
101 } else { | |
102 PrintF(stdout, " at <unknown>:%d", line); | |
103 } | |
104 } else { | |
105 PrintF(stdout, " at <unknown>:<unknown>"); | |
67 } | 106 } |
68 } | 107 } |
69 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 108 |
70 ExtraICState extra_state = new_target->extra_ic_state(); | 109 ExtraICState extra_state = new_target->extra_ic_state(); |
71 const char* modifier = ""; | 110 const char* modifier = ""; |
72 if (new_target->kind() == Code::KEYED_STORE_IC) { | 111 if (new_target->kind() == Code::KEYED_STORE_IC) { |
73 modifier = GetTransitionMarkModifier( | 112 modifier = GetTransitionMarkModifier( |
74 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | 113 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); |
75 } | 114 } |
76 PrintF(" (%c->%c%s)", | 115 PrintF(" (%c->%c%s)", |
77 TransitionMarkFromState(state()), | 116 TransitionMarkFromState(state()), |
78 TransitionMarkFromState(new_state), | 117 TransitionMarkFromState(new_state), |
79 modifier); | 118 modifier); |
80 name->Print(); | 119 name->Print(); |
81 PrintF("]\n"); | 120 PrintF("]\n"); |
82 } | 121 } |
83 } | 122 } |
84 | 123 |
85 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 124 #define TRACE_IC(type, name) TraceIC(type, name) |
86 do { \ | |
87 if (FLAG_trace_ic) { \ | |
88 PrintF("[%s patching generic stub in ", type); \ | |
89 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ | |
90 PrintF(" (%s)]\n", reason); \ | |
91 } \ | |
92 } while (false) | |
93 | 125 |
94 #else | |
95 #define TRACE_GENERIC_IC(isolate, type, reason) | |
96 #endif // DEBUG | |
97 | |
98 #define TRACE_IC(type, name) \ | |
99 ASSERT((TraceIC(type, name), true)) | |
100 | 126 |
101 IC::IC(FrameDepth depth, Isolate* isolate) | 127 IC::IC(FrameDepth depth, Isolate* isolate) |
102 : isolate_(isolate), | 128 : isolate_(isolate), |
103 target_set_(false), | 129 target_set_(false), |
104 target_maps_set_(false) { | 130 target_maps_set_(false) { |
105 // To improve the performance of the (much used) IC code, we unfold a few | 131 // To improve the performance of the (much used) IC code, we unfold a few |
106 // levels of the stack frame iteration code. This yields a ~35% speedup when | 132 // levels of the stack frame iteration code. This yields a ~35% speedup when |
107 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. | 133 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
108 const Address entry = | 134 const Address entry = |
109 Isolate::c_entry_fp(isolate->thread_local_top()); | 135 Isolate::c_entry_fp(isolate->thread_local_top()); |
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
608 } | 634 } |
609 return Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 635 return Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
610 } | 636 } |
611 } | 637 } |
612 | 638 |
613 // Check if the name is trivially convertible to an index and get | 639 // Check if the name is trivially convertible to an index and get |
614 // the element or char if so. | 640 // the element or char if so. |
615 uint32_t index; | 641 uint32_t index; |
616 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 642 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
617 // Rewrite to the generic keyed load stub. | 643 // Rewrite to the generic keyed load stub. |
618 if (FLAG_use_ic) set_target(*generic_stub()); | 644 if (FLAG_use_ic) { |
645 set_target(*generic_stub()); | |
646 TRACE_IC("LoadIC", name); | |
647 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | |
648 } | |
619 Handle<Object> result; | 649 Handle<Object> result; |
620 ASSIGN_RETURN_ON_EXCEPTION( | 650 ASSIGN_RETURN_ON_EXCEPTION( |
621 isolate(), | 651 isolate(), |
622 result, | 652 result, |
623 Runtime::GetElementOrCharAt(isolate(), object, index), | 653 Runtime::GetElementOrCharAt(isolate(), object, index), |
624 Object); | 654 Object); |
625 return result; | 655 return result; |
626 } | 656 } |
627 | 657 |
628 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | 658 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
(...skipping 2444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3073 #undef ADDR | 3103 #undef ADDR |
3074 }; | 3104 }; |
3075 | 3105 |
3076 | 3106 |
3077 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3107 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3078 return IC_utilities[id]; | 3108 return IC_utilities[id]; |
3079 } | 3109 } |
3080 | 3110 |
3081 | 3111 |
3082 } } // namespace v8::internal | 3112 } } // namespace v8::internal |
OLD | NEW |