summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/ic.cc
diff options
context:
space:
mode:
authorAli Ijaz Sheikh <ofrobots@google.com>2016-01-20 09:45:45 -0800
committerAli Ijaz Sheikh <ofrobots@google.com>2016-01-21 16:53:58 -0800
commitef4170ea03a80b21b2d8a65ce432efaa370fe2fa (patch)
treee382b1b38b729cd8155b56b441c3a563914854a3 /deps/v8/src/ic/ic.cc
parent5f6dfab832979999d2f806fc1a2f1c11a25b0f35 (diff)
downloadnode-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.cc121
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.