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:
kmillikin@chromium.org 2011-10-26 08:32:37 +00:00
parent d022406db2
commit 77c4571aca
3 changed files with 387 additions and 84 deletions

View File

@ -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, MacroAssembler* masm,
Label* miss, Label* miss,
Label* done, Label* done,
@ -6974,8 +7049,7 @@ MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
// Scale the index by multiplying by the entry size. // Scale the index by multiplying by the entry size.
ASSERT(StringDictionary::kEntrySize == 3); ASSERT(StringDictionary::kEntrySize == 3);
// index *= 3. // index *= 3.
__ mov(at, index); __ sll(at, index, 1);
__ sll(index, index, 1);
__ Addu(index, index, at); __ Addu(index, index, at);
Register entity_name = scratch0; Register entity_name = scratch0;
@ -7010,7 +7084,7 @@ MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
const int spill_mask = const int spill_mask =
(ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() | (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); __ MultiPush(spill_mask);
__ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
@ -7018,10 +7092,11 @@ MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
StringDictionaryLookupStub stub(NEGATIVE_LOOKUP); StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
MaybeObject* result = masm->TryCallStub(&stub); MaybeObject* result = masm->TryCallStub(&stub);
if (result->IsFailure()) return result; if (result->IsFailure()) return result;
__ mov(at, v0);
__ MultiPop(spill_mask); __ MultiPop(spill_mask);
__ Branch(done, eq, v0, Operand(zero_reg)); __ Branch(done, eq, at, Operand(zero_reg));
__ Branch(miss, ne, v0, Operand(zero_reg)); __ Branch(miss, ne, at, Operand(zero_reg));
return result; return result;
} }
@ -7067,8 +7142,7 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
ASSERT(StringDictionary::kEntrySize == 3); ASSERT(StringDictionary::kEntrySize == 3);
// scratch2 = scratch2 * 3. // scratch2 = scratch2 * 3.
__ mov(at, scratch2); __ sll(at, scratch2, 1);
__ sll(scratch2, scratch2, 1);
__ Addu(scratch2, scratch2, at); __ Addu(scratch2, scratch2, at);
// Check if the key is identical to the name. // Check if the key is identical to the name.
@ -7080,19 +7154,26 @@ void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
const int spill_mask = const int spill_mask =
(ra.bit() | t2.bit() | t1.bit() | t0.bit() | (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()); ~(scratch1.bit() | scratch2.bit());
__ MultiPush(spill_mask); __ MultiPush(spill_mask);
__ Move(a0, elements); if (name.is(a0)) {
__ Move(a1, name); ASSERT(!elements.is(a1));
__ Move(a1, name);
__ Move(a0, elements);
} else {
__ Move(a0, elements);
__ Move(a1, name);
}
StringDictionaryLookupStub stub(POSITIVE_LOOKUP); StringDictionaryLookupStub stub(POSITIVE_LOOKUP);
__ CallStub(&stub); __ CallStub(&stub);
__ mov(scratch2, a2); __ mov(scratch2, a2);
__ mov(at, v0);
__ MultiPop(spill_mask); __ MultiPop(spill_mask);
__ Branch(done, ne, v0, Operand(zero_reg)); __ Branch(done, ne, at, Operand(zero_reg));
__ Branch(miss, eq, v0, Operand(zero_reg)); __ Branch(miss, eq, at, Operand(zero_reg));
} }

View File

@ -799,7 +799,17 @@ class StringDictionaryLookupStub: public CodeStub {
void Generate(MacroAssembler* masm); 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, MacroAssembler* masm,
Label* miss, Label* miss,
Label* done, Label* done,

View File

@ -99,7 +99,61 @@ static void ProbeTable(Isolate* isolate,
// must always call a backup property check that is complete. // must always call a backup property check that is complete.
// This function is safe to call if the receiver has fast properties. // This function is safe to call if the receiver has fast properties.
// Name must be a symbol and receiver must be a heap object. // 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, MacroAssembler* masm,
Label* miss_label, Label* miss_label,
Register receiver, Register receiver,
@ -140,7 +194,7 @@ MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup(
// Restore the temporarily used register. // Restore the temporarily used register.
__ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup( MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup(
masm, masm,
miss_label, miss_label,
&done, &done,
@ -261,8 +315,10 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
// are loaded directly otherwise the property is loaded from the properties // are loaded directly otherwise the property is loaded from the properties
// fixed array. // fixed array.
void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
Register dst, Register src, Register dst,
JSObject* holder, int index) { Register src,
Handle<JSObject> holder,
int index) {
// Adjust for the number of properties stored in the holder. // Adjust for the number of properties stored in the holder.
index -= holder->map()->inobject_properties(); index -= holder->map()->inobject_properties();
if (index < 0) { if (index < 0) {
@ -482,7 +538,7 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
static void GenerateCallFunction(MacroAssembler* masm, static void GenerateCallFunction(MacroAssembler* masm,
Object* object, Handle<Object> object,
const ParameterCount& arguments, const ParameterCount& arguments,
Label* miss, Label* miss,
Code::ExtraICState extra_ic_state) { 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 // Generate code to check that a global property cell is empty. Create
// the property cell at compilation time if no cell exists for the // the property cell at compilation time if no cell exists for the
// property. // 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, MacroAssembler* masm,
GlobalObject* global, GlobalObject* global,
String* name, String* name,
@ -901,7 +975,29 @@ MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
// Calls GenerateCheckPropertyCell for each global object in the prototype chain // Calls GenerateCheckPropertyCell for each global object in the prototype chain
// from object to (but not including) holder. // 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, MacroAssembler* masm,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
@ -912,7 +1008,7 @@ MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells(
while (current != holder) { while (current != holder) {
if (current->IsGlobalObject()) { if (current->IsGlobalObject()) {
// Returns a cell or a failure. // Returns a cell or a failure.
MaybeObject* result = GenerateCheckPropertyCell( MaybeObject* result = TryGenerateCheckPropertyCell(
masm, masm,
GlobalObject::cast(current), GlobalObject::cast(current),
name, name,
@ -1047,6 +1143,108 @@ static void GenerateUInt2Double(MacroAssembler* masm,
#define __ ACCESS_MASM(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 StubCompiler::CheckPrototypes(JSObject* object,
Register object_reg, Register object_reg,
JSObject* holder, JSObject* holder,
@ -1096,12 +1294,14 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
ASSERT(current->property_dictionary()->FindEntry(name) == ASSERT(current->property_dictionary()->FindEntry(name) ==
StringDictionary::kNotFound); StringDictionary::kNotFound);
MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), MaybeObject* negative_lookup =
miss, TryGenerateDictionaryNegativeLookup(masm(),
reg, miss,
name, reg,
scratch1, name,
scratch2); scratch1,
scratch2);
if (negative_lookup->IsFailure()) { if (negative_lookup->IsFailure()) {
set_failure(Failure::cast(negative_lookup)); set_failure(Failure::cast(negative_lookup));
return reg; return reg;
@ -1166,18 +1366,18 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
if (holder->IsJSGlobalProxy()) { if (holder->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(reg, scratch1, miss); __ CheckAccessGlobalProxy(reg, scratch1, miss);
}; }
// If we've skipped any global objects, it's not enough to verify // 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 // that their maps haven't changed. We also need to check that the
// property cell for the property is still empty. // property cell for the property is still empty.
MaybeObject* result = GenerateCheckPropertyCells(masm(), MaybeObject* result = TryGenerateCheckPropertyCells(masm(),
object, object,
holder, holder,
name, name,
scratch1, scratch1,
miss); miss);
if (result->IsFailure()) set_failure(Failure::cast(result)); if (result->IsFailure()) set_failure(Failure::cast(result));
// Return the register containing the holder. // Return the register containing the holder.
@ -1202,7 +1402,7 @@ void StubCompiler::GenerateLoadField(JSObject* object,
Register reg = Register reg =
CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
name, miss); name, miss);
GenerateFastPropertyLoad(masm(), v0, reg, holder, index); GenerateFastPropertyLoad(masm(), v0, reg, Handle<JSObject>(holder), index);
__ Ret(); __ Ret();
} }
@ -1390,7 +1590,8 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
// We found FIELD property in prototype chain of interceptor's holder. // We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder. // Retrieve a field from field's holder.
GenerateFastPropertyLoad(masm(), v0, holder_reg, GenerateFastPropertyLoad(masm(), v0, holder_reg,
lookup->holder(), lookup->GetFieldIndex()); Handle<JSObject>(lookup->holder()),
lookup->GetFieldIndex());
__ Ret(); __ Ret();
} else { } else {
// We found CALLBACKS property in prototype chain of interceptor's // 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) { 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 = MaybeObject* maybe_obj =
isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(),
kind_, kind_,
@ -1511,10 +1723,10 @@ MaybeObject* CallStubCompiler::GenerateMissBranch() {
} }
MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
JSObject* holder, Handle<JSObject> holder,
int index, int index,
String* name) { Handle<String> name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a2 : name // -- a2 : name
// -- ra : return address // -- ra : return address
@ -1538,8 +1750,7 @@ MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
MaybeObject* maybe_result = GenerateMissBranch(); GenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // Return the generated code.
return GetCode(FIELD, name); return GetCode(FIELD, name);
@ -1564,7 +1775,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
Label miss; Label miss;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
Register receiver = a1; Register receiver = a1;
@ -1730,11 +1941,11 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // Return the generated code.
return GetCode(function); return TryGetCode(function);
} }
@ -1759,7 +1970,7 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
Register receiver = a1; Register receiver = a1;
Register elements = a3; Register elements = a3;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack. // Get the receiver from the stack.
const int argc = arguments().immediate(); const int argc = arguments().immediate();
@ -1819,11 +2030,11 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // Return the generated code.
return GetCode(function); return TryGetCode(function);
} }
@ -1858,7 +2069,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
index_out_of_range_label = &miss; 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. // Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(), GenerateDirectLoadGlobalFunctionPrototype(masm(),
@ -1906,11 +2117,11 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
// Restore function name in a2. // Restore function name in a2.
__ li(a2, Handle<String>(name)); __ li(a2, Handle<String>(name));
__ bind(&name_miss); __ bind(&name_miss);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // Return the generated code.
return GetCode(function); return TryGetCode(function);
} }
@ -1944,7 +2155,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
index_out_of_range_label = &miss; 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. // Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(), GenerateDirectLoadGlobalFunctionPrototype(masm(),
@ -1994,11 +2205,11 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
// Restore function name in a2. // Restore function name in a2.
__ li(a2, Handle<String>(name)); __ li(a2, Handle<String>(name));
__ bind(&name_miss); __ bind(&name_miss);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // 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(); if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss; Label miss;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) { if (cell == NULL) {
__ lw(a1, MemOperand(sp, 1 * kPointerSize)); __ lw(a1, MemOperand(sp, 1 * kPointerSize));
@ -2066,11 +2277,11 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
__ bind(&miss); __ bind(&miss);
// a2: function name. // a2: function name.
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // 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(); if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss, slow; Label miss, slow;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) { if (cell == NULL) {
__ lw(a1, MemOperand(sp, 1 * kPointerSize)); __ lw(a1, MemOperand(sp, 1 * kPointerSize));
@ -2200,11 +2411,11 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
__ bind(&miss); __ bind(&miss);
// a2: function name. // a2: function name.
MaybeObject* obj = GenerateMissBranch(); MaybeObject* obj = TryGenerateMissBranch();
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
// Return the generated code. // 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(); if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss; Label miss;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) { if (cell == NULL) {
__ lw(a1, MemOperand(sp, 1 * kPointerSize)); __ lw(a1, MemOperand(sp, 1 * kPointerSize));
@ -2302,11 +2513,11 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
__ bind(&miss); __ bind(&miss);
// a2: function name. // a2: function name.
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // 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; 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. // Get the receiver from the stack.
const int argc = arguments().immediate(); const int argc = arguments().immediate();
@ -2357,11 +2568,11 @@ MaybeObject* CallStubCompiler::CompileFastApiCall(
FreeSpaceForFastApiCall(masm()); FreeSpaceForFastApiCall(masm());
__ bind(&miss_before_stack_reserved); __ bind(&miss_before_stack_reserved);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // Return the generated code.
return GetCode(function); return TryGetCode(function);
} }
@ -2385,7 +2596,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
Label miss; Label miss;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack. // Get the receiver from the stack.
const int argc = arguments().immediate(); const int argc = arguments().immediate();
@ -2492,11 +2703,11 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // Return the generated code.
return GetCode(function); return TryGetCode(function);
} }
@ -2510,7 +2721,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
Label miss; Label miss;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments. // Get the number of arguments.
const int argc = arguments().immediate(); const int argc = arguments().immediate();
@ -2541,15 +2752,16 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Restore receiver. // Restore receiver.
__ lw(a0, MemOperand(sp, argc * kPointerSize)); __ 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. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // Return the generated code.
return GetCode(INTERCEPTOR, name); return TryGetCode(INTERCEPTOR, name);
} }
@ -2574,7 +2786,7 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
Label miss; Label miss;
GenerateNameCheck(name, &miss); GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments. // Get the number of arguments.
const int argc = arguments().immediate(); const int argc = arguments().immediate();
@ -2610,11 +2822,11 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
__ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3);
MaybeObject* maybe_result = GenerateMissBranch(); MaybeObject* maybe_result = TryGenerateMissBranch();
if (maybe_result->IsFailure()) return maybe_result; if (maybe_result->IsFailure()) return maybe_result;
// Return the generated code. // 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, // If the last object in the prototype chain is a global object,
// check that the global property cell is empty. // check that the global property cell is empty.
if (last->IsGlobalObject()) { if (last->IsGlobalObject()) {
MaybeObject* cell = GenerateCheckPropertyCell(masm(), MaybeObject* cell = TryGenerateCheckPropertyCell(masm(),
GlobalObject::cast(last), GlobalObject::cast(last),
name, name,
a1, a1,
&miss); &miss);
if (cell->IsFailure()) { if (cell->IsFailure()) {
miss.Unuse(); miss.Unuse();
return cell; return cell;