diff options
author | Ali Ijaz Sheikh <ofrobots@google.com> | 2016-01-20 09:45:45 -0800 |
---|---|---|
committer | Ali Ijaz Sheikh <ofrobots@google.com> | 2016-01-21 16:53:58 -0800 |
commit | ef4170ea03a80b21b2d8a65ce432efaa370fe2fa (patch) | |
tree | e382b1b38b729cd8155b56b441c3a563914854a3 /deps/v8/src/ic/ic.cc | |
parent | 5f6dfab832979999d2f806fc1a2f1c11a25b0f35 (diff) | |
download | node-new-ef4170ea03a80b21b2d8a65ce432efaa370fe2fa.tar.gz |
deps: upgrade to V8 4.8.271.17
Pick up V8 4.8 branch-head. This branch brings in @@isConcatSpreadable,
@@toPrimitive and ToLength ES6 changes. For full details see:
http://v8project.blogspot.de/2015/11/v8-release-48.html
https://github.com/v8/v8/commit/fa163e2
Ref: https://github.com/nodejs/node/pull/4399
PR-URL: https://github.com/nodejs/node/pull/4785
Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'deps/v8/src/ic/ic.cc')
-rw-r--r-- | deps/v8/src/ic/ic.cc | 121 |
1 files changed, 68 insertions, 53 deletions
diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc index b2bcaeeb0f..3dc3029300 100644 --- a/deps/v8/src/ic/ic.cc +++ b/deps/v8/src/ic/ic.cc @@ -47,9 +47,6 @@ char IC::TransitionMarkFromState(IC::State state) { // 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; @@ -200,6 +197,11 @@ SharedFunctionInfo* IC::GetSharedFunctionInfo() const { // corresponding to the frame. StackFrameIterator it(isolate()); while (it.frame()->fp() != this->fp()) it.Advance(); + if (FLAG_ignition && it.frame()->type() == StackFrame::STUB) { + // Advance over bytecode handler frame. + // TODO(rmcilroy): Remove this once bytecode handlers don't need a frame. + it.Advance(); + } JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame()); // Find the function on the stack and both the active code for the // function and the original code. @@ -293,8 +295,8 @@ bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver, } } - if (receiver->IsGlobalObject()) { - Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); + if (receiver->IsJSGlobalObject()) { + Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver); LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR); if (it.state() == LookupIterator::ACCESS_CHECK) return false; if (!it.IsFound()) return false; @@ -332,14 +334,6 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { MarkPrototypeFailure(name); return; } - - // The builtins object is special. It only changes when JavaScript - // builtins are loaded lazily. It is important to keep inline - // caches for the builtins object monomorphic. Therefore, if we get - // an inline cache miss for the builtins object after lazily loading - // JavaScript builtins, we return uninitialized as the state to - // force the inline cache back to monomorphic state. - if (receiver->IsJSBuiltinsObject()) state_ = PREMONOMORPHIC; } @@ -388,7 +382,6 @@ static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state, break; case PROTOTYPE_FAILURE: case DEBUG_STUB: - case DEFAULT: UNREACHABLE(); } } @@ -707,10 +700,10 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) { bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; - if (object->IsGlobalObject() && name->IsString()) { + if (object->IsJSGlobalObject() && name->IsString()) { // Look up in script context table. Handle<String> str_name = Handle<String>::cast(name); - Handle<GlobalObject> global = Handle<GlobalObject>::cast(object); + Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object); Handle<ScriptContextTable> script_contexts( global->native_context()->script_context_table()); @@ -918,7 +911,6 @@ void IC::PatchCache(Handle<Name> name, Handle<Code> code) { break; case DEBUG_STUB: break; - case DEFAULT: case GENERIC: UNREACHABLE(); break; @@ -1241,7 +1233,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, // When debugging we need to go the slow path to flood the accessor. if (GetSharedFunctionInfo()->HasDebugInfo()) break; Handle<JSFunction> function = Handle<JSFunction>::cast(getter); - if (!receiver->IsJSObject() && !function->IsBuiltin() && + if (!receiver->IsJSObject() && !function->shared()->IsBuiltin() && is_sloppy(function->shared()->language_mode())) { // Calling sloppy non-builtins with a value as the receiver // requires boxing. @@ -1269,7 +1261,7 @@ Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup, case LookupIterator::DATA: { if (lookup->is_dictionary_holder()) { if (kind() != Code::LOAD_IC) break; - if (holder->IsGlobalObject()) { + if (holder->IsJSGlobalObject()) { NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder); Handle<PropertyCell> cell = lookup->GetPropertyCell(); @@ -1507,6 +1499,8 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value, PrototypeIterator::GetCurrent(iter)); } + if (it->HolderIsReceiverOrHiddenPrototype()) return false; + it->PrepareTransitionToDataProperty(value, NONE, store_mode); return it->IsCacheableTransition(); } @@ -1542,10 +1536,10 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, return result; } - if (object->IsGlobalObject() && name->IsString()) { + if (object->IsJSGlobalObject() && name->IsString()) { // Look up in script context table. Handle<String> str_name = Handle<String>::cast(name); - Handle<GlobalObject> global = Handle<GlobalObject>::cast(object); + Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object); Handle<ScriptContextTable> script_contexts( global->native_context()->script_context_table()); @@ -1607,26 +1601,23 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, LookupIterator it(object, name); if (FLAG_use_ic) UpdateCaches(&it, value, store_mode); - // Set the property. - Handle<Object> result; - ASSIGN_RETURN_ON_EXCEPTION( - isolate(), result, - Object::SetProperty(&it, value, language_mode(), store_mode), Object); - return result; + MAYBE_RETURN_NULL( + Object::SetProperty(&it, value, language_mode(), store_mode)); + return value; } Handle<Code> CallIC::initialize_stub(Isolate* isolate, int argc, - CallICState::CallType call_type) { - CallICTrampolineStub stub(isolate, CallICState(argc, call_type)); + ConvertReceiverMode mode) { + CallICTrampolineStub stub(isolate, CallICState(argc, mode)); Handle<Code> code = stub.GetCode(); return code; } Handle<Code> CallIC::initialize_stub_in_optimized_code( - Isolate* isolate, int argc, CallICState::CallType call_type) { - CallICStub stub(isolate, CallICState(argc, call_type)); + Isolate* isolate, int argc, ConvertReceiverMode mode) { + CallICStub stub(isolate, CallICState(argc, mode)); Handle<Code> code = stub.GetCode(); return code; } @@ -1730,7 +1721,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, static Handle<Code> PropertyCellStoreHandler( - Isolate* isolate, Handle<JSObject> receiver, Handle<GlobalObject> holder, + Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { auto constant_type = Nothing<PropertyCellConstantType>(); if (type == PropertyCellType::kConstantType) { @@ -1759,12 +1750,12 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, switch (lookup->state()) { case LookupIterator::TRANSITION: { auto store_target = lookup->GetStoreTarget(); - if (store_target->IsGlobalObject()) { + if (store_target->IsJSGlobalObject()) { // TODO(dcarney): this currently just deopts. Use the transition cell. auto cell = isolate()->factory()->NewPropertyCell(); cell->set_value(*value); auto code = PropertyCellStoreHandler( - isolate(), store_target, Handle<GlobalObject>::cast(store_target), + isolate(), store_target, Handle<JSGlobalObject>::cast(store_target), lookup->name(), cell, PropertyCellType::kConstant); cell->set_value(isolate()->heap()->the_hole_value()); return code; @@ -1842,14 +1833,14 @@ Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, case LookupIterator::DATA: { if (lookup->is_dictionary_holder()) { - if (holder->IsGlobalObject()) { + if (holder->IsJSGlobalObject()) { DCHECK(holder.is_identical_to(receiver) || receiver->map()->prototype() == *holder); auto cell = lookup->GetPropertyCell(); auto updated_type = PropertyCell::UpdatedType( cell, value, lookup->property_details()); auto code = PropertyCellStoreHandler( - isolate(), receiver, Handle<GlobalObject>::cast(holder), + isolate(), receiver, Handle<JSGlobalObject>::cast(holder), lookup->name(), cell, updated_type); return code; } @@ -2276,7 +2267,8 @@ MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, // from peeking in the code bits of the handlers. if (!FLAG_vector_stores) ValidateStoreMode(stub); } else { - TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype"); + TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", + "dictionary or proxy prototype"); } } else { TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); @@ -2367,7 +2359,7 @@ RUNTIME_FUNCTION(Runtime_CallIC_Miss) { Handle<Object> function = args.at<Object>(0); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1); Handle<Smi> slot = args.at<Smi>(2); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); CallICNexus nexus(vector, vector_slot); CallIC ic(isolate, &nexus); ic.HandleMiss(function); @@ -2386,7 +2378,7 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) { DCHECK(args.length() == 4); Handle<Smi> slot = args.at<Smi>(2); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); // A monomorphic or polymorphic KeyedLoadIC with a string key can call the // LoadIC miss handler if the handler misses. Since the vector Nexus is // set up outside the IC, handle that here. @@ -2418,7 +2410,7 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) { DCHECK(args.length() == 4); Handle<Smi> slot = args.at<Smi>(2); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); KeyedLoadICNexus nexus(vector, vector_slot); KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); ic.UpdateState(receiver, key); @@ -2437,7 +2429,7 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) { DCHECK(args.length() == 4); Handle<Smi> slot = args.at<Smi>(2); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); KeyedLoadICNexus nexus(vector, vector_slot); KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); ic.UpdateState(receiver, key); @@ -2460,7 +2452,7 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) { DCHECK(args.length() == 5 || args.length() == 6); Handle<Smi> slot = args.at<Smi>(3); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { StoreICNexus nexus(vector, vector_slot); StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); @@ -2496,10 +2488,30 @@ RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) { Handle<Object> result; if (FLAG_vector_stores) { - DCHECK(args.length() == 5 || args.length() == 6); - Handle<Smi> slot = args.at<Smi>(3); - Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + int length = args.length(); + DCHECK(length == 5 || length == 6); + // We might have slot and vector, for a normal miss (slot(3), vector(4)). + // Or, map and vector for a transitioning store miss (map(3), vector(4)). + // In this case, we need to recover the slot from a virtual register. + // If length == 6, then a map is included (map(3), slot(4), vector(5)). + Handle<Smi> slot; + Handle<TypeFeedbackVector> vector; + if (length == 5) { + if (args.at<Object>(3)->IsMap()) { + vector = args.at<TypeFeedbackVector>(4); + slot = handle( + *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()), + isolate); + } else { + vector = args.at<TypeFeedbackVector>(4); + slot = args.at<Smi>(3); + } + } else { + vector = args.at<TypeFeedbackVector>(5); + slot = args.at<Smi>(4); + } + + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { StoreICNexus nexus(vector, vector_slot); StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); @@ -2539,7 +2551,7 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) { DCHECK(args.length() == 5); Handle<Smi> slot = args.at<Smi>(3); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); KeyedStoreICNexus nexus(vector, vector_slot); KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); ic.UpdateState(receiver, key); @@ -2568,7 +2580,7 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) { DCHECK(args.length() == 5); Handle<Smi> slot = args.at<Smi>(3); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); KeyedStoreICNexus nexus(vector, vector_slot); KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); ic.UpdateState(receiver, key); @@ -2634,11 +2646,14 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) { RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - DCHECK(args.length() == (FLAG_vector_stores ? 6 : 4)); + // Without vector stores, length == 4. + // With vector stores, length == 5 or 6, depending on whether the vector slot + // is passed in a virtual register or not. + DCHECK(!FLAG_vector_stores || args.length() == 5 || args.length() == 6); Handle<Object> object = args.at<Object>(0); Handle<Object> key = args.at<Object>(1); Handle<Object> value = args.at<Object>(2); - Handle<Map> map = args.at<Map>(FLAG_vector_stores ? 5 : 3); + Handle<Map> map = args.at<Map>(3); LanguageMode language_mode; if (FLAG_vector_stores) { KeyedStoreICNexus nexus(isolate); @@ -2910,9 +2925,9 @@ void CompareNilIC::Clear(Address address, Code* target, Address constant_pool) { Handle<Object> CompareNilIC::DoCompareNilSlow(Isolate* isolate, NilValue nil, Handle<Object> object) { if (object->IsNull() || object->IsUndefined()) { - return handle(Smi::FromInt(true), isolate); + return isolate->factory()->true_value(); } - return handle(Smi::FromInt(object->IsUndetectableObject()), isolate); + return isolate->factory()->ToBoolean(object->IsUndetectableObject()); } @@ -3127,7 +3142,7 @@ RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) { DCHECK(args.length() == 4); Handle<Smi> slot = args.at<Smi>(2); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); - FeedbackVectorICSlot vector_slot = vector->ToICSlot(slot->value()); + FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); // A monomorphic or polymorphic KeyedLoadIC with a string key can call the // LoadIC miss handler if the handler misses. Since the vector Nexus is // set up outside the IC, handle that here. |