X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fv8%2Fsrc%2Fic.cc;h=d73cf83f8f2429f5afe7084ff485af8dc85c0a5c;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=b46575794486e9dbc29b75a2eb2d25964b1dba8b;hpb=7338fba38ba696536d1cc9d389afd716a6ab2fe6;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/v8/src/ic.cc b/src/v8/src/ic.cc index b465757..d73cf83 100644 --- a/src/v8/src/ic.cc +++ b/src/v8/src/ic.cc @@ -424,8 +424,6 @@ void IC::Clear(Isolate* isolate, Address address) { case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(isolate, address, target); - case Code::CALL_IC: return CallIC::Clear(address, target); - case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); case Code::BINARY_OP_IC: @@ -438,14 +436,6 @@ void IC::Clear(Isolate* isolate, Address address) { } -void CallICBase::Clear(Address address, Code* target) { - if (IsCleared(target)) return; - Code* code = target->GetIsolate()->stub_cache()->FindCallInitialize( - target->arguments_count(), target->kind()); - SetTargetAtAddress(address, code); -} - - void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { if (IsCleared(target)) return; // Make sure to also clear the map used in inline fast cases. If we @@ -492,50 +482,6 @@ void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { } -Handle CallICBase::TryCallAsFunction(Handle object) { - Handle delegate = Execution::GetFunctionDelegate(isolate(), object); - - if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { - // Patch the receiver and use the delegate as the function to - // invoke. This is used for invoking objects as if they were functions. - const int argc = target()->arguments_count(); - StackFrameLocator locator(isolate()); - JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); - int index = frame->ComputeExpressionsCount() - (argc + 1); - frame->SetExpression(index, *object); - } - - return delegate; -} - - -void CallICBase::ReceiverToObjectIfRequired(Handle callee, - Handle object) { - while (callee->IsJSFunctionProxy()) { - callee = Handle(JSFunctionProxy::cast(*callee)->call_trap(), - isolate()); - } - - if (callee->IsJSFunction()) { - Handle function = Handle::cast(callee); - if (!function->shared()->is_classic_mode() || function->IsBuiltin()) { - // Do not wrap receiver for strict mode functions or for builtins. - return; - } - } - - // And only wrap string, number or boolean. - if (object->IsString() || object->IsNumber() || object->IsBoolean()) { - // Change the receiver to the result of calling ToObject on it. - const int argc = this->target()->arguments_count(); - StackFrameLocator locator(isolate()); - JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); - int index = frame->ComputeExpressionsCount() - (argc + 1); - frame->SetExpression(index, *isolate()->factory()->ToObject(object)); - } -} - - static bool MigrateDeprecated(Handle object) { if (!object->IsJSObject()) return false; Handle receiver = Handle::cast(object); @@ -545,248 +491,6 @@ static bool MigrateDeprecated(Handle object) { } -MaybeObject* CallICBase::LoadFunction(Handle object, - Handle name) { - bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; - - // 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_call", object, name); - } - - // Check if the name is trivially convertible to an index and get - // the element if so. - uint32_t index; - if (name->AsArrayIndex(&index)) { - Handle result = Object::GetElement(isolate(), object, index); - RETURN_IF_EMPTY_HANDLE(isolate(), result); - if (result->IsJSFunction()) return *result; - - // Try to find a suitable function delegate for the object at hand. - result = TryCallAsFunction(result); - if (result->IsJSFunction()) return *result; - - // Otherwise, it will fail in the lookup step. - } - - // Lookup the property in the object. - LookupResult lookup(isolate()); - LookupForRead(object, name, &lookup); - - if (!lookup.IsFound()) { - // If the object does not have the requested property, check which - // exception we need to throw. - return object->IsGlobalObject() - ? ReferenceError("not_defined", name) - : TypeError("undefined_method", object, name); - } - - // Lookup is valid: Update inline cache and stub cache. - if (use_ic) UpdateCaches(&lookup, object, name); - - // Get the property. - PropertyAttributes attr; - Handle result = - Object::GetProperty(object, object, &lookup, name, &attr); - RETURN_IF_EMPTY_HANDLE(isolate(), result); - - if (lookup.IsInterceptor() && attr == ABSENT) { - // If the object does not have the requested property, check which - // exception we need to throw. - return object->IsGlobalObject() - ? ReferenceError("not_defined", name) - : TypeError("undefined_method", object, name); - } - - ASSERT(!result->IsTheHole()); - - // Make receiver an object if the callee requires it. Strict mode or builtin - // functions do not wrap the receiver, non-strict functions and objects - // called as functions do. - ReceiverToObjectIfRequired(result, object); - - if (result->IsJSFunction()) { - Handle function = Handle::cast(result); -#ifdef ENABLE_DEBUGGER_SUPPORT - // Handle stepping into a function if step into is active. - Debug* debug = isolate()->debug(); - if (debug->StepInActive()) { - // Protect the result in a handle as the debugger can allocate and might - // cause GC. - debug->HandleStepIn(function, object, fp(), false); - } -#endif - return *function; - } - - // Try to find a suitable function delegate for the object at hand. - result = TryCallAsFunction(result); - if (result->IsJSFunction()) return *result; - - return TypeError("property_not_function", object, name); -} - - -Handle CallICBase::ComputeMonomorphicStub(LookupResult* lookup, - Handle object, - Handle name) { - int argc = target()->arguments_count(); - Handle holder(lookup->holder(), isolate()); - switch (lookup->type()) { - case FIELD: { - PropertyIndex index = lookup->GetFieldIndex(); - return isolate()->stub_cache()->ComputeCallField( - argc, kind_, extra_ic_state(), name, object, holder, index); - } - case CONSTANT: { - if (!lookup->IsConstantFunction()) return Handle::null(); - // 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. - Handle function(lookup->GetConstantFunction(), isolate()); - return isolate()->stub_cache()->ComputeCallConstant( - argc, kind_, extra_ic_state(), name, object, holder, function); - } - case NORMAL: { - // If we return a null handle, the IC will not be patched. - if (!object->IsJSObject()) return Handle::null(); - Handle receiver = Handle::cast(object); - - if (holder->IsGlobalObject()) { - Handle global = Handle::cast(holder); - Handle cell( - global->GetPropertyCell(lookup), isolate()); - if (!cell->value()->IsJSFunction()) return Handle::null(); - Handle function(JSFunction::cast(cell->value())); - return isolate()->stub_cache()->ComputeCallGlobal( - argc, kind_, extra_ic_state(), name, - receiver, global, cell, function); - } else { - // 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 (!holder.is_identical_to(receiver)) return Handle::null(); - return isolate()->stub_cache()->ComputeCallNormal( - argc, kind_, extra_ic_state()); - } - break; - } - case INTERCEPTOR: - ASSERT(HasInterceptorGetter(*holder)); - return isolate()->stub_cache()->ComputeCallInterceptor( - argc, kind_, extra_ic_state(), name, object, holder); - default: - return Handle::null(); - } -} - - -Handle CallICBase::megamorphic_stub() { - return isolate()->stub_cache()->ComputeCallMegamorphic( - target()->arguments_count(), kind_, extra_ic_state()); -} - - -Handle CallICBase::pre_monomorphic_stub() { - return isolate()->stub_cache()->ComputeCallPreMonomorphic( - target()->arguments_count(), kind_, extra_ic_state()); -} - - -void CallICBase::UpdateCaches(LookupResult* lookup, - Handle object, - Handle name) { - // Bail out if we didn't find a result. - if (!lookup->IsProperty() || !lookup->IsCacheable()) return; - - if (state() == UNINITIALIZED) { - set_target(*pre_monomorphic_stub()); - TRACE_IC("CallIC", name); - return; - } - - Handle code = ComputeMonomorphicStub(lookup, object, name); - // If there's no appropriate stub we simply avoid updating the caches. - // TODO(verwaest): Install a slow fallback in this case to avoid not learning, - // and deopting Crankshaft code. - if (code.is_null()) return; - - Handle cache_object = object->IsJSObject() - ? Handle::cast(object) - : Handle(JSObject::cast(object->GetPrototype(isolate())), - isolate()); - - PatchCache(CurrentTypeOf(cache_object, isolate()), name, code); - TRACE_IC("CallIC", name); -} - - -MaybeObject* KeyedCallIC::LoadFunction(Handle object, - Handle key) { - if (key->IsInternalizedString()) { - return CallICBase::LoadFunction(object, Handle::cast(key)); - } - - if (object->IsUndefined() || object->IsNull()) { - return TypeError("non_object_property_call", object, key); - } - - bool use_ic = MigrateDeprecated(object) - ? false : FLAG_use_ic && !object->IsAccessCheckNeeded(); - - if (use_ic && state() != MEGAMORPHIC) { - ASSERT(!object->IsJSGlobalProxy()); - int argc = target()->arguments_count(); - Handle stub; - - // Use the KeyedArrayCallStub if the call is of the form array[smi](...), - // where array is an instance of one of the initial array maps (without - // extra named properties). - // TODO(verwaest): Also support keyed calls on instances of other maps. - if (object->IsJSArray() && key->IsSmi()) { - Handle array = Handle::cast(object); - ElementsKind kind = array->map()->elements_kind(); - if (IsFastObjectElementsKind(kind) && - array->map() == isolate()->get_initial_js_array_map(kind)) { - KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc); - stub = stub_gen.GetCode(isolate()); - } - } - - if (stub.is_null()) { - stub = isolate()->stub_cache()->ComputeCallMegamorphic( - argc, Code::KEYED_CALL_IC, kNoExtraICState); - if (object->IsJSObject()) { - Handle receiver = Handle::cast(object); - if (receiver->elements()->map() == - isolate()->heap()->non_strict_arguments_elements_map()) { - stub = isolate()->stub_cache()->ComputeCallArguments(argc); - } - } - ASSERT(!stub.is_null()); - } - set_target(*stub); - TRACE_IC("CallIC", key); - } - - Handle result = GetProperty(isolate(), object, key); - RETURN_IF_EMPTY_HANDLE(isolate(), result); - - // Make receiver an object if the callee requires it. Strict mode or builtin - // functions do not wrap the receiver, non-strict functions and objects - // called as functions do. - ReceiverToObjectIfRequired(result, object); - if (result->IsJSFunction()) return *result; - - result = TryCallAsFunction(result); - if (result->IsJSFunction()) return *result; - - return TypeError("property_not_function", object, key); -} - - MaybeObject* LoadIC::Load(Handle object, Handle name) { // If the object is undefined or null it's illegal to try to get any @@ -880,6 +584,7 @@ MaybeObject* LoadIC::Load(Handle object, attr == ABSENT && IsUndeclaredGlobal(object)) { return ReferenceError("not_defined", name); } + return *result; } @@ -956,6 +661,10 @@ Handle IC::CurrentTypeOf(Handle object, Isolate* isolate) { Handle IC::TypeToMap(HeapType* type, Isolate* isolate) { if (type->Is(HeapType::Number())) return isolate->factory()->heap_number_map(); + if (type->Is(HeapType::Float32x4())) + return isolate->factory()->float32x4_map(); + if (type->Is(HeapType::Int32x4())) + return isolate->factory()->int32x4_map(); if (type->Is(HeapType::Boolean())) return isolate->factory()->oddball_map(); if (type->IsConstant()) { return handle(Handle::cast(type->AsConstant())->map()); @@ -965,19 +674,32 @@ Handle IC::TypeToMap(HeapType* type, Isolate* isolate) { } -Handle IC::MapToType(Handle map) { - Isolate* isolate = map->GetIsolate(); +template +typename T::TypeHandle IC::MapToType(Handle map, + typename T::Region* region) { if (map->instance_type() == HEAP_NUMBER_TYPE) { - return HeapType::Number(isolate); + return T::Number(region); + } else if (map->instance_type() == FLOAT32x4_TYPE) { + return T::Float32x4(region); + } else if (map->instance_type() == INT32x4_TYPE) { + return T::Int32x4(region); } else if (map->instance_type() == ODDBALL_TYPE) { // The only oddballs that can be recorded in ICs are booleans. - return HeapType::Boolean(isolate); + return T::Boolean(region); } else { - return HeapType::Class(map, isolate); + return T::Class(map, region); } } +template +Type* IC::MapToType(Handle map, Zone* zone); + + +template +Handle IC::MapToType(Handle map, Isolate* region); + + void IC::UpdateMonomorphicIC(Handle type, Handle handler, Handle name) { @@ -1027,9 +749,7 @@ void IC::PatchCache(Handle type, case MONOMORPHIC: { // For now, call stubs are allowed to rewrite to the same stub. This // happens e.g., when the field does not contain a function. - ASSERT(target()->is_call_stub() || - target()->is_keyed_call_stub() || - !target().is_identical_to(code)); + ASSERT(!target().is_identical_to(code)); Code* old_handler = target()->FindFirstHandler(); if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { UpdateMonomorphicIC(type, code, name); @@ -1056,23 +776,20 @@ void IC::PatchCache(Handle type, } -Handle LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { - Handle ic = isolate->stub_cache()->ComputeLoad( - UNINITIALIZED, ComputeExtraICState(mode)); - return ic; +Handle LoadIC::initialize_stub(Isolate* isolate, + ExtraICState extra_state) { + return isolate->stub_cache()->ComputeLoad(UNINITIALIZED, extra_state); } Handle LoadIC::pre_monomorphic_stub(Isolate* isolate, - ContextualMode mode) { - return isolate->stub_cache()->ComputeLoad( - PREMONOMORPHIC, ComputeExtraICState(mode)); + ExtraICState extra_state) { + return isolate->stub_cache()->ComputeLoad(PREMONOMORPHIC, extra_state); } Handle LoadIC::megamorphic_stub() { - return isolate()->stub_cache()->ComputeLoad( - MEGAMORPHIC, extra_ic_state()); + return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state()); } @@ -1208,9 +925,11 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, // Use simple field loads for some well-known callback properties. if (object->IsJSObject()) { Handle receiver = Handle::cast(object); - Handle map(receiver->map()); + Handle type = IC::MapToType( + handle(receiver->map()), isolate()); int object_offset; - if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { + if (Accessors::IsJSObjectFieldAccessor( + type, name, &object_offset)) { return SimpleFieldLoad(object_offset / kPointerSize); } } @@ -1238,7 +957,7 @@ Handle LoadIC::CompileHandler(LookupResult* lookup, } CallOptimization call_optimization(function); if (call_optimization.is_simple_api_call() && - call_optimization.IsCompatibleReceiver(*object)) { + call_optimization.IsCompatibleReceiver(object, holder)) { return compiler.CompileLoadCallback( type, holder, name, call_optimization); } @@ -1429,8 +1148,7 @@ static bool LookupForWrite(Handle receiver, // receiver when trying to fetch extra information from the transition. receiver->map()->LookupTransition(*holder, *name, lookup); if (!lookup->IsTransition()) return false; - PropertyDetails target_details = - lookup->GetTransitionDetails(receiver->map()); + PropertyDetails target_details = lookup->GetTransitionDetails(); if (target_details.IsReadOnly()) return false; // If the value that's being stored does not fit in the field that the @@ -1441,7 +1159,7 @@ static bool LookupForWrite(Handle receiver, // transition target. ASSERT(!receiver->map()->is_deprecated()); if (!value->FitsRepresentation(target_details.representation())) { - Handle target(lookup->GetTransitionMapFromMap(receiver->map())); + Handle target(lookup->GetTransitionTarget()); Map::GeneralizeRepresentation( target, target->LastAdded(), value->OptimalRepresentation(), FORCE_FIELD); @@ -1614,12 +1332,8 @@ Handle StoreIC::CompileHandler(LookupResult* lookup, case TRANSITION: { // Explicitly pass in the receiver map since LookupForWrite may have // stored something else than the receiver in the holder. - Handle transition( - lookup->GetTransitionTarget(receiver->map()), isolate()); - int descriptor = transition->LastAdded(); - - DescriptorArray* target_descriptors = transition->instance_descriptors(); - PropertyDetails details = target_descriptors->GetDetails(descriptor); + Handle transition(lookup->GetTransitionTarget()); + PropertyDetails details = transition->GetLastDescriptorDetails(); if (details.type() == CALLBACKS || details.attributes() != NONE) break; @@ -1664,7 +1378,7 @@ Handle StoreIC::CompileHandler(LookupResult* lookup, Handle function = Handle::cast(setter); CallOptimization call_optimization(function); if (call_optimization.is_simple_api_call() && - call_optimization.IsCompatibleReceiver(*receiver)) { + call_optimization.IsCompatibleReceiver(receiver, holder)) { return compiler.CompileStoreCallback( receiver, holder, name, call_optimization); } @@ -1736,7 +1450,8 @@ Handle KeyedStoreIC::StoreElementStub(Handle receiver, transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode); } - if (IsTransitionOfMonomorphicTarget(MapToType(transitioned_receiver_map))) { + if (IsTransitionOfMonomorphicTarget( + MapToType(transitioned_receiver_map, isolate()))) { // Element family is the same, use the "worst" case map. store_mode = GetNonTransitioningStoreMode(store_mode); return isolate()->stub_cache()->ComputeKeyedStoreElement( @@ -2025,51 +1740,6 @@ MaybeObject* KeyedStoreIC::Store(Handle object, // // Used from ic-.cc. -RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { - HandleScope scope(isolate); - ASSERT(args.length() == 2); - CallIC ic(isolate); - Handle receiver = args.at(0); - Handle key = args.at(1); - ic.UpdateState(receiver, key); - MaybeObject* maybe_result = ic.LoadFunction(receiver, key); - JSFunction* raw_function; - if (!maybe_result->To(&raw_function)) return maybe_result; - - // The first time the inline cache is updated may be the first time the - // function it references gets called. If the function is lazily compiled - // then the first call will trigger a compilation. We check for this case - // and we do the compilation immediately, instead of waiting for the stub - // currently attached to the JSFunction object to trigger compilation. - if (raw_function->is_compiled()) return raw_function; - - Handle function(raw_function); - Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); - return *function; -} - - -// Used from ic-.cc. -RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { - HandleScope scope(isolate); - ASSERT(args.length() == 2); - KeyedCallIC ic(isolate); - Handle receiver = args.at(0); - Handle key = args.at(1); - ic.UpdateState(receiver, key); - MaybeObject* maybe_result = ic.LoadFunction(receiver, key); - // Result could be a function or a failure. - JSFunction* raw_function = NULL; - if (!maybe_result->To(&raw_function)) return maybe_result; - - if (raw_function->is_compiled()) return raw_function; - - Handle function(raw_function, isolate); - Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); - return *function; -} - - // Used from ic-.cc. RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { HandleScope scope(isolate); @@ -2128,28 +1798,6 @@ RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { } -RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure) { - HandleScope scope(isolate); - ASSERT(args.length() == 2); - KeyedCallIC ic(isolate); - Arguments* caller_args = reinterpret_cast(args[0]); - Handle key = args.at(1); - Handle receiver((*caller_args)[0], isolate); - - ic.UpdateState(receiver, key); - MaybeObject* maybe_result = ic.LoadFunction(receiver, key); - // Result could be a function or a failure. - JSFunction* raw_function = NULL; - if (!maybe_result->To(&raw_function)) return maybe_result; - - if (raw_function->is_compiled()) return raw_function; - - Handle function(raw_function, isolate); - Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); - return *function; -} - - RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { SealHandleScope shs(isolate);