Commit 336d6e42 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[ic] Turn load global from prototype chain into data handler

BUG=

Change-Id: Ic63c63a312c6282814c14176d982b8c825ba6dc4
Reviewed-on: https://chromium-review.googlesource.com/454756
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43816}
parent db467667
......@@ -2937,6 +2937,10 @@ Node* CodeStubAssembler::IsBoolean(Node* object) {
return IsBooleanMap(LoadMap(object));
}
Node* CodeStubAssembler::IsPropertyCell(Node* object) {
return IsPropertyCellMap(LoadMap(object));
}
Node* CodeStubAssembler::IsHeapNumber(Node* object) {
return IsHeapNumberMap(LoadMap(object));
}
......
......@@ -41,6 +41,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(MinusZeroValue, MinusZero) \
V(NanValue, Nan) \
V(NullValue, Null) \
V(GlobalPropertyCellMap, PropertyCellMap) \
V(SymbolMap, SymbolMap) \
V(TheHoleValue, TheHole) \
V(TrueValue, True) \
......@@ -700,6 +701,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* IsDeprecatedMap(Node* map);
Node* IsCallable(Node* object);
Node* IsBoolean(Node* object);
Node* IsPropertyCell(Node* object);
Node* IsHeapNumber(Node* object);
Node* IsName(Node* object);
Node* IsSymbol(Node* object);
......
......@@ -785,7 +785,7 @@ class RuntimeCallTimer final {
V(LoadIC_LoadFieldDH) \
V(LoadIC_LoadFieldFromPrototypeDH) \
V(LoadIC_LoadField) \
V(LoadIC_LoadGlobal) \
V(LoadIC_LoadGlobalFromPrototypeDH) \
V(LoadIC_LoadInterceptorDH) \
V(LoadIC_LoadNonMaskingInterceptorDH) \
V(LoadIC_LoadInterceptorFromPrototypeDH) \
......
......@@ -297,7 +297,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
}
Label constant(this), field(this), normal(this, Label::kDeferred),
interceptor(this, Label::kDeferred), nonexistent(this);
interceptor(this, Label::kDeferred), nonexistent(this),
global(this, Label::kDeferred);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kField)), &field);
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kConstant)),
......@@ -306,7 +307,10 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNonExistent)),
&nonexistent);
Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNormal)), &normal,
GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kNormal)),
&normal);
Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kGlobal)), &global,
&interceptor);
Bind(&field);
......@@ -369,6 +373,19 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
}
}
Bind(&global);
{
CSA_ASSERT(this, IsPropertyCell(holder));
// Ensure the property cell doesn't contain the hole.
Node* value = LoadObjectField(holder, PropertyCell::kValueOffset);
Node* details =
LoadAndUntagToWord32ObjectField(holder, PropertyCell::kDetailsOffset);
GotoIf(IsTheHole(value), miss);
exit_point->Return(
CallGetterIfAccessor(value, details, p->context, p->receiver, miss));
}
Bind(&interceptor);
{
Comment("load_interceptor");
......@@ -1295,9 +1312,8 @@ void AccessorAssembler::CheckPrototype(Node* prototype_cell, Node* name,
Label if_property_cell(this), if_dictionary_object(this);
// |maybe_prototype| is either a PropertyCell or a slow-mode prototype.
Branch(WordEqual(LoadMap(maybe_prototype),
LoadRoot(Heap::kGlobalPropertyCellMapRootIndex)),
&if_property_cell, &if_dictionary_object);
Branch(IsPropertyCell(maybe_prototype), &if_property_cell,
&if_dictionary_object);
Bind(&if_dictionary_object);
{
......@@ -1310,7 +1326,7 @@ void AccessorAssembler::CheckPrototype(Node* prototype_cell, Node* name,
{
// Ensure the property cell still contains the hole.
Node* value = LoadObjectField(maybe_prototype, PropertyCell::kValueOffset);
GotoIf(WordNotEqual(value, LoadRoot(Heap::kTheHoleValueRootIndex)), miss);
GotoIfNot(IsTheHole(value), miss);
Goto(&done);
}
......@@ -1867,7 +1883,7 @@ void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
// Load value or try handler case if the {weak_cell} is cleared.
Node* property_cell = LoadWeakCellValue(weak_cell, try_handler);
CSA_ASSERT(this, HasInstanceType(property_cell, PROPERTY_CELL_TYPE));
CSA_ASSERT(this, IsPropertyCell(property_cell));
Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset);
GotoIf(WordEqual(value, TheHoleConstant()), miss);
......
......@@ -323,8 +323,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -389,15 +388,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......@@ -465,41 +463,6 @@ 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, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
__ LoadWeakValue(result, weak_cell, &miss);
__ ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
__ b(eq, &miss);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1, r1, r3);
if (IC::ICUseVector(kind())) {
DiscardVectorAndSlot();
}
__ Ret();
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -277,39 +277,6 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
#define __ ACCESS_MASM(masm())
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
if (IC::ICUseVector(kind())) {
PushVectorAndSlot();
}
FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
__ LoadWeakValue(result, weak_cell, &miss);
__ Ldr(result, FieldMemOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
__ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1, x1, x3);
if (IC::ICUseVector(kind())) {
DiscardVectorAndSlot();
}
__ Ret();
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
Register NamedStoreHandlerCompiler::value() {
return StoreDescriptor::ValueRegister();
}
......@@ -350,8 +317,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// object_reg and holder_reg registers can alias.
......@@ -416,15 +382,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......
......@@ -39,11 +39,9 @@ Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind,
#define __ ACCESS_MASM(masm())
Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
Handle<Name> name,
Label* miss,
ReturnHolder return_what) {
Label* miss) {
if (map()->IsPrimitiveMap() || map()->IsJSGlobalProxyMap()) {
// If the receiver is a global proxy and if we get to this point then
// the compile-time (current) native context has access to global proxy's
......@@ -60,7 +58,7 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
// Check that the maps starting from the prototype haven't changed.
return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name,
miss, return_what);
miss);
}
......@@ -68,8 +66,7 @@ Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
// miss.
Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
Handle<Name> name,
Label* miss,
ReturnHolder return_what) {
Label* miss) {
if (map()->IsJSGlobalProxyMap()) {
Handle<Context> native_context = isolate()->native_context();
Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
......@@ -77,7 +74,7 @@ Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
}
return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
miss, return_what);
miss);
}
......@@ -86,7 +83,7 @@ Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
if (IC::ShouldPushPopSlotAndVector(kind())) {
PushVectorAndSlot();
}
Register reg = FrontendHeader(receiver(), name, &miss, RETURN_HOLDER);
Register reg = FrontendHeader(receiver(), name, &miss);
FrontendFooter(name, &miss);
// The footer consumes the vector and slot from the stack if miss occurs.
if (IC::ShouldPushPopSlotAndVector(kind())) {
......
......@@ -13,8 +13,6 @@ namespace internal {
class CallOptimization;
enum ReturnHolder { RETURN_HOLDER, DONT_RETURN_ANYTHING };
class PropertyHandlerCompiler : public PropertyAccessCompiler {
public:
static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind,
......@@ -30,7 +28,7 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
virtual ~PropertyHandlerCompiler() {}
virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Label* miss, ReturnHolder return_what) {
Label* miss) {
UNREACHABLE();
return receiver();
}
......@@ -104,13 +102,10 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
// holder_reg.
Register CheckPrototypes(Register object_reg, Register holder_reg,
Register scratch1, Register scratch2,
Handle<Name> name, Label* miss,
ReturnHolder return_what);
Handle<Name> name, Label* miss);
Handle<Code> GetCode(Code::Kind kind, Handle<Name> name);
void set_holder(Handle<JSObject> holder) { holder_ = holder; }
Handle<Map> map() const { return map_; }
void set_map(Handle<Map> map) { map_ = map; }
Handle<JSObject> holder() const { return holder_; }
private:
......@@ -136,9 +131,6 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
Handle<Code> CompileLoadViaGetter(Handle<Name> name, int accessor_index,
int expected_arguments);
Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
bool is_configurable);
static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
Register receiver, Register holder,
int accessor_index, int expected_arguments,
......@@ -151,7 +143,7 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
protected:
virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Label* miss, ReturnHolder return_what);
Label* miss);
virtual void FrontendFooter(Handle<Name> name, Label* miss);
......@@ -202,7 +194,7 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
protected:
virtual Register FrontendHeader(Register object_reg, Handle<Name> name,
Label* miss, ReturnHolder return_what);
Label* miss);
virtual void FrontendFooter(Handle<Name> name, Label* miss);
void GenerateRestoreName(Label* label, Handle<Name> name);
......
......@@ -18,6 +18,11 @@ Handle<Smi> LoadHandler::LoadNormal(Isolate* isolate) {
return handle(Smi::FromInt(config), isolate);
}
Handle<Smi> LoadHandler::LoadGlobal(Isolate* isolate) {
int config = KindBits::encode(kGlobal);
return handle(Smi::FromInt(config), isolate);
}
Handle<Smi> LoadHandler::LoadInterceptor(Isolate* isolate) {
int config = KindBits::encode(kInterceptor);
return handle(Smi::FromInt(config), isolate);
......
......@@ -19,6 +19,7 @@ class LoadHandler {
enum Kind {
kElement,
kNormal,
kGlobal,
kField,
kConstant,
kInterceptor,
......@@ -91,6 +92,9 @@ class LoadHandler {
// Creates a Smi-handler for loading a property from a slow object.
static inline Handle<Smi> LoadNormal(Isolate* isolate);
// Creates a Smi-handler for loading a property from a global object.
static inline Handle<Smi> LoadGlobal(Isolate* isolate);
// Creates a Smi-handler for loading a property from an object with an
// interceptor.
static inline Handle<Smi> LoadInterceptor(Isolate* isolate);
......
......@@ -324,8 +324,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -390,15 +389,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......@@ -476,43 +474,6 @@ Register NamedStoreHandlerCompiler::value() {
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
if (IC::ShouldPushPopSlotAndVector(kind())) {
PushVectorAndSlot();
}
FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
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) {
__ cmp(result, factory()->the_hole_value());
__ j(equal, &miss);
} else if (FLAG_debug_code) {
__ cmp(result, factory()->the_hole_value());
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1);
// The code above already loads the result into the return register.
if (IC::ShouldPushPopSlotAndVector(kind())) {
DiscardVectorAndSlot();
}
__ ret(0);
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -316,8 +316,7 @@ static void LookupForRead(LookupIterator* it) {
break;
}
case LookupIterator::ACCESS_CHECK:
// PropertyHandlerCompiler::CheckPrototypes() knows how to emit
// access checks for global proxies.
// ICs know how to perform access checks on global proxies.
if (it->GetHolder<JSObject>()->IsJSGlobalProxy() && it->HasAccess()) {
break;
}
......@@ -962,6 +961,20 @@ int GetPrototypeCheckCount(Isolate* isolate, Handle<Map> receiver_map,
Handle<FixedArray>(), 0);
}
Handle<WeakCell> HolderCell(Isolate* isolate, Handle<JSObject> holder,
Handle<Name> name) {
if (holder->IsJSGlobalObject()) {
Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(holder);
GlobalDictionary* dict = global->global_dictionary();
int number = dict->FindEntry(name);
DCHECK_NE(NameDictionary::kNotFound, number);
Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(number)),
isolate);
return isolate->factory()->NewWeakCell(cell);
}
return Map::GetOrCreatePrototypeWeakCell(holder, isolate);
}
} // namespace
Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
......@@ -987,8 +1000,7 @@ Handle<Object> LoadIC::LoadFromPrototype(Handle<Map> receiver_map,
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
DCHECK(!validity_cell.is_null());
Handle<WeakCell> holder_cell =
Map::GetOrCreatePrototypeWeakCell(holder, isolate());
Handle<WeakCell> holder_cell = HolderCell(isolate(), holder, name);
if (checks_count == 0) {
return isolate()->factory()->NewTuple3(holder_cell, smi_handler,
......@@ -1386,13 +1398,19 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
DCHECK_EQ(kData, lookup->property_details().kind());
Handle<Smi> smi_handler;
if (lookup->is_dictionary_holder()) {
smi_handler = LoadHandler::LoadNormal(isolate());
if (receiver_is_holder) {
DCHECK(!holder->IsJSGlobalObject());
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
return smi_handler;
}
if (holder->IsJSGlobalObject()) {
break; // Custom-compiled handler.
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobalFromPrototypeDH);
smi_handler = LoadHandler::LoadGlobal(isolate());
} else {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
}
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalDH);
smi_handler = LoadHandler::LoadNormal(isolate());
if (receiver_is_holder) return smi_handler;
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadNormalFromPrototypeDH);
} else if (lookup->property_details().location() == kField) {
FieldIndex field = lookup->GetFieldIndex();
......@@ -1446,10 +1464,6 @@ Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup,
Handle<Map> map = receiver_map();
switch (lookup->state()) {
case LookupIterator::INTERCEPTOR:
UNREACHABLE();
break;
case LookupIterator::ACCESSOR: {
#ifdef DEBUG
int object_offset;
......@@ -1485,17 +1499,8 @@ Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup,
lookup->name(), lookup->GetAccessorIndex(), expected_arguments);
}
case LookupIterator::DATA: {
DCHECK(lookup->is_dictionary_holder());
DCHECK(holder->IsJSGlobalObject());
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadGlobal);
NamedLoadHandlerCompiler compiler(isolate(), map, holder, cache_holder);
Handle<PropertyCell> cell = lookup->GetPropertyCell();
Handle<Code> code = compiler.CompileLoadGlobal(cell, lookup->name(),
lookup->IsConfigurable());
return code;
}
case LookupIterator::INTERCEPTOR:
case LookupIterator::DATA:
case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::ACCESS_CHECK:
case LookupIterator::JSPROXY:
......
......@@ -308,8 +308,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -374,15 +373,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......@@ -448,42 +446,6 @@ 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, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
__ LoadWeakValue(result, weak_cell, &miss);
__ lw(result, FieldMemOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&miss, eq, result, Operand(at));
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1, a1, a3);
if (IC::ICUseVector(kind())) {
DiscardVectorAndSlot();
}
__ Ret(USE_DELAY_SLOT);
__ Move(v0, result); // Ensure the stub returns correct value.
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -308,8 +308,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -374,15 +373,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......@@ -448,42 +446,6 @@ 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, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
__ LoadWeakValue(result, weak_cell, &miss);
__ ld(result, FieldMemOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ Branch(&miss, eq, result, Operand(at));
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1, a1, a3);
if (IC::ICUseVector(kind())) {
DiscardVectorAndSlot();
}
__ Ret(USE_DELAY_SLOT);
__ Move(v0, result); // Ensure the stub returns correct value.
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -318,8 +318,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -389,15 +388,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......@@ -464,41 +462,6 @@ 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, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
__ LoadWeakValue(result, weak_cell, &miss);
__ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(result, ip);
__ beq(&miss);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1, r4, r6);
if (IC::ICUseVector(kind())) {
DiscardVectorAndSlot();
}
__ Ret();
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -308,8 +308,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -374,15 +373,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
......@@ -445,39 +443,6 @@ Register NamedStoreHandlerCompiler::value() {
return StoreDescriptor::ValueRegister();
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
if (IC::ICUseVector(kind())) {
PushVectorAndSlot();
}
FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
__ LoadWeakValue(result, weak_cell, &miss);
__ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
__ beq(&miss);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1, r3, r5);
if (IC::ICUseVector(kind())) {
DiscardVectorAndSlot();
}
__ Ret();
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -312,8 +312,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -381,15 +380,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......@@ -457,43 +455,6 @@ 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, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell);
__ LoadWeakValue(result, weak_cell, &miss);
__ movp(result, FieldOperand(result, PropertyCell::kValueOffset));
// Check for deleted property if property can actually be deleted.
if (is_configurable) {
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
__ j(equal, &miss);
} else if (FLAG_debug_code) {
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1);
if (IC::ICUseVector(kind())) {
DiscardVectorAndSlot();
}
__ ret(0);
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
......@@ -324,8 +324,7 @@ void PropertyHandlerCompiler::GenerateAccessCheck(
Register PropertyHandlerCompiler::CheckPrototypes(
Register object_reg, Register holder_reg, Register scratch1,
Register scratch2, Handle<Name> name, Label* miss,
ReturnHolder return_what) {
Register scratch2, Handle<Name> name, Label* miss) {
Handle<Map> receiver_map = map();
// Make sure there's no overlap between holder and object registers.
......@@ -390,15 +389,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
// Log the check depth.
LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
bool return_holder = return_what == RETURN_HOLDER;
if (return_holder && depth != 0) {
if (depth != 0) {
Handle<WeakCell> weak_cell =
Map::GetOrCreatePrototypeWeakCell(current, isolate());
__ LoadWeakValue(reg, weak_cell, miss);
}
// Return the register containing the holder.
return return_holder ? reg : no_reg;
return reg;
}
......@@ -476,43 +474,6 @@ Register NamedStoreHandlerCompiler::value() {
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
Label miss;
if (IC::ShouldPushPopSlotAndVector(kind())) {
PushVectorAndSlot();
}
FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING);
// Get the value from the cell.
Register result = StoreDescriptor::ValueRegister();
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) {
__ cmp(result, factory()->the_hole_value());
__ j(equal, &miss);
} else if (FLAG_debug_code) {
__ cmp(result, factory()->the_hole_value());
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->ic_named_load_global_stub(), 1);
// The code above already loads the result into the return register.
if (IC::ShouldPushPopSlotAndVector(kind())) {
DiscardVectorAndSlot();
}
__ ret(0);
FrontendFooter(name, &miss);
// Return the generated code.
return GetCode(kind(), name);
}
#undef __
} // namespace internal
} // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment