| 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: |
| 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()) { |
| 67 } | 82 JSFunction* function = JSFunction::cast(maybe_function); |
| 83 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(), |
| 84 stdout, true); |
| 68 } | 85 } |
| 69 JavaScriptFrame::PrintTop(isolate(), stdout, false, true); | 86 |
| 70 ExtraICState extra_state = new_target->extra_ic_state(); | 87 ExtraICState extra_state = new_target->extra_ic_state(); |
| 71 const char* modifier = ""; | 88 const char* modifier = ""; |
| 72 if (new_target->kind() == Code::KEYED_STORE_IC) { | 89 if (new_target->kind() == Code::KEYED_STORE_IC) { |
| 73 modifier = GetTransitionMarkModifier( | 90 modifier = GetTransitionMarkModifier( |
| 74 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); | 91 KeyedStoreIC::GetKeyedAccessStoreMode(extra_state)); |
| 75 } | 92 } |
| 76 PrintF(" (%c->%c%s)", | 93 PrintF(" (%c->%c%s)", |
| 77 TransitionMarkFromState(state()), | 94 TransitionMarkFromState(state()), |
| 78 TransitionMarkFromState(new_state), | 95 TransitionMarkFromState(new_state), |
| 79 modifier); | 96 modifier); |
| 80 name->Print(); | 97 name->Print(); |
| 81 PrintF("]\n"); | 98 PrintF("]\n"); |
| 82 } | 99 } |
| 83 } | 100 } |
| 84 | 101 |
| 85 #define TRACE_GENERIC_IC(isolate, type, reason) \ | 102 #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 | 103 |
| 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 | 104 |
| 101 IC::IC(FrameDepth depth, Isolate* isolate) | 105 IC::IC(FrameDepth depth, Isolate* isolate) |
| 102 : isolate_(isolate), | 106 : isolate_(isolate), |
| 103 target_set_(false), | 107 target_set_(false), |
| 104 target_maps_set_(false) { | 108 target_maps_set_(false) { |
| 105 // To improve the performance of the (much used) IC code, we unfold a few | 109 // 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 | 110 // 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. | 111 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. |
| 108 const Address entry = | 112 const Address entry = |
| 109 Isolate::c_entry_fp(isolate->thread_local_top()); | 113 Isolate::c_entry_fp(isolate->thread_local_top()); |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 } | 612 } |
| 609 return Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 613 return Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
| 610 } | 614 } |
| 611 } | 615 } |
| 612 | 616 |
| 613 // Check if the name is trivially convertible to an index and get | 617 // Check if the name is trivially convertible to an index and get |
| 614 // the element or char if so. | 618 // the element or char if so. |
| 615 uint32_t index; | 619 uint32_t index; |
| 616 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 620 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 617 // Rewrite to the generic keyed load stub. | 621 // Rewrite to the generic keyed load stub. |
| 618 if (FLAG_use_ic) set_target(*generic_stub()); | 622 if (FLAG_use_ic) { |
| 623 set_target(*generic_stub()); |
| 624 TRACE_IC("LoadIC", name); |
| 625 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
| 626 } |
| 619 Handle<Object> result; | 627 Handle<Object> result; |
| 620 ASSIGN_RETURN_ON_EXCEPTION( | 628 ASSIGN_RETURN_ON_EXCEPTION( |
| 621 isolate(), | 629 isolate(), |
| 622 result, | 630 result, |
| 623 Runtime::GetElementOrCharAt(isolate(), object, index), | 631 Runtime::GetElementOrCharAt(isolate(), object, index), |
| 624 Object); | 632 Object); |
| 625 return result; | 633 return result; |
| 626 } | 634 } |
| 627 | 635 |
| 628 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | 636 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 | 3081 #undef ADDR |
| 3074 }; | 3082 }; |
| 3075 | 3083 |
| 3076 | 3084 |
| 3077 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3085 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3078 return IC_utilities[id]; | 3086 return IC_utilities[id]; |
| 3079 } | 3087 } |
| 3080 | 3088 |
| 3081 | 3089 |
| 3082 } } // namespace v8::internal | 3090 } } // namespace v8::internal |
| OLD | NEW |