📄 ic.cc.svn-base
字号:
case INTERCEPTOR: { code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, lookup->holder()); break; } default: { // Always rewrite to the generic case so that we do not // repeatedly try to rewrite. code = generic_stub(); break; } } } // If we're unable to compute the stub (not enough memory left), we // simply avoid updating the caches. if (code->IsFailure()) return; // Patch the call site depending on the state of the cache. Make // sure to always rewrite from monomorphic to megamorphic. ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); if (state == UNINITIALIZED || state == PREMONOMORPHIC) { set_target(Code::cast(code)); } else if (state == MONOMORPHIC) { set_target(megamorphic_stub()); }#ifdef DEBUG TraceIC("KeyedLoadIC", name, state, target());#endif}Object* StoreIC::Store(State state, Handle<Object> object, Handle<String> name, Handle<Object> value) { // If the object is undefined or null it's illegal to try to set any // properties on it; throw a TypeError in that case. if (object->IsUndefined() || object->IsNull()) { return TypeError("non_object_property_store", object, name); } // Ignore stores where the receiver is not a JSObject. if (!object->IsJSObject()) return *value; Handle<JSObject> receiver = Handle<JSObject>::cast(object); // Check if the given name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { HandleScope scope; Handle<Object> result = SetElement(receiver, index, value); if (result.is_null()) return Failure::Exception(); return *value; } // Lookup the property locally in the receiver. LookupResult lookup; receiver->LocalLookup(*name, &lookup); // Update inline cache and stub cache. if (FLAG_use_ic && lookup.IsLoaded()) { UpdateCaches(&lookup, state, receiver, name, value); } // Set the property. return receiver->SetProperty(*name, *value, NONE);}void StoreIC::UpdateCaches(LookupResult* lookup, State state, Handle<JSObject> receiver, Handle<String> name, Handle<Object> value) { ASSERT(lookup->IsLoaded()); // Bail out if we didn't find a result. if (!lookup->IsValid() || !lookup->IsCacheable()) return; // If the property is read-only, we leave the IC in its current // state. if (lookup->IsReadOnly()) return; // If the property has a non-field type allowing map transitions // where there is extra room in the object, we leave the IC in its // current state. PropertyType type = lookup->type(); // Compute the code stub for this store; used for rewriting to // monomorphic state and making sure that the code stub is in the // stub cache. Object* code = NULL; switch (type) { case FIELD: { code = StubCache::ComputeStoreField(*name, *receiver, lookup->GetFieldIndex()); break; } case MAP_TRANSITION: { if (lookup->GetAttributes() != NONE) return; if (receiver->map()->unused_property_fields() == 0) return; HandleScope scope; ASSERT(type == MAP_TRANSITION && (receiver->map()->unused_property_fields() > 0)); Handle<Map> transition(lookup->GetTransitionMap()); int index = transition->PropertyIndexFor(*name); code = StubCache::ComputeStoreField(*name, *receiver, index, *transition); break; } case CALLBACKS: { if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); if (v8::ToCData<Address>(callback->setter()) == 0) return; code = StubCache::ComputeStoreCallback(*name, *receiver, callback); break; } case INTERCEPTOR: { code = StubCache::ComputeStoreInterceptor(*name, *receiver); break; } default: return; } // If we're unable to compute the stub (not enough memory left), we // simply avoid updating the caches. if (code->IsFailure()) return; // Patch the call site depending on the state of the cache. if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { set_target(Code::cast(code)); } else if (state == MONOMORPHIC) { set_target(megamorphic_stub()); }#ifdef DEBUG TraceIC("StoreIC", name, state, target());#endif}Object* KeyedStoreIC::Store(State state, Handle<Object> object, Handle<Object> key, Handle<Object> value) { if (key->IsSymbol()) { Handle<String> name = Handle<String>::cast(key); // If the object is undefined or null it's illegal to try to set any // properties on it; throw a TypeError in that case. if (object->IsUndefined() || object->IsNull()) { return TypeError("non_object_property_store", object, name); } // Ignore stores where the receiver is not a JSObject. if (!object->IsJSObject()) return *value; Handle<JSObject> receiver = Handle<JSObject>::cast(object); // Check if the given name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { HandleScope scope; Handle<Object> result = SetElement(receiver, index, value); if (result.is_null()) return Failure::Exception(); return *value; } // Lookup the property locally in the receiver. LookupResult lookup; receiver->LocalLookup(*name, &lookup); // Update inline cache and stub cache. if (FLAG_use_ic && lookup.IsLoaded()) { UpdateCaches(&lookup, state, receiver, name, value); } // Set the property. return receiver->SetProperty(*name, *value, NONE); } // Do not use ICs for objects that require access checks (including // the global object). bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); if (use_ic) set_target(generic_stub()); // Set the property. return Runtime::SetObjectProperty(object, key, value, NONE);}void KeyedStoreIC::UpdateCaches(LookupResult* lookup, State state, Handle<JSObject> receiver, Handle<String> name, Handle<Object> value) { ASSERT(lookup->IsLoaded()); // Bail out if we didn't find a result. if (!lookup->IsValid() || !lookup->IsCacheable()) return; // If the property is read-only, we leave the IC in its current // state. if (lookup->IsReadOnly()) return; // If the property has a non-field type allowing map transitions // where there is extra room in the object, we leave the IC in its // current state. PropertyType type = lookup->type(); // Compute the code stub for this store; used for rewriting to // monomorphic state and making sure that the code stub is in the // stub cache. Object* code = NULL; switch (type) { case FIELD: { code = StubCache::ComputeKeyedStoreField(*name, *receiver, lookup->GetFieldIndex()); break; } case MAP_TRANSITION: { if (lookup->GetAttributes() == NONE) { if (receiver->map()->unused_property_fields() == 0) return; HandleScope scope; ASSERT(type == MAP_TRANSITION && (receiver->map()->unused_property_fields() > 0)); Handle<Map> transition(lookup->GetTransitionMap()); int index = transition->PropertyIndexFor(*name); code = StubCache::ComputeKeyedStoreField(*name, *receiver, index, *transition); break; } // fall through. } default: { // Always rewrite to the generic case so that we do not // repeatedly try to rewrite. code = generic_stub(); break; } } // If we're unable to compute the stub (not enough memory left), we // simply avoid updating the caches. if (code->IsFailure()) return; // Patch the call site depending on the state of the cache. Make // sure to always rewrite from monomorphic to megamorphic. ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); if (state == UNINITIALIZED || state == PREMONOMORPHIC) { set_target(Code::cast(code)); } else if (state == MONOMORPHIC) { set_target(megamorphic_stub()); }#ifdef DEBUG TraceIC("KeyedStoreIC", name, state, target());#endif}// ----------------------------------------------------------------------------// Static IC stub generators.//// Used from ic_<arch>.cc.Object* CallIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); CallIC ic; IC::State state = IC::StateFrom(ic.target(), args[0]); return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));}void CallIC::GenerateInitialize(MacroAssembler* masm, int argc) { Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));}void CallIC::GeneratePreMonomorphic(MacroAssembler* masm, int argc) { Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));}void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));}// Used from ic_<arch>.cc.Object* LoadIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); LoadIC ic; IC::State state = IC::StateFrom(ic.target(), args[0]); return ic.Load(state, args.at<Object>(0), args.at<String>(1));}void LoadIC::GenerateInitialize(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));}void LoadIC::GeneratePreMonomorphic(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));}// Used from ic_<arch>.ccObject* KeyedLoadIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); KeyedLoadIC ic; IC::State state = IC::StateFrom(ic.target(), args[0]); return ic.Load(state, args.at<Object>(0), args.at<Object>(1));}void KeyedLoadIC::GenerateInitialize(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));}void KeyedLoadIC::GeneratePreMonomorphic(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));}// Used from ic_<arch>.cc.Object* StoreIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 3); StoreIC ic; IC::State state = IC::StateFrom(ic.target(), args[0]); return ic.Store(state, args.at<Object>(0), args.at<String>(1), args.at<Object>(2));}void StoreIC::GenerateInitialize(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));}void StoreIC::GenerateMiss(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss)));}// Used from ic_<arch>.cc.Object* KeyedStoreIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 3); KeyedStoreIC ic; IC::State state = IC::StateFrom(ic.target(), args[0]); return ic.Store(state, args.at<Object>(0), args.at<Object>(1), args.at<Object>(2));}void KeyedStoreIC::GenerateInitialize(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss)));}void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss)));}static Address IC_utilities[] = {#define ADDR(name) FUNCTION_ADDR(name), IC_UTIL_LIST(ADDR) NULL#undef ADDR};Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id];}} } // namespace v8::internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -