MIPS: port Handlify CallStubCompiler::CompileCallField.
Port r9769 (db287698) BUG= TEST= Review URL: http://codereview.chromium.org/8394028 Patch from Paul Lind <plind44@gmail.com>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9782 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d022406db2
commit
77c4571aca
@ -6948,7 +6948,82 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
|
||||
void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
|
||||
Label* miss,
|
||||
Label* done,
|
||||
Register receiver,
|
||||
Register properties,
|
||||
Handle<String> name,
|
||||
Register scratch0) {
|
||||
// If names of slots in range from 1 to kProbes - 1 for the hash value are
|
||||
// not equal to the name and kProbes-th slot is not used (its name is the
|
||||
// undefined value), it guarantees the hash table doesn't contain the
|
||||
// property. It's true even if some slots represent deleted properties
|
||||
// (their names are the null value).
|
||||
for (int i = 0; i < kInlinedProbes; i++) {
|
||||
// scratch0 points to properties hash.
|
||||
// Compute the masked index: (hash + i + i * i) & mask.
|
||||
Register index = scratch0;
|
||||
// Capacity is smi 2^n.
|
||||
__ lw(index, FieldMemOperand(properties, kCapacityOffset));
|
||||
__ Subu(index, index, Operand(1));
|
||||
__ And(index, index, Operand(
|
||||
Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
|
||||
|
||||
// Scale the index by multiplying by the entry size.
|
||||
ASSERT(StringDictionary::kEntrySize == 3);
|
||||
__ sll(at, index, 1);
|
||||
__ Addu(index, index, at);
|
||||
|
||||
Register entity_name = scratch0;
|
||||
// Having undefined at this place means the name is not contained.
|
||||
ASSERT_EQ(kSmiTagSize, 1);
|
||||
Register tmp = properties;
|
||||
__ sll(tmp, index, 1);
|
||||
__ Addu(tmp, properties, tmp);
|
||||
__ lw(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
|
||||
|
||||
ASSERT(!tmp.is(entity_name));
|
||||
__ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
|
||||
__ Branch(done, eq, entity_name, Operand(tmp));
|
||||
|
||||
if (i != kInlinedProbes - 1) {
|
||||
// Stop if found the property.
|
||||
__ Branch(miss, eq, entity_name, Operand(Handle<String>(name)));
|
||||
|
||||
// Check if the entry name is not a symbol.
|
||||
__ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
|
||||
__ lbu(entity_name,
|
||||
FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
|
||||
__ And(tmp, entity_name, Operand(kIsSymbolMask));
|
||||
__ Branch(miss, eq, tmp, Operand(zero_reg));
|
||||
|
||||
// Restore the properties.
|
||||
__ lw(properties,
|
||||
FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
}
|
||||
}
|
||||
|
||||
const int spill_mask =
|
||||
(ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() |
|
||||
a2.bit() | a1.bit() | a0.bit() | v0.bit());
|
||||
|
||||
__ MultiPush(spill_mask);
|
||||
__ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
__ li(a1, Operand(Handle<String>(name)));
|
||||
StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
|
||||
__ CallStub(&stub);
|
||||
__ mov(at, v0);
|
||||
__ MultiPop(spill_mask);
|
||||
|
||||
__ Branch(done, eq, at, Operand(zero_reg));
|
||||
__ Branch(miss, ne, at, Operand(zero_reg));
|
||||
}
|
||||
|
||||
|
||||
// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
||||
// handlified.
|
||||
MaybeObject* StringDictionaryLookupStub::TryGenerateNegativeLookup(
|
||||
MacroAssembler* masm,
|
||||
Label* miss,
|
||||
Label* done,
|
||||
@ -6974,8 +7049,7 @@ MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
|
||||
// Scale the index by multiplying by the entry size.
|
||||
ASSERT(StringDictionary::kEntrySize == 3);
|
||||
// index *= 3.
|
||||
__ mov(at, index);
|
||||
__ sll(index, index, 1);
|
||||
__ sll(at, index, 1);
|
||||
__ Addu(index, index, at);
|
||||
|
||||
Register entity_name = scratch0;
|
||||
@ -7010,7 +7084,7 @@ MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
|
||||
|
||||
const int spill_mask =
|
||||
(ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() |
|
||||
a2.bit() | a1.bit() | a0.bit());
|
||||
a2.bit() | a1.bit() | a0.bit() | v0.bit());
|
||||
|
||||
__ MultiPush(spill_mask);
|
||||
__ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
@ -7018,10 +7092,11 @@ MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
|
||||
StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
|
||||
MaybeObject* result = masm->TryCallStub(&stub);
|
||||
if (result->IsFailure()) return result;
|
||||
__ mov(at, v0);
|
||||
__ MultiPop(spill_mask);
|
||||
|
||||
__ Branch(done, eq, v0, Operand(zero_reg));
|
||||
__ Branch(miss, ne, v0, Operand(zero_reg));
|
||||
__ Branch(done, eq, at, Operand(zero_reg));
|
||||
__ Branch(miss, ne, at, Operand(zero_reg));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -7067,8 +7142,7 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
|
||||
ASSERT(StringDictionary::kEntrySize == 3);
|
||||
// scratch2 = scratch2 * 3.
|
||||
|
||||
__ mov(at, scratch2);
|
||||
__ sll(scratch2, scratch2, 1);
|
||||
__ sll(at, scratch2, 1);
|
||||
__ Addu(scratch2, scratch2, at);
|
||||
|
||||
// Check if the key is identical to the name.
|
||||
@ -7080,19 +7154,26 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
|
||||
|
||||
const int spill_mask =
|
||||
(ra.bit() | t2.bit() | t1.bit() | t0.bit() |
|
||||
a3.bit() | a2.bit() | a1.bit() | a0.bit()) &
|
||||
a3.bit() | a2.bit() | a1.bit() | a0.bit() | v0.bit()) &
|
||||
~(scratch1.bit() | scratch2.bit());
|
||||
|
||||
__ MultiPush(spill_mask);
|
||||
__ Move(a0, elements);
|
||||
__ Move(a1, name);
|
||||
if (name.is(a0)) {
|
||||
ASSERT(!elements.is(a1));
|
||||
__ Move(a1, name);
|
||||
__ Move(a0, elements);
|
||||
} else {
|
||||
__ Move(a0, elements);
|
||||
__ Move(a1, name);
|
||||
}
|
||||
StringDictionaryLookupStub stub(POSITIVE_LOOKUP);
|
||||
__ CallStub(&stub);
|
||||
__ mov(scratch2, a2);
|
||||
__ mov(at, v0);
|
||||
__ MultiPop(spill_mask);
|
||||
|
||||
__ Branch(done, ne, v0, Operand(zero_reg));
|
||||
__ Branch(miss, eq, v0, Operand(zero_reg));
|
||||
__ Branch(done, ne, at, Operand(zero_reg));
|
||||
__ Branch(miss, eq, at, Operand(zero_reg));
|
||||
}
|
||||
|
||||
|
||||
|
@ -799,7 +799,17 @@ class StringDictionaryLookupStub: public CodeStub {
|
||||
|
||||
void Generate(MacroAssembler* masm);
|
||||
|
||||
MUST_USE_RESULT static MaybeObject* GenerateNegativeLookup(
|
||||
static void GenerateNegativeLookup(MacroAssembler* masm,
|
||||
Label* miss,
|
||||
Label* done,
|
||||
Register receiver,
|
||||
Register properties,
|
||||
Handle<String> name,
|
||||
Register scratch0);
|
||||
|
||||
// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
||||
// handlified.
|
||||
MUST_USE_RESULT static MaybeObject* TryGenerateNegativeLookup(
|
||||
MacroAssembler* masm,
|
||||
Label* miss,
|
||||
Label* done,
|
||||
|
@ -99,7 +99,61 @@ static void ProbeTable(Isolate* isolate,
|
||||
// must always call a backup property check that is complete.
|
||||
// This function is safe to call if the receiver has fast properties.
|
||||
// Name must be a symbol and receiver must be a heap object.
|
||||
MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup(
|
||||
static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
|
||||
Label* miss_label,
|
||||
Register receiver,
|
||||
Handle<String> name,
|
||||
Register scratch0,
|
||||
Register scratch1) {
|
||||
ASSERT(name->IsSymbol());
|
||||
Counters* counters = masm->isolate()->counters();
|
||||
__ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
|
||||
__ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||
|
||||
Label done;
|
||||
|
||||
const int kInterceptorOrAccessCheckNeededMask =
|
||||
(1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
|
||||
|
||||
// Bail out if the receiver has a named interceptor or requires access checks.
|
||||
Register map = scratch1;
|
||||
__ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
||||
__ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
|
||||
__ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
|
||||
__ Branch(miss_label, ne, scratch0, Operand(zero_reg));
|
||||
|
||||
// Check that receiver is a JSObject.
|
||||
__ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
||||
__ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
|
||||
|
||||
// Load properties array.
|
||||
Register properties = scratch0;
|
||||
__ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
// Check that the properties array is a dictionary.
|
||||
__ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
||||
Register tmp = properties;
|
||||
__ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
|
||||
__ Branch(miss_label, ne, map, Operand(tmp));
|
||||
|
||||
// Restore the temporarily used register.
|
||||
__ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
|
||||
|
||||
StringDictionaryLookupStub::GenerateNegativeLookup(masm,
|
||||
miss_label,
|
||||
&done,
|
||||
receiver,
|
||||
properties,
|
||||
name,
|
||||
scratch1);
|
||||
__ bind(&done);
|
||||
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||
}
|
||||
|
||||
|
||||
// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
||||
// handlified.
|
||||
MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup(
|
||||
MacroAssembler* masm,
|
||||
Label* miss_label,
|
||||
Register receiver,
|
||||
@ -140,7 +194,7 @@ MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup(
|
||||
// Restore the temporarily used register.
|
||||
__ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
||||
|
||||
MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup(
|
||||
MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup(
|
||||
masm,
|
||||
miss_label,
|
||||
&done,
|
||||
@ -261,8 +315,10 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
||||
// are loaded directly otherwise the property is loaded from the properties
|
||||
// fixed array.
|
||||
void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
|
||||
Register dst, Register src,
|
||||
JSObject* holder, int index) {
|
||||
Register dst,
|
||||
Register src,
|
||||
Handle<JSObject> holder,
|
||||
int index) {
|
||||
// Adjust for the number of properties stored in the holder.
|
||||
index -= holder->map()->inobject_properties();
|
||||
if (index < 0) {
|
||||
@ -482,7 +538,7 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
|
||||
|
||||
|
||||
static void GenerateCallFunction(MacroAssembler* masm,
|
||||
Object* object,
|
||||
Handle<Object> object,
|
||||
const ParameterCount& arguments,
|
||||
Label* miss,
|
||||
Code::ExtraICState extra_ic_state) {
|
||||
@ -878,7 +934,25 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
||||
// Generate code to check that a global property cell is empty. Create
|
||||
// the property cell at compilation time if no cell exists for the
|
||||
// property.
|
||||
MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
|
||||
static void GenerateCheckPropertyCell(MacroAssembler* masm,
|
||||
Handle<GlobalObject> global,
|
||||
Handle<String> name,
|
||||
Register scratch,
|
||||
Label* miss) {
|
||||
Handle<JSGlobalPropertyCell> cell =
|
||||
GlobalObject::EnsurePropertyCell(global, name);
|
||||
ASSERT(cell->value()->IsTheHole());
|
||||
__ li(scratch, Operand(cell));
|
||||
__ lw(scratch,
|
||||
FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
|
||||
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
||||
__ Branch(miss, ne, scratch, Operand(at));
|
||||
}
|
||||
|
||||
|
||||
// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
||||
// handlified.
|
||||
MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell(
|
||||
MacroAssembler* masm,
|
||||
GlobalObject* global,
|
||||
String* name,
|
||||
@ -901,7 +975,29 @@ MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
|
||||
|
||||
// Calls GenerateCheckPropertyCell for each global object in the prototype chain
|
||||
// from object to (but not including) holder.
|
||||
MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells(
|
||||
static void GenerateCheckPropertyCells(MacroAssembler* masm,
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<String> name,
|
||||
Register scratch,
|
||||
Label* miss) {
|
||||
Handle<JSObject> current = object;
|
||||
while (!current.is_identical_to(holder)) {
|
||||
if (current->IsGlobalObject()) {
|
||||
GenerateCheckPropertyCell(masm,
|
||||
Handle<GlobalObject>::cast(current),
|
||||
name,
|
||||
scratch,
|
||||
miss);
|
||||
}
|
||||
current = Handle<JSObject>(JSObject::cast(current->GetPrototype()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
||||
// handlified.
|
||||
MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells(
|
||||
MacroAssembler* masm,
|
||||
JSObject* object,
|
||||
JSObject* holder,
|
||||
@ -912,7 +1008,7 @@ MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells(
|
||||
while (current != holder) {
|
||||
if (current->IsGlobalObject()) {
|
||||
// Returns a cell or a failure.
|
||||
MaybeObject* result = GenerateCheckPropertyCell(
|
||||
MaybeObject* result = TryGenerateCheckPropertyCell(
|
||||
masm,
|
||||
GlobalObject::cast(current),
|
||||
name,
|
||||
@ -1047,6 +1143,108 @@ static void GenerateUInt2Double(MacroAssembler* masm,
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
|
||||
Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
||||
Register object_reg,
|
||||
Handle<JSObject> holder,
|
||||
Register holder_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Handle<String> name,
|
||||
int save_at_depth,
|
||||
Label* miss) {
|
||||
// Make sure there's no overlap between holder and object registers.
|
||||
ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
|
||||
ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
|
||||
&& !scratch2.is(scratch1));
|
||||
|
||||
// Keep track of the current object in register reg.
|
||||
Register reg = object_reg;
|
||||
int depth = 0;
|
||||
|
||||
if (save_at_depth == depth) {
|
||||
__ sw(reg, MemOperand(sp));
|
||||
}
|
||||
|
||||
// Check the maps in the prototype chain.
|
||||
// Traverse the prototype chain from the object and do map checks.
|
||||
Handle<JSObject> current = object;
|
||||
while (!current.is_identical_to(holder)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
|
||||
|
||||
Handle<JSObject> prototype(JSObject::cast(current->GetPrototype()));
|
||||
if (!current->HasFastProperties() &&
|
||||
!current->IsJSGlobalObject() &&
|
||||
!current->IsJSGlobalProxy()) {
|
||||
if (!name->IsSymbol()) {
|
||||
name = factory()->LookupSymbol(name);
|
||||
}
|
||||
ASSERT(current->property_dictionary()->FindEntry(*name) ==
|
||||
StringDictionary::kNotFound);
|
||||
|
||||
GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
|
||||
scratch1, scratch2);
|
||||
|
||||
__ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
||||
reg = holder_reg; // From now on the object will be in holder_reg.
|
||||
__ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
|
||||
} else {
|
||||
Handle<Map> current_map(current->map());
|
||||
__ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
||||
// Branch on the result of the map check.
|
||||
__ Branch(miss, ne, scratch1, Operand(current_map));
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
if (current->IsJSGlobalProxy()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, miss);
|
||||
}
|
||||
reg = holder_reg; // From now on the object will be in holder_reg.
|
||||
|
||||
if (heap()->InNewSpace(*prototype)) {
|
||||
// The prototype is in new space; we cannot store a reference to it
|
||||
// in the code. Load it from the map.
|
||||
__ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
|
||||
} else {
|
||||
// The prototype is in old space; load it directly.
|
||||
__ li(reg, Operand(prototype));
|
||||
}
|
||||
}
|
||||
|
||||
if (save_at_depth == depth) {
|
||||
__ sw(reg, MemOperand(sp));
|
||||
}
|
||||
|
||||
// Go to the next object in the prototype chain.
|
||||
current = prototype;
|
||||
}
|
||||
|
||||
// Log the check depth.
|
||||
LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
|
||||
|
||||
// Check the holder map.
|
||||
__ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
||||
__ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map())));
|
||||
|
||||
// Perform security check for access to the global object.
|
||||
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
|
||||
if (holder->IsJSGlobalProxy()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch1, miss);
|
||||
}
|
||||
|
||||
// If we've skipped any global objects, it's not enough to verify that
|
||||
// their maps haven't changed. We also need to check that the property
|
||||
// cell for the property is still empty.
|
||||
GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
|
||||
|
||||
// Return the register containing the holder.
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
Register StubCompiler::CheckPrototypes(JSObject* object,
|
||||
Register object_reg,
|
||||
JSObject* holder,
|
||||
@ -1096,12 +1294,14 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
|
||||
ASSERT(current->property_dictionary()->FindEntry(name) ==
|
||||
StringDictionary::kNotFound);
|
||||
|
||||
MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(),
|
||||
miss,
|
||||
reg,
|
||||
name,
|
||||
scratch1,
|
||||
scratch2);
|
||||
MaybeObject* negative_lookup =
|
||||
TryGenerateDictionaryNegativeLookup(masm(),
|
||||
miss,
|
||||
reg,
|
||||
name,
|
||||
scratch1,
|
||||
scratch2);
|
||||
|
||||
if (negative_lookup->IsFailure()) {
|
||||
set_failure(Failure::cast(negative_lookup));
|
||||
return reg;
|
||||
@ -1166,18 +1366,18 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
|
||||
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
|
||||
if (holder->IsJSGlobalProxy()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch1, miss);
|
||||
};
|
||||
}
|
||||
|
||||
// If we've skipped any global objects, it's not enough to verify
|
||||
// that their maps haven't changed. We also need to check that the
|
||||
// property cell for the property is still empty.
|
||||
|
||||
MaybeObject* result = GenerateCheckPropertyCells(masm(),
|
||||
object,
|
||||
holder,
|
||||
name,
|
||||
scratch1,
|
||||
miss);
|
||||
MaybeObject* result = TryGenerateCheckPropertyCells(masm(),
|
||||
object,
|
||||
holder,
|
||||
name,
|
||||
scratch1,
|
||||
miss);
|
||||
if (result->IsFailure()) set_failure(Failure::cast(result));
|
||||
|
||||
// Return the register containing the holder.
|
||||
@ -1202,7 +1402,7 @@ void StubCompiler::GenerateLoadField(JSObject* object,
|
||||
Register reg =
|
||||
CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
|
||||
name, miss);
|
||||
GenerateFastPropertyLoad(masm(), v0, reg, holder, index);
|
||||
GenerateFastPropertyLoad(masm(), v0, reg, Handle<JSObject>(holder), index);
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
@ -1390,7 +1590,8 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
||||
// We found FIELD property in prototype chain of interceptor's holder.
|
||||
// Retrieve a field from field's holder.
|
||||
GenerateFastPropertyLoad(masm(), v0, holder_reg,
|
||||
lookup->holder(), lookup->GetFieldIndex());
|
||||
Handle<JSObject>(lookup->holder()),
|
||||
lookup->GetFieldIndex());
|
||||
__ Ret();
|
||||
} else {
|
||||
// We found CALLBACKS property in prototype chain of interceptor's
|
||||
@ -1440,9 +1641,9 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
||||
}
|
||||
|
||||
|
||||
void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
|
||||
void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
|
||||
if (kind_ == Code::KEYED_CALL_IC) {
|
||||
__ Branch(miss, ne, a2, Operand(Handle<String>(name)));
|
||||
__ Branch(miss, ne, a2, Operand(name));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1499,7 +1700,18 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* CallStubCompiler::GenerateMissBranch() {
|
||||
void CallStubCompiler::GenerateMissBranch() {
|
||||
Handle<Code> code =
|
||||
isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
extra_state_);
|
||||
__ Jump(code, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
||||
// handlified.
|
||||
MaybeObject* CallStubCompiler::TryGenerateMissBranch() {
|
||||
MaybeObject* maybe_obj =
|
||||
isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(),
|
||||
kind_,
|
||||
@ -1511,10 +1723,10 @@ MaybeObject* CallStubCompiler::GenerateMissBranch() {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
|
||||
JSObject* holder,
|
||||
Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
|
||||
Handle<JSObject> holder,
|
||||
int index,
|
||||
String* name) {
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a2 : name
|
||||
// -- ra : return address
|
||||
@ -1538,8 +1750,7 @@ MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
GenerateMissBranch();
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(FIELD, name);
|
||||
@ -1564,7 +1775,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
|
||||
Label miss;
|
||||
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
Register receiver = a1;
|
||||
|
||||
@ -1730,11 +1941,11 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(function);
|
||||
return TryGetCode(function);
|
||||
}
|
||||
|
||||
|
||||
@ -1759,7 +1970,7 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
|
||||
Register receiver = a1;
|
||||
Register elements = a3;
|
||||
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
// Get the receiver from the stack.
|
||||
const int argc = arguments().immediate();
|
||||
@ -1819,11 +2030,11 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(function);
|
||||
return TryGetCode(function);
|
||||
}
|
||||
|
||||
|
||||
@ -1858,7 +2069,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
GenerateNameCheck(name, &name_miss);
|
||||
GenerateNameCheck(Handle<String>(name), &name_miss);
|
||||
|
||||
// Check that the maps starting from the prototype haven't changed.
|
||||
GenerateDirectLoadGlobalFunctionPrototype(masm(),
|
||||
@ -1906,11 +2117,11 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
// Restore function name in a2.
|
||||
__ li(a2, Handle<String>(name));
|
||||
__ bind(&name_miss);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(function);
|
||||
return TryGetCode(function);
|
||||
}
|
||||
|
||||
|
||||
@ -1944,7 +2155,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
GenerateNameCheck(name, &name_miss);
|
||||
GenerateNameCheck(Handle<String>(name), &name_miss);
|
||||
|
||||
// Check that the maps starting from the prototype haven't changed.
|
||||
GenerateDirectLoadGlobalFunctionPrototype(masm(),
|
||||
@ -1994,11 +2205,11 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
||||
// Restore function name in a2.
|
||||
__ li(a2, Handle<String>(name));
|
||||
__ bind(&name_miss);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(function);
|
||||
return TryGetCode(function);
|
||||
}
|
||||
|
||||
|
||||
@ -2023,7 +2234,7 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
|
||||
|
||||
Label miss;
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
if (cell == NULL) {
|
||||
__ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
||||
@ -2066,11 +2277,11 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
|
||||
__ bind(&miss);
|
||||
// a2: function name.
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
|
||||
return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2098,7 +2309,7 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
|
||||
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
|
||||
|
||||
Label miss, slow;
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
if (cell == NULL) {
|
||||
__ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
||||
@ -2200,11 +2411,11 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
|
||||
|
||||
__ bind(&miss);
|
||||
// a2: function name.
|
||||
MaybeObject* obj = GenerateMissBranch();
|
||||
MaybeObject* obj = TryGenerateMissBranch();
|
||||
if (obj->IsFailure()) return obj;
|
||||
|
||||
// Return the generated code.
|
||||
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
|
||||
return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2228,7 +2439,7 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
|
||||
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
|
||||
|
||||
Label miss;
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
if (cell == NULL) {
|
||||
__ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
||||
@ -2302,11 +2513,11 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
|
||||
|
||||
__ bind(&miss);
|
||||
// a2: function name.
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
|
||||
return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2332,7 +2543,7 @@ MaybeObject* CallStubCompiler::CompileFastApiCall(
|
||||
|
||||
Label miss, miss_before_stack_reserved;
|
||||
|
||||
GenerateNameCheck(name, &miss_before_stack_reserved);
|
||||
GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved);
|
||||
|
||||
// Get the receiver from the stack.
|
||||
const int argc = arguments().immediate();
|
||||
@ -2357,11 +2568,11 @@ MaybeObject* CallStubCompiler::CompileFastApiCall(
|
||||
FreeSpaceForFastApiCall(masm());
|
||||
|
||||
__ bind(&miss_before_stack_reserved);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(function);
|
||||
return TryGetCode(function);
|
||||
}
|
||||
|
||||
|
||||
@ -2385,7 +2596,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
||||
|
||||
Label miss;
|
||||
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
// Get the receiver from the stack.
|
||||
const int argc = arguments().immediate();
|
||||
@ -2492,11 +2703,11 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(function);
|
||||
return TryGetCode(function);
|
||||
}
|
||||
|
||||
|
||||
@ -2510,7 +2721,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
|
||||
Label miss;
|
||||
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
// Get the number of arguments.
|
||||
const int argc = arguments().immediate();
|
||||
@ -2541,15 +2752,16 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
||||
// Restore receiver.
|
||||
__ lw(a0, MemOperand(sp, argc * kPointerSize));
|
||||
|
||||
GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
|
||||
GenerateCallFunction(masm(), Handle<Object>(object), arguments(), &miss,
|
||||
extra_state_);
|
||||
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(INTERCEPTOR, name);
|
||||
return TryGetCode(INTERCEPTOR, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2574,7 +2786,7 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
||||
|
||||
Label miss;
|
||||
|
||||
GenerateNameCheck(name, &miss);
|
||||
GenerateNameCheck(Handle<String>(name), &miss);
|
||||
|
||||
// Get the number of arguments.
|
||||
const int argc = arguments().immediate();
|
||||
@ -2610,11 +2822,11 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
__ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3);
|
||||
MaybeObject* maybe_result = GenerateMissBranch();
|
||||
MaybeObject* maybe_result = TryGenerateMissBranch();
|
||||
if (maybe_result->IsFailure()) return maybe_result;
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(NORMAL, name);
|
||||
return TryGetCode(NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
@ -2811,11 +3023,11 @@ MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
|
||||
// If the last object in the prototype chain is a global object,
|
||||
// check that the global property cell is empty.
|
||||
if (last->IsGlobalObject()) {
|
||||
MaybeObject* cell = GenerateCheckPropertyCell(masm(),
|
||||
GlobalObject::cast(last),
|
||||
name,
|
||||
a1,
|
||||
&miss);
|
||||
MaybeObject* cell = TryGenerateCheckPropertyCell(masm(),
|
||||
GlobalObject::cast(last),
|
||||
name,
|
||||
a1,
|
||||
&miss);
|
||||
if (cell->IsFailure()) {
|
||||
miss.Unuse();
|
||||
return cell;
|
||||
|
Loading…
Reference in New Issue
Block a user