⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ic.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
    // setting the monomorphic state.    code = StubCache::ComputeCallPreMonomorphic(argc);  } else if (state == MONOMORPHIC) {    code = StubCache::ComputeCallMegamorphic(argc);  } else {    // Compute monomorphic stub.    switch (lookup->type()) {      case FIELD: {        int index = lookup->GetFieldIndex();        code = StubCache::ComputeCallField(argc, *name, *object,                                           lookup->holder(), index);        break;      }      case CONSTANT_FUNCTION: {        // Get the constant function and compute the code stub for this        // call; used for rewriting to monomorphic state and making sure        // that the code stub is in the stub cache.        JSFunction* function = lookup->GetConstantFunction();        code = StubCache::ComputeCallConstant(argc, *name, *object,                                              lookup->holder(), function);        break;      }      case NORMAL: {        // There is only one shared stub for calling normalized        // properties. It does not traverse the prototype chain, so the        // property must be found in the receiver for the stub to be        // applicable.        if (!object->IsJSObject()) return;        Handle<JSObject> receiver = Handle<JSObject>::cast(object);        if (lookup->holder() != *receiver) return;        code = StubCache::ComputeCallNormal(argc, *name, *receiver);        break;      }      case INTERCEPTOR: {        code = StubCache::ComputeCallInterceptor(argc, *name, *object,                                                 lookup->holder());        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 == PREMONOMORPHIC ||      state == MONOMORPHIC || state == MONOMORPHIC_PROTOTYPE_FAILURE) {    set_target(Code::cast(code));  }#ifdef DEBUG  TraceIC("CallIC", name, state, target());#endif}Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {  // If the object is undefined or null it's illegal to try to get any  // of its properties; throw a TypeError in that case.  if (object->IsUndefined() || object->IsNull()) {    return TypeError("non_object_property_load", object, name);  }  if (FLAG_use_ic) {    // Use specialized code for getting the length of strings.    if (object->IsString() && name->Equals(Heap::length_symbol())) {#ifdef DEBUG      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");#endif      Code* target = NULL;      if (object->IsShortString()) {        target = Builtins::builtin(Builtins::LoadIC_ShortStringLength);      } else if (object->IsMediumString()) {        target = Builtins::builtin(Builtins::LoadIC_MediumStringLength);      } else {        ASSERT(object->IsLongString());        target  = Builtins::builtin(Builtins::LoadIC_LongStringLength);      }      set_target(target);      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);      return Smi::FromInt(String::cast(*object)->length());    }    // Use specialized code for getting the length of arrays.    if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {#ifdef DEBUG      if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");#endif      Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength);      set_target(target);      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);      return JSArray::cast(*object)->length();    }    // Use specialized code for getting prototype of functions.    if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) {#ifdef DEBUG      if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");#endif      Code* target = Builtins::builtin(Builtins::LoadIC_FunctionPrototype);      set_target(target);      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);      return Accessors::FunctionGetPrototype(*object, 0);    }  }  // Check if the name is trivially convertible to an index and get  // the element if so.  uint32_t index;  if (name->AsArrayIndex(&index)) return object->GetElement(index);  // Named lookup in the object.  LookupResult lookup;  object->Lookup(*name, &lookup);  // If lookup is invalid, check if we need to throw an exception.  if (!lookup.IsValid()) {    if (FLAG_strict || is_contextual()) {      return ReferenceError("not_defined", name);    }    String* class_name = object->IsJSObject()                         ? Handle<JSObject>::cast(object)->class_name()                         : Heap::empty_string();    LOG(SuspectReadEvent(*name, class_name));    USE(class_name);  }  // Update inline cache and stub cache.  if (FLAG_use_ic && lookup.IsLoaded()) {    UpdateCaches(&lookup, state, object, name);  }  PropertyAttributes attr;  if (lookup.IsValid() && lookup.type() == INTERCEPTOR) {    // Get the property.    Object* result = object->GetProperty(*object, &lookup, *name, &attr);    if (result->IsFailure()) return result;    // If the property is not present, check if we need to throw an    // exception.    if (attr == ABSENT && is_contextual()) {      return ReferenceError("not_defined", name);    }    return result;  }  // Get the property.  return object->GetProperty(*object, &lookup, *name, &attr);}void LoadIC::UpdateCaches(LookupResult* lookup,                          State state,                          Handle<Object> object,                          Handle<String> name) {  ASSERT(lookup->IsLoaded());  // Bail out if we didn't find a result.  if (!lookup->IsValid() || !lookup->IsCacheable()) return;  // Loading properties from values is not common, so don't try to  // deal with non-JS objects here.  if (!object->IsJSObject()) return;  Handle<JSObject> receiver = Handle<JSObject>::cast(object);  // Compute the code stub for this load.  Object* code = NULL;  if (state == UNINITIALIZED) {    // This is the first time we execute this inline cache.    // Set the target to the pre monomorphic stub to delay    // setting the monomorphic state.    code = pre_monomorphic_stub();  } else {    // Compute monomorphic stub.    switch (lookup->type()) {      case FIELD: {        code = StubCache::ComputeLoadField(*name, *receiver,                                           lookup->holder(),                                           lookup->GetFieldIndex());        break;      }      case CONSTANT_FUNCTION: {        Object* constant = lookup->GetConstantFunction();        code = StubCache::ComputeLoadConstant(*name, *receiver,                                              lookup->holder(), constant);        break;      }      case NORMAL: {        // There is only one shared stub for loading normalized        // properties. It does not traverse the prototype chain, so the        // property must be found in the receiver for the stub to be        // applicable.        if (lookup->holder() != *receiver) return;        code = StubCache::ComputeLoadNormal(*name, *receiver);        break;      }      case CALLBACKS: {        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;        AccessorInfo* callback =            AccessorInfo::cast(lookup->GetCallbackObject());        if (v8::ToCData<Address>(callback->getter()) == 0) return;        code = StubCache::ComputeLoadCallback(*name, *receiver,                                              lookup->holder(), callback);        break;      }      case INTERCEPTOR: {        code = StubCache::ComputeLoadInterceptor(*name, *receiver,                                                 lookup->holder());        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 == PREMONOMORPHIC ||      state == MONOMORPHIC_PROTOTYPE_FAILURE) {    set_target(Code::cast(code));  } else if (state == MONOMORPHIC) {    set_target(megamorphic_stub());  }#ifdef DEBUG  TraceIC("LoadIC", name, state, target());#endif}Object* KeyedLoadIC::Load(State state,                          Handle<Object> object,                          Handle<Object> key) {  if (key->IsSymbol()) {    Handle<String> name = Handle<String>::cast(key);    // If the object is undefined or null it's illegal to try to get any    // of its properties; throw a TypeError in that case.    if (object->IsUndefined() || object->IsNull()) {      return TypeError("non_object_property_load", object, name);    }    if (FLAG_use_ic) {      // Use specialized code for getting the length of strings.      if (object->IsString() && name->Equals(Heap::length_symbol())) {        Handle<String> string = Handle<String>::cast(object);        Object* code = NULL;        if (string->IsShortString()) {          code = StubCache::ComputeKeyedLoadShortStringLength(*name, *string);        } else if (string->IsMediumString()) {          code =              StubCache::ComputeKeyedLoadMediumStringLength(*name, *string);        } else {          ASSERT(string->IsLongString());          code = StubCache::ComputeKeyedLoadLongStringLength(*name, *string);        }        if (code->IsFailure()) return code;        set_target(Code::cast(code));#ifdef DEBUG        TraceIC("KeyedLoadIC", name, state, target());#endif        return Smi::FromInt(string->length());      }      // Use specialized code for getting the length of arrays.      if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {        Handle<JSArray> array = Handle<JSArray>::cast(object);        Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array);        if (code->IsFailure()) return code;        set_target(Code::cast(code));#ifdef DEBUG        TraceIC("KeyedLoadIC", name, state, target());#endif        return JSArray::cast(*object)->length();      }      // Use specialized code for getting prototype of functions.      if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol())) {        Handle<JSFunction> function = Handle<JSFunction>::cast(object);        Object* code =            StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);        if (code->IsFailure()) return code;        set_target(Code::cast(code));#ifdef DEBUG        TraceIC("KeyedLoadIC", name, state, target());#endif        return Accessors::FunctionGetPrototype(*object, 0);      }    }    // Check if the name is trivially convertible to an index and get    // the element or char if so.    uint32_t index = 0;    if (name->AsArrayIndex(&index)) {      HandleScope scope;      // Rewrite to the generic keyed load stub.      if (FLAG_use_ic) set_target(generic_stub());      return Runtime::GetElementOrCharAt(object, index);    }    // Named lookup.    LookupResult lookup;    object->Lookup(*name, &lookup);    // If lookup is invalid, check if we need to throw an exception.    if (!lookup.IsValid()) {      if (FLAG_strict || is_contextual()) {        return ReferenceError("not_defined", name);      }    }    // Update the inline cache.    if (FLAG_use_ic && lookup.IsLoaded()) {      UpdateCaches(&lookup, state, object, name);    }    PropertyAttributes attr;    if (lookup.IsValid() && lookup.type() == INTERCEPTOR) {      // Get the property.      Object* result = object->GetProperty(*object, &lookup, *name, &attr);      if (result->IsFailure()) return result;      // If the property is not present, check if we need to throw an      // exception.      if (attr == ABSENT && is_contextual()) {        return ReferenceError("not_defined", name);      }      return result;    }    return object->GetProperty(*object, &lookup, *name, &attr);  }  // 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());  // Get the property.  return Runtime::GetObjectProperty(object, key);}void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,                               Handle<Object> object, Handle<String> name) {  ASSERT(lookup->IsLoaded());  // Bail out if we didn't find a result.  if (!lookup->IsValid() || !lookup->IsCacheable()) return;  if (!object->IsJSObject()) return;  Handle<JSObject> receiver = Handle<JSObject>::cast(object);  // Compute the code stub for this load.  Object* code = NULL;  if (state == UNINITIALIZED) {    // This is the first time we execute this inline cache.    // Set the target to the pre monomorphic stub to delay    // setting the monomorphic state.    code = pre_monomorphic_stub();  } else {    // Compute a monomorphic stub.    switch (lookup->type()) {      case FIELD: {        code = StubCache::ComputeKeyedLoadField(*name, *receiver,                                                lookup->holder(),                                                lookup->GetFieldIndex());        break;      }      case CONSTANT_FUNCTION: {        Object* constant = lookup->GetConstantFunction();        code = StubCache::ComputeKeyedLoadConstant(*name, *receiver,                                                   lookup->holder(), constant);        break;      }      case CALLBACKS: {        if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;        AccessorInfo* callback =            AccessorInfo::cast(lookup->GetCallbackObject());        if (v8::ToCData<Address>(callback->getter()) == 0) return;        code = StubCache::ComputeKeyedLoadCallback(*name, *receiver,                                                   lookup->holder(), callback);        break;      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -