summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic/x87
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2015-01-07 18:38:38 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2015-01-07 22:11:18 +0100
commitdad73f645cde6920e79db956e7ef82ed640d7615 (patch)
tree7ba3f3fc7e0722c5f130065461b7c56f571af383 /deps/v8/src/ic/x87
parent53ba494537259b18b346dc6150d6a100c557e08f (diff)
downloadnode-new-dad73f645cde6920e79db956e7ef82ed640d7615.tar.gz
deps: upgrade v8 to 3.31.74.1
PR-URL: https://github.com/iojs/io.js/pull/243 Reviewed-By: Fedor Indutny <fedor@indutny.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Diffstat (limited to 'deps/v8/src/ic/x87')
-rw-r--r--deps/v8/src/ic/x87/handler-compiler-x87.cc133
-rw-r--r--deps/v8/src/ic/x87/ic-compiler-x87.cc19
-rw-r--r--deps/v8/src/ic/x87/ic-x87.cc55
-rw-r--r--deps/v8/src/ic/x87/stub-cache-x87.cc40
4 files changed, 171 insertions, 76 deletions
diff --git a/deps/v8/src/ic/x87/handler-compiler-x87.cc b/deps/v8/src/ic/x87/handler-compiler-x87.cc
index ae637d11b7..2ff35954c8 100644
--- a/deps/v8/src/ic/x87/handler-compiler-x87.cc
+++ b/deps/v8/src/ic/x87/handler-compiler-x87.cc
@@ -47,6 +47,28 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
}
+void PropertyHandlerCompiler::PushVectorAndSlot(Register vector,
+ Register slot) {
+ MacroAssembler* masm = this->masm();
+ __ push(vector);
+ __ push(slot);
+}
+
+
+void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) {
+ MacroAssembler* masm = this->masm();
+ __ pop(slot);
+ __ pop(vector);
+}
+
+
+void PropertyHandlerCompiler::DiscardVectorAndSlot() {
+ MacroAssembler* masm = this->masm();
+ // Remove vector and slot.
+ __ add(esp, Immediate(2 * kPointerSize));
+}
+
+
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
MacroAssembler* masm, Label* miss_label, Register receiver,
Handle<Name> name, Register scratch0, Register scratch1) {
@@ -88,28 +110,23 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
- MacroAssembler* masm, int index, Register prototype, Label* miss) {
- // Get the global function with the given index.
- Handle<JSFunction> function(
- JSFunction::cast(masm->isolate()->native_context()->get(index)));
- // Check we're still in the same context.
- Register scratch = prototype;
+ MacroAssembler* masm, int index, Register result, Label* miss) {
const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
- __ mov(scratch, Operand(esi, offset));
- __ mov(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
- __ cmp(Operand(scratch, Context::SlotOffset(index)), function);
- __ j(not_equal, miss);
-
+ __ mov(result, Operand(esi, offset));
+ __ mov(result, FieldOperand(result, GlobalObject::kNativeContextOffset));
+ __ mov(result, Operand(result, Context::SlotOffset(index)));
// Load its initial map. The global functions all have initial maps.
- __ Move(prototype, Immediate(Handle<Map>(function->initial_map())));
+ __ mov(result,
+ FieldOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
// Load the prototype from the initial map.
- __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
+ __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
}
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
MacroAssembler* masm, Register receiver, Register scratch1,
Register scratch2, Label* miss_label) {
+ DCHECK(!FLAG_vector_ics);
__ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
__ mov(eax, scratch1);
__ ret(0);
@@ -329,17 +346,38 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
}
-void NamedStoreHandlerCompiler::GenerateRestoreNameAndMap(
- Handle<Name> name, Handle<Map> transition) {
+void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
__ mov(this->name(), Immediate(name));
- __ mov(StoreTransitionDescriptor::MapRegister(), Immediate(transition));
}
-void NamedStoreHandlerCompiler::GenerateConstantCheck(Object* constant,
+void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
+ Register scratch,
+ Label* miss) {
+ Handle<WeakCell> cell = Map::WeakCellForMap(transition);
+ Register map_reg = StoreTransitionDescriptor::MapRegister();
+ DCHECK(!map_reg.is(scratch));
+ __ LoadWeakValue(map_reg, cell, miss);
+ if (transition->CanBeDeprecated()) {
+ __ mov(scratch, FieldOperand(map_reg, Map::kBitField3Offset));
+ __ and_(scratch, Immediate(Map::Deprecated::kMask));
+ __ j(not_zero, miss);
+ }
+}
+
+
+void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
+ int descriptor,
Register value_reg,
+ Register scratch,
Label* miss_label) {
- __ CmpObject(value_reg, handle(constant, isolate()));
+ DCHECK(!map_reg.is(scratch));
+ DCHECK(!map_reg.is(value_reg));
+ DCHECK(!value_reg.is(scratch));
+ __ LoadInstanceDescriptors(map_reg, scratch);
+ __ mov(scratch,
+ FieldOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
+ __ cmp(value_reg, scratch);
__ j(not_equal, miss_label);
}
@@ -415,14 +453,12 @@ Register PropertyHandlerCompiler::CheckPrototypes(
reg = holder_reg; // From now on the object will be in holder_reg.
__ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
} else {
- bool in_new_space = heap()->InNewSpace(*prototype);
- // Two possible reasons for loading the prototype from the map:
- // (1) Can't store references to new space in code.
- // (2) Handler is shared for all receivers with the same prototype
- // map (but not necessarily the same prototype instance).
- bool load_prototype_from_map = in_new_space || depth == 1;
+ Register map_reg = scratch1;
+ __ mov(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
if (depth != 1 || check == CHECK_ALL_MAPS) {
- __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
+ Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
+ __ CmpWeakValue(map_reg, cell, scratch2);
+ __ j(not_equal, miss);
}
// Check access rights to the global object. This has to happen after
@@ -432,24 +468,15 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// global proxy (as opposed to using slow ICs). See corresponding code
// in LookupForRead().
if (current_map->IsJSGlobalProxyMap()) {
- __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss);
+ __ CheckAccessGlobalProxy(reg, map_reg, scratch2, miss);
+ // Restore map_reg.
+ __ mov(map_reg, FieldOperand(reg, HeapObject::kMapOffset));
} else if (current_map->IsJSGlobalObjectMap()) {
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
name, scratch2, miss);
}
-
- if (load_prototype_from_map) {
- // Save the map in scratch1 for later.
- __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
- }
-
reg = holder_reg; // From now on the object will be in holder_reg.
-
- if (load_prototype_from_map) {
- __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
- } else {
- __ mov(reg, prototype);
- }
+ __ mov(reg, FieldOperand(map_reg, Map::kPrototypeOffset));
}
// Go to the next object in the prototype chain.
@@ -462,7 +489,10 @@ Register PropertyHandlerCompiler::CheckPrototypes(
if (depth != 0 || check == CHECK_ALL_MAPS) {
// Check the holder map.
- __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
+ __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
+ __ CmpWeakValue(scratch1, cell, scratch2);
+ __ j(not_equal, miss);
}
// Perform security check for access to the global object.
@@ -482,6 +512,10 @@ void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
Label success;
__ jmp(&success);
__ bind(miss);
+ if (IC::ICUseVector(kind())) {
+ DCHECK(kind() == Code::LOAD_IC);
+ PopVectorAndSlot();
+ }
TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
}
@@ -581,7 +615,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
}
__ push(holder_reg);
__ push(this->name());
-
+ InterceptorVectorSlotPush(holder_reg);
// Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
// of this method.)
@@ -605,6 +639,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
__ mov(this->name(), Immediate(bit_cast<int32_t>(kZapValue)));
}
+ InterceptorVectorSlotPop(holder_reg);
__ pop(this->name());
__ pop(holder_reg);
if (must_preserve_receiver_reg) {
@@ -637,7 +672,7 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) {
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) {
- Register holder_reg = Frontend(receiver(), name);
+ Register holder_reg = Frontend(name);
__ pop(scratch1()); // remove the return address
__ push(receiver());
@@ -683,16 +718,15 @@ Register NamedStoreHandlerCompiler::value() {
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
-
+ if (IC::ICUseVector(kind())) {
+ PushVectorAndSlot();
+ }
FrontendHeader(receiver(), name, &miss);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
- if (masm()->serializer_enabled()) {
- __ mov(result, Immediate(cell));
- __ mov(result, FieldOperand(result, PropertyCell::kValueOffset));
- } else {
- __ mov(result, Operand::ForCell(cell));
- }
+ Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
+ __ LoadWeakValue(result, weak_cell, &miss);
+ __ mov(result, FieldOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
@@ -706,6 +740,9 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
// The code above already loads the result into the return register.
+ if (IC::ICUseVector(kind())) {
+ DiscardVectorAndSlot();
+ }
__ ret(0);
FrontendFooter(name, &miss);
diff --git a/deps/v8/src/ic/x87/ic-compiler-x87.cc b/deps/v8/src/ic/x87/ic-compiler-x87.cc
index 20b47e726e..89bd937480 100644
--- a/deps/v8/src/ic/x87/ic-compiler-x87.cc
+++ b/deps/v8/src/ic/x87/ic-compiler-x87.cc
@@ -44,10 +44,13 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
Label miss;
if (check == PROPERTY &&
- (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
- // In case we are compiling an IC for dictionary loads and stores, just
+ (kind() == Code::KEYED_STORE_IC || kind() == Code::KEYED_LOAD_IC)) {
+ // In case we are compiling an IC for dictionary loads or stores, just
// check whether the name is unique.
if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) {
+ // Keyed loads with dictionaries shouldn't be here, they go generic.
+ // The DCHECK is to protect assumptions when --vector-ics is on.
+ DCHECK(kind() != Code::KEYED_LOAD_IC);
Register tmp = scratch1();
__ JumpIfSmi(this->name(), &miss);
__ mov(tmp, FieldOperand(this->name(), HeapObject::kMapOffset));
@@ -75,7 +78,8 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
Handle<Map> map = IC::TypeToMap(*type, isolate());
if (!map->is_deprecated()) {
number_of_handled_maps++;
- __ cmp(map_reg, map);
+ Handle<WeakCell> cell = Map::WeakCellForMap(map);
+ __ CmpWeakValue(map_reg, cell, scratch2());
if (type->Is(HeapType::Number())) {
DCHECK(!number_case.is_unused());
__ bind(&number_case);
@@ -100,15 +104,18 @@ Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
MapHandleList* transitioned_maps) {
Label miss;
__ JumpIfSmi(receiver(), &miss, Label::kNear);
- __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
+ Register map_reg = scratch1();
+ __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
for (int i = 0; i < receiver_maps->length(); ++i) {
- __ cmp(scratch1(), receiver_maps->at(i));
+ Handle<WeakCell> cell = Map::WeakCellForMap(receiver_maps->at(i));
+ __ CmpWeakValue(map_reg, cell, scratch2());
if (transitioned_maps->at(i).is_null()) {
__ j(equal, handler_stubs->at(i));
} else {
Label next_map;
__ j(not_equal, &next_map, Label::kNear);
- __ mov(transition_map(), Immediate(transitioned_maps->at(i)));
+ Handle<WeakCell> cell = Map::WeakCellForMap(transitioned_maps->at(i));
+ __ LoadWeakValue(transition_map(), cell, &miss);
__ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map);
}
diff --git a/deps/v8/src/ic/x87/ic-x87.cc b/deps/v8/src/ic/x87/ic-x87.cc
index 959b8b628e..1004ac036b 100644
--- a/deps/v8/src/ic/x87/ic-x87.cc
+++ b/deps/v8/src/ic/x87/ic-x87.cc
@@ -694,8 +694,8 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
__ JumpIfNotUniqueNameInstanceType(ebx, &slow);
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::STORE_IC));
- masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
- key, ebx, no_reg);
+ masm->isolate()->stub_cache()->GenerateProbe(
+ masm, Code::STORE_IC, flags, false, receiver, key, ebx, no_reg);
// Cache miss.
__ jmp(&miss);
@@ -769,31 +769,52 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
static void LoadIC_PushArgs(MacroAssembler* masm) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
- DCHECK(!ebx.is(receiver) && !ebx.is(name));
+ if (FLAG_vector_ics) {
+ Register slot = VectorLoadICDescriptor::SlotRegister();
+ Register vector = VectorLoadICDescriptor::VectorRegister();
+ DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) &&
+ !edi.is(vector));
+
+ __ pop(edi);
+ __ push(receiver);
+ __ push(name);
+ __ push(slot);
+ __ push(vector);
+ __ push(edi);
+ } else {
+ DCHECK(!ebx.is(receiver) && !ebx.is(name));
- __ pop(ebx);
- __ push(receiver);
- __ push(name);
- __ push(ebx);
+ __ pop(ebx);
+ __ push(receiver);
+ __ push(name);
+ __ push(ebx);
+ }
}
void LoadIC::GenerateMiss(MacroAssembler* masm) {
// Return address is on the stack.
__ IncrementCounter(masm->isolate()->counters()->load_miss(), 1);
-
LoadIC_PushArgs(masm);
// Perform tail call to the entry.
ExternalReference ref =
ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
- __ TailCallExternalReference(ref, 2, 1);
+ int arg_count = FLAG_vector_ics ? 4 : 2;
+ __ TailCallExternalReference(ref, arg_count, 1);
}
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
// Return address is on the stack.
- LoadIC_PushArgs(masm);
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register name = LoadDescriptor::NameRegister();
+ DCHECK(!ebx.is(receiver) && !ebx.is(name));
+
+ __ pop(ebx);
+ __ push(receiver);
+ __ push(name);
+ __ push(ebx);
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
@@ -809,13 +830,21 @@ void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
// Perform tail call to the entry.
ExternalReference ref =
ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
- __ TailCallExternalReference(ref, 2, 1);
+ int arg_count = FLAG_vector_ics ? 4 : 2;
+ __ TailCallExternalReference(ref, arg_count, 1);
}
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
// Return address is on the stack.
- LoadIC_PushArgs(masm);
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register name = LoadDescriptor::NameRegister();
+ DCHECK(!ebx.is(receiver) && !ebx.is(name));
+
+ __ pop(ebx);
+ __ push(receiver);
+ __ push(name);
+ __ push(ebx);
// Perform tail call to the entry.
__ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
@@ -827,7 +856,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::STORE_IC));
masm->isolate()->stub_cache()->GenerateProbe(
- masm, flags, false, StoreDescriptor::ReceiverRegister(),
+ masm, Code::STORE_IC, flags, false, StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(), ebx, no_reg);
// Cache miss: Jump to runtime.
diff --git a/deps/v8/src/ic/x87/stub-cache-x87.cc b/deps/v8/src/ic/x87/stub-cache-x87.cc
index 0291ef3d82..be456ce95c 100644
--- a/deps/v8/src/ic/x87/stub-cache-x87.cc
+++ b/deps/v8/src/ic/x87/stub-cache-x87.cc
@@ -7,7 +7,9 @@
#if V8_TARGET_ARCH_X87
#include "src/codegen.h"
+#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
+#include "src/interface-descriptors.h"
namespace v8 {
namespace internal {
@@ -16,7 +18,7 @@ namespace internal {
static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
- Code::Flags flags, bool leave_frame,
+ Code::Kind ic_kind, Code::Flags flags, bool leave_frame,
StubCache::Table table, Register name, Register receiver,
// Number of the cache entry pointer-size scaled.
Register offset, Register extra) {
@@ -56,6 +58,13 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
}
#endif
+ if (IC::ICUseVector(ic_kind)) {
+ // The vector and slot were pushed onto the stack before starting the
+ // probe, and need to be dropped before calling the handler.
+ __ pop(VectorLoadICDescriptor::VectorRegister());
+ __ pop(VectorLoadICDescriptor::SlotRegister());
+ }
+
if (leave_frame) __ leave();
// Jump to the first instruction in the code stub.
@@ -100,6 +109,18 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
__ pop(offset);
__ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
+ if (IC::ICUseVector(ic_kind)) {
+ // The vector and slot were pushed onto the stack before starting the
+ // probe, and need to be dropped before calling the handler.
+ Register vector = VectorLoadICDescriptor::VectorRegister();
+ Register slot = VectorLoadICDescriptor::SlotRegister();
+ DCHECK(!offset.is(vector) && !offset.is(slot));
+
+ __ pop(vector);
+ __ pop(slot);
+ }
+
+
if (leave_frame) __ leave();
// Jump to the first instruction in the code stub.
@@ -113,10 +134,11 @@ static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
}
-void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
- bool leave_frame, Register receiver,
- Register name, Register scratch, Register extra,
- Register extra2, Register extra3) {
+void StubCache::GenerateProbe(MacroAssembler* masm, Code::Kind ic_kind,
+ Code::Flags flags, bool leave_frame,
+ Register receiver, Register name,
+ Register scratch, Register extra, Register extra2,
+ Register extra3) {
Label miss;
// Assert that code is valid. The multiplying code relies on the entry size
@@ -159,8 +181,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
DCHECK(kCacheIndexShift == kPointerSizeLog2);
// Probe the primary table.
- ProbeTable(isolate(), masm, flags, leave_frame, kPrimary, name, receiver,
- offset, extra);
+ ProbeTable(isolate(), masm, ic_kind, flags, leave_frame, kPrimary, name,
+ receiver, offset, extra);
// Primary miss: Compute hash for secondary probe.
__ mov(offset, FieldOperand(name, Name::kHashFieldOffset));
@@ -172,8 +194,8 @@ void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
__ and_(offset, (kSecondaryTableSize - 1) << kCacheIndexShift);
// Probe the secondary table.
- ProbeTable(isolate(), masm, flags, leave_frame, kSecondary, name, receiver,
- offset, extra);
+ ProbeTable(isolate(), masm, ic_kind, flags, leave_frame, kSecondary, name,
+ receiver, offset, extra);
// Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system.