virtual Major MajorKey() const = 0;
virtual int MinorKey() const = 0;
- virtual InlineCacheState GetICState() {
- return UNINITIALIZED;
- }
+ virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
virtual Code::StubType GetStubType() {
return Code::NORMAL;
return Code::CALL_IC;
}
- virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE {
- return state_.GetICState();
- }
+ virtual InlineCacheState GetICState() const V8_OVERRIDE { return DEFAULT; }
virtual ExtraICState GetExtraICState() const V8_FINAL V8_OVERRIDE {
return state_.GetExtraICState();
virtual void Generate(MacroAssembler* masm);
+ virtual InlineCacheState GetICState() const V8_FINAL V8_OVERRIDE {
+ return MONOMORPHIC;
+ }
+
protected:
virtual void PrintState(OStream& os) const V8_OVERRIDE; // NOLINT
public:
virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
virtual ExtraICState GetExtraICState() const { return kind(); }
- virtual InlineCacheState GetICState() { return MONOMORPHIC; }
+ virtual InlineCacheState GetICState() const { return MONOMORPHIC; }
virtual void InitializeInterfaceDescriptor(
CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
return Code::BINARY_OP_IC;
}
- virtual InlineCacheState GetICState() V8_FINAL V8_OVERRIDE {
+ virtual InlineCacheState GetICState() const V8_FINAL V8_OVERRIDE {
return state_.GetICState();
}
return Code::BINARY_OP_IC;
}
- virtual InlineCacheState GetICState() V8_OVERRIDE {
+ virtual InlineCacheState GetICState() const V8_OVERRIDE {
return state_.GetICState();
}
CompareIC::State* right_state,
CompareIC::State* handler_state, Token::Value* op);
- virtual InlineCacheState GetICState();
+ virtual InlineCacheState GetICState() const;
private:
class OpField: public BitField<int, 0, 3> { };
isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
}
- virtual InlineCacheState GetICState() {
+ virtual InlineCacheState GetICState() const {
if (state_.Contains(GENERIC)) {
return MEGAMORPHIC;
} else if (state_.Contains(MONOMORPHIC_MAP)) {
static void InstallDescriptors(Isolate* isolate);
virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
- virtual InlineCacheState GetICState() { return GENERIC; }
+ virtual InlineCacheState GetICState() const { return GENERIC; }
private:
Major MajorKey() const { return KeyedLoadGeneric; }
virtual ExtraICState GetExtraICState() const { return types_.ToIntegral(); }
- virtual InlineCacheState GetICState() {
+ virtual InlineCacheState GetICState() const {
if (types_.IsEmpty()) {
return ::v8::internal::UNINITIALIZED;
} else {
// computed from the original code - not the patched code. Let
// these cases fall through to the unreachable code below.
case DEBUG_STUB: break;
+ // Type-vector-based ICs resolve state to one of the above.
+ case DEFAULT:
+ break;
}
UNREACHABLE();
return 0;
#endif // DEBUG
+
void IC::TraceIC(const char* type, Handle<Object> name) {
if (FLAG_trace_ic) {
Code* new_target = raw_target();
State new_state = new_target->ic_state();
+ TraceIC(type, name, state(), new_state);
+ }
+}
+
+
+void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
+ State new_state) {
+ if (FLAG_trace_ic) {
+ Code* new_target = raw_target();
PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
// TODO(jkummerow): Add support for "apply". The logic is roughly:
modifier = GetTransitionMarkModifier(
KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
}
- PrintF(" (%c->%c%s)",
- TransitionMarkFromState(state()),
- TransitionMarkFromState(new_state),
- modifier);
+ PrintF(" (%c->%c%s)", TransitionMarkFromState(old_state),
+ TransitionMarkFromState(new_state), modifier);
#ifdef OBJECT_PRINT
OFStream os(stdout);
name->Print(os);
}
#define TRACE_IC(type, name) TraceIC(type, name)
-
+#define TRACE_VECTOR_IC(type, name, old_state, new_state) \
+ TraceIC(type, name, old_state, new_state)
IC::IC(FrameDepth depth, Isolate* isolate)
: isolate_(isolate),
break;
case PROTOTYPE_FAILURE:
case DEBUG_STUB:
+ case DEFAULT:
UNREACHABLE();
}
}
break;
case DEBUG_STUB:
break;
+ case DEFAULT:
case GENERIC:
UNREACHABLE();
break;
isolate()->native_context()->array_function());
if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
// Alter the slot.
+ IC::State old_state = FeedbackToState(vector, slot);
Object* feedback = vector->get(slot->value());
if (!feedback->IsAllocationSite()) {
Handle<AllocationSite> new_site =
isolate());
}
- TRACE_IC("CallIC (Array call)", name);
- Object* new_feedback = vector->get(slot->value());
- UpdateTypeFeedbackInfo(feedback, new_feedback);
+ IC::State new_state = FeedbackToState(vector, slot);
+ OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
+ TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state);
return true;
}
return false;
}
-void CallIC::PatchMegamorphic(Handle<FixedArray> vector,
- Handle<Smi> slot) {
+void CallIC::PatchMegamorphic(Handle<Object> function,
+ Handle<FixedArray> vector, Handle<Smi> slot) {
State state(target()->extra_ic_state());
+ IC::State old_state = FeedbackToState(vector, slot);
// We are going generic.
vector->set(slot->value(),
Handle<Code> code = stub.GetCode();
set_target(*code);
- TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
-}
-
+ Handle<Object> name = isolate()->factory()->empty_string();
+ if (function->IsJSFunction()) {
+ Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
+ name = handle(js_function->shared()->name(), isolate());
+ }
-void CallIC::UpdateTypeFeedbackInfo(Object* old_feedback,
- Object* new_feedback) {
- IC::State old_state = FeedbackObjectToState(old_feedback);
- IC::State new_state = FeedbackObjectToState(new_feedback);
+ IC::State new_state = FeedbackToState(vector, slot);
OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
+ TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
}
Handle<FixedArray> vector,
Handle<Smi> slot) {
State state(target()->extra_ic_state());
+ IC::State old_state = FeedbackToState(vector, slot);
+ Handle<Object> name = isolate()->factory()->empty_string();
Object* feedback = vector->get(slot->value());
// Hand-coded MISS handling is easier if CallIC slots don't contain smis.
vector->set(slot->value(),
*TypeFeedbackInfo::MegamorphicSentinel(isolate()),
SKIP_WRITE_BARRIER);
-
- TRACE_GENERIC_IC(isolate(), "CallIC", "megamorphic");
} else {
// The feedback is either uninitialized or an allocation site.
// It might be an allocation site because if we re-compile the full code
return;
}
- Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
- Handle<Object> name(js_function->shared()->name(), isolate());
- TRACE_IC("CallIC", name);
vector->set(slot->value(), *function);
}
- Object* new_feedback = vector->get(slot->value());
- UpdateTypeFeedbackInfo(feedback, new_feedback);
+ if (function->IsJSFunction()) {
+ Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
+ name = handle(js_function->shared()->name(), isolate());
+ }
+
+ IC::State new_state = FeedbackToState(vector, slot);
+ OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
+ TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
}
Handle<Object> function = args.at<Object>(1);
Handle<FixedArray> vector = args.at<FixedArray>(2);
Handle<Smi> slot = args.at<Smi>(3);
- ic.PatchMegamorphic(vector, slot);
+ ic.PatchMegamorphic(function, vector, slot);
return *function;
}
char TransitionMarkFromState(IC::State state);
void TraceIC(const char* type, Handle<Object> name);
+ void TraceIC(const char* type, Handle<Object> name, State old_state,
+ State new_state);
MaybeHandle<Object> TypeError(const char* type,
Handle<Object> object,
: argc_(argc), call_type_(call_type) {
}
- InlineCacheState GetICState() const { return ::v8::internal::GENERIC; }
-
ExtraICState GetExtraICState() const;
static void GenerateAheadOfTime(
: IC(EXTRA_CALL_FRAME, isolate) {
}
- void PatchMegamorphic(Handle<FixedArray> vector, Handle<Smi> slot);
+ void PatchMegamorphic(Handle<Object> function, Handle<FixedArray> vector,
+ Handle<Smi> slot);
void HandleMiss(Handle<Object> receiver,
Handle<Object> function,
ConstantPoolArray* constant_pool);
private:
- void UpdateTypeFeedbackInfo(Object* old_feedback, Object* new_feedback);
- inline IC::State FeedbackObjectToState(Object* feedback) const;
+ inline IC::State FeedbackToState(Handle<FixedArray> vector,
+ Handle<Smi> slot) const;
};
static const int kProfilerTicksOffset = kFullCodeFlags + 1;
// Flags layout. BitField<type, shift, size>.
- class ICStateField: public BitField<InlineCacheState, 0, 3> {};
- class TypeField: public BitField<StubType, 3, 1> {};
- class CacheHolderField : public BitField<CacheHolderFlag, 4, 2> {};
- class KindField: public BitField<Kind, 6, 4> {};
- // TODO(bmeurer): Bit 10 is available for free use. :-)
+ class ICStateField : public BitField<InlineCacheState, 0, 4> {};
+ class TypeField : public BitField<StubType, 4, 1> {};
+ class CacheHolderField : public BitField<CacheHolderFlag, 5, 2> {};
+ class KindField : public BitField<Kind, 7, 4> {};
class ExtraICStateField: public BitField<ExtraICState, 11,
PlatformSmiTagging::kSmiValueSize - 11 + 1> {}; // NOLINT