}
-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.
+ __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
+ __ sub(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);
+ __ add(index, index, Operand(index, LSL, 1)); // index *= 3.
+
+ Register entity_name = scratch0;
+ // Having undefined at this place means the name is not contained.
+ ASSERT_EQ(kSmiTagSize, 1);
+ Register tmp = properties;
+ __ add(tmp, properties, Operand(index, LSL, 1));
+ __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset));
+
+ ASSERT(!tmp.is(entity_name));
+ __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex);
+ __ cmp(entity_name, tmp);
+ __ b(eq, done);
+
+ if (i != kInlinedProbes - 1) {
+ // Stop if found the property.
+ __ cmp(entity_name, Operand(Handle<String>(name)));
+ __ b(eq, miss);
+
+ // Check if the entry name is not a symbol.
+ __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
+ __ ldrb(entity_name,
+ FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
+ __ tst(entity_name, Operand(kIsSymbolMask));
+ __ b(eq, miss);
+
+ // Restore the properties.
+ __ ldr(properties,
+ FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+ }
+ }
+
+ const int spill_mask =
+ (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() |
+ r2.bit() | r1.bit() | r0.bit());
+
+ __ stm(db_w, sp, spill_mask);
+ __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+ __ mov(r1, Operand(Handle<String>(name)));
+ StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
+ __ CallStub(&stub);
+ __ tst(r0, Operand(r0));
+ __ ldm(ia_w, sp, spill_mask);
+
+ __ b(eq, done);
+ __ b(ne, miss);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MaybeObject* StringDictionaryLookupStub::TryGenerateNegativeLookup(
MacroAssembler* masm,
Label* miss,
Label* done,
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,
// 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;
+ __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
+ __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
+ __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
+ __ b(ne, miss_label);
+
+ // Check that receiver is a JSObject.
+ __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
+ __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
+ __ b(lt, miss_label);
+
+ // Load properties array.
+ Register properties = scratch0;
+ __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+ // Check that the properties array is a dictionary.
+ __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
+ Register tmp = properties;
+ __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
+ __ cmp(map, tmp);
+ __ b(ne, miss_label);
+
+ // Restore the temporarily used register.
+ __ ldr(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,
__ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
- MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup(
+ MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup(
masm,
miss_label,
&done,
// 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) {
static void GenerateCallFunction(MacroAssembler* masm,
- Object* object,
+ Handle<Object> object,
const ParameterCount& arguments,
Label* miss,
Code::ExtraICState extra_ic_state) {
// 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());
+ __ mov(scratch, Operand(cell));
+ __ ldr(scratch,
+ FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ cmp(scratch, ip);
+ __ b(ne, miss);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell(
MacroAssembler* masm,
GlobalObject* global,
String* name,
return cell;
}
+
// 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,
while (current != holder) {
if (current->IsGlobalObject()) {
// Returns a cell or a failure.
- MaybeObject* result = GenerateCheckPropertyCell(
+ MaybeObject* result = TryGenerateCheckPropertyCell(
masm,
GlobalObject::cast(current),
name,
#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) {
+ __ str(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);
+
+ __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+ reg = holder_reg; // From now on the object will be in holder_reg.
+ __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
+ } else {
+ Handle<Map> current_map(current->map());
+ __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ cmp(scratch1, Operand(current_map));
+ // Branch on the result of the map check.
+ __ b(ne, miss);
+ // 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.
+ __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
+ } else {
+ // The prototype is in old space; load it directly.
+ __ mov(reg, Operand(prototype));
+ }
+ }
+
+ if (save_at_depth == depth) {
+ __ str(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.
+ __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
+ __ cmp(scratch1, Operand(Handle<Map>(current->map())));
+ __ b(ne, miss);
+
+ // 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;
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
Register StubCompiler::CheckPrototypes(JSObject* object,
Register object_reg,
JSObject* holder,
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;
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.
Register reg =
CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
name, miss);
- GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
+ GenerateFastPropertyLoad(masm(), r0, reg, Handle<JSObject>(holder), index);
__ Ret();
}
// We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder.
GenerateFastPropertyLoad(masm(), r0, holder_reg,
- lookup->holder(), lookup->GetFieldIndex());
+ Handle<JSObject>(lookup->holder()),
+ lookup->GetFieldIndex());
__ Ret();
} else {
// We found CALLBACKS property in prototype chain of interceptor's
}
-void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
- __ cmp(r2, Operand(Handle<String>(name)));
+ __ cmp(r2, Operand(name));
__ b(ne, miss);
}
}
}
-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_,
}
-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 -------------
// -- r2 : name
// -- lr : return address
// 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);
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
Register receiver = r1;
// 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);
}
Register receiver = r1;
Register elements = r3;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack
const int argc = arguments().immediate();
// 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);
}
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(),
// Restore function name in r2.
__ Move(r2, 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);
}
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(),
// Restore function name in r2.
__ Move(r2, 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);
}
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ ldr(r1, MemOperand(sp, 1 * kPointerSize));
__ bind(&miss);
// r2: 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);
}
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss, slow;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ ldr(r1, MemOperand(sp, 1 * kPointerSize));
__ bind(&miss);
// r2: 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);
}
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ ldr(r1, MemOperand(sp, 1 * kPointerSize));
__ bind(&miss);
// r2: 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);
}
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();
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);
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack
const int argc = arguments().immediate();
// 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);
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
// Restore receiver.
__ ldr(r0, 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);
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
- 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);
}
// 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,
- r1,
- &miss);
+ MaybeObject* cell = TryGenerateCheckPropertyCell(masm(),
+ GlobalObject::cast(last),
+ name,
+ r1,
+ &miss);
if (cell->IsFailure()) {
miss.Unuse();
return cell;
// 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.
-MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
+void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register properties,
+ Handle<String> name,
+ Register r0) {
+ ASSERT(name->IsSymbol());
+
+ // 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++) {
+ // Compute the masked index: (hash + i + i * i) & mask.
+ Register index = r0;
+ // Capacity is smi 2^n.
+ __ mov(index, FieldOperand(properties, kCapacityOffset));
+ __ dec(index);
+ __ and_(index,
+ Immediate(Smi::FromInt(name->Hash() +
+ StringDictionary::GetProbeOffset(i))));
+
+ // Scale the index by multiplying by the entry size.
+ ASSERT(StringDictionary::kEntrySize == 3);
+ __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
+ Register entity_name = r0;
+ // Having undefined at this place means the name is not contained.
+ ASSERT_EQ(kSmiTagSize, 1);
+ __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
+ kElementsStartOffset - kHeapObjectTag));
+ __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
+ __ j(equal, done);
+
+ // Stop if found the property.
+ __ cmp(entity_name, Handle<String>(name));
+ __ j(equal, miss);
+
+ // Check if the entry name is not a symbol.
+ __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
+ __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ kIsSymbolMask);
+ __ j(zero, miss);
+ }
+
+ StringDictionaryLookupStub stub(properties,
+ r0,
+ r0,
+ StringDictionaryLookupStub::NEGATIVE_LOOKUP);
+ __ push(Immediate(Handle<Object>(name)));
+ __ push(Immediate(name->Hash()));
+ __ CallStub(&stub);
+ __ test(r0, r0);
+ __ j(not_zero, miss);
+ __ jmp(done);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MaybeObject* StringDictionaryLookupStub::TryGenerateNegativeLookup(
MacroAssembler* masm,
Label* miss,
Label* done,
void Generate(MacroAssembler* masm);
- MUST_USE_RESULT static MaybeObject* GenerateNegativeLookup(
+ static void GenerateNegativeLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register properties,
+ Handle<String> name,
+ Register r0);
+
+ // TODO(kmillikin): Eliminate this function when the stub cache is fully
+ // handlified.
+ MUST_USE_RESULT static MaybeObject* TryGenerateNegativeLookup(
MacroAssembler* masm,
Label* miss,
Label* done,
// 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.
-static MaybeObject* GenerateDictionaryNegativeLookup(MacroAssembler* masm,
- Label* miss_label,
- Register receiver,
- String* name,
- Register r0,
- Register r1) {
+static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
+ Label* miss_label,
+ Register receiver,
+ Handle<String> name,
+ Register r0,
+ Register r1) {
+ ASSERT(name->IsSymbol());
+ Counters* counters = masm->isolate()->counters();
+ __ IncrementCounter(counters->negative_lookups(), 1);
+ __ IncrementCounter(counters->negative_lookups_miss(), 1);
+
+ __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
+
+ const int kInterceptorOrAccessCheckNeededMask =
+ (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
+
+ // Bail out if the receiver has a named interceptor or requires access checks.
+ __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
+ kInterceptorOrAccessCheckNeededMask);
+ __ j(not_zero, miss_label);
+
+ // Check that receiver is a JSObject.
+ __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
+ __ j(below, miss_label);
+
+ // Load properties array.
+ Register properties = r0;
+ __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
+
+ // Check that the properties array is a dictionary.
+ __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
+ Immediate(masm->isolate()->factory()->hash_table_map()));
+ __ j(not_equal, miss_label);
+
+ Label done;
+ StringDictionaryLookupStub::GenerateNegativeLookup(masm,
+ miss_label,
+ &done,
+ properties,
+ name,
+ r1);
+ __ bind(&done);
+ __ DecrementCounter(counters->negative_lookups_miss(), 1);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+static MaybeObject* TryGenerateDictionaryNegativeLookup(MacroAssembler* masm,
+ Label* miss_label,
+ Register receiver,
+ String* name,
+ Register r0,
+ Register r1) {
ASSERT(name->IsSymbol());
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->negative_lookups(), 1);
Label done;
MaybeObject* result =
- StringDictionaryLookupStub::GenerateNegativeLookup(masm,
- miss_label,
- &done,
- properties,
- name,
- r1);
+ StringDictionaryLookupStub::TryGenerateNegativeLookup(masm,
+ miss_label,
+ &done,
+ properties,
+ name,
+ r1);
if (result->IsFailure()) return result;
__ bind(&done);
// 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) {
// 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());
+ Handle<Oddball> the_hole = masm->isolate()->factory()->the_hole_value();
+ if (Serializer::enabled()) {
+ __ mov(scratch, Immediate(cell));
+ __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
+ Immediate(the_hole));
+ } else {
+ __ cmp(Operand::Cell(cell), Immediate(the_hole));
+ }
+ __ j(not_equal, miss);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell(
MacroAssembler* masm,
GlobalObject* global,
String* name,
// 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,
while (current != holder) {
if (current->IsGlobalObject()) {
// Returns a cell or a failure.
- MaybeObject* result = GenerateCheckPropertyCell(
+ MaybeObject* result = TryGenerateCheckPropertyCell(
masm,
GlobalObject::cast(current),
name,
#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;
+ Handle<JSObject> current = object;
+ int depth = 0;
+
+ if (save_at_depth == depth) {
+ __ mov(Operand(esp, kPointerSize), reg);
+ }
+
+ // Traverse the prototype chain and check the maps in the prototype chain for
+ // fast and global objects or do negative lookup for normal objects.
+ 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);
+
+ __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ reg = holder_reg; // From now on the object will be in holder_reg.
+ __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+ } else {
+ bool in_new_space = heap()->InNewSpace(*prototype);
+ Handle<Map> current_map(current->map());
+ if (in_new_space) {
+ // Save the map in scratch1 for later.
+ __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ __ cmp(scratch1, Immediate(current_map));
+ } else {
+ __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
+ Immediate(current_map));
+ }
+ // Branch on the result of the map check.
+ __ j(not_equal, miss);
+ // 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 (in_new_space) {
+ // The prototype is in new space; we cannot store a reference to it
+ // in the code. Load it from the map.
+ __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+ } else {
+ // The prototype is in old space; load it directly.
+ __ mov(reg, prototype);
+ }
+ }
+
+ if (save_at_depth == depth) {
+ __ mov(Operand(esp, kPointerSize), reg);
+ }
+
+ // Go to the next object in the prototype chain.
+ current = prototype;
+ }
+ ASSERT(current.is_identical_to(holder));
+
+ // Log the check depth.
+ LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
+
+ // Check the holder map.
+ __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
+ Immediate(Handle<Map>(holder->map())));
+ __ j(not_equal, miss);
+
+ // 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;
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
Register StubCompiler::CheckPrototypes(JSObject* object,
Register object_reg,
JSObject* holder,
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;
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.
scratch1, scratch2, scratch3, name, miss);
// Get the value from the properties.
- GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
+ GenerateFastPropertyLoad(masm(), eax, reg, Handle<JSObject>(holder), index);
__ ret(0);
}
// We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder.
GenerateFastPropertyLoad(masm(), eax, holder_reg,
- lookup->holder(), lookup->GetFieldIndex());
+ Handle<JSObject>(lookup->holder()),
+ lookup->GetFieldIndex());
__ ret(0);
} else {
// We found CALLBACKS property in prototype chain of interceptor's
}
-void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
- __ cmp(ecx, Immediate(Handle<String>(name)));
+ __ cmp(ecx, Immediate(name));
__ j(not_equal, miss);
}
}
}
-MaybeObject* CallStubCompiler::GenerateMissBranch() {
+void CallStubCompiler::GenerateMissBranch() {
+ Handle<Code> code =
+ isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
+ kind_,
+ extra_state_);
+ __ jmp(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_,
}
-MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField(
- JSObject* object,
- JSObject* holder,
- int index,
- String* name) {
+Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
+ Handle<JSObject> holder,
+ int index,
+ Handle<String> name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
// 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);
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
}
__ 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);
}
Label miss, return_undefined, call_builtin;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
1);
__ 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);
}
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(),
// Restore function name in ecx.
__ Set(ecx, Immediate(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);
}
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(),
// Restore function name in ecx.
__ Set(ecx, Immediate(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);
}
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ mov(edx, Operand(esp, 2 * kPointerSize));
__ bind(&miss);
// ecx: 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);
}
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ mov(edx, Operand(esp, 2 * kPointerSize));
__ bind(&miss);
// ecx: 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);
}
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ mov(edx, Operand(esp, 2 * kPointerSize));
__ bind(&miss);
// ecx: 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);
}
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();
__ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
__ 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);
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
// 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);
}
// -----------------------------------
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
// Handle load 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);
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(counters->call_global_inline_miss(), 1);
- 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);
}
// 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,
- edx,
- &miss);
+ MaybeObject* cell = TryGenerateCheckPropertyCell(masm(),
+ GlobalObject::cast(last),
+ name,
+ edx,
+ &miss);
if (cell->IsFailure()) {
miss.Unuse();
return cell;
}
+Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell(
+ Handle<GlobalObject> global,
+ Handle<String> name) {
+ Isolate* isolate = global->GetIsolate();
+ CALL_HEAP_FUNCTION(isolate,
+ global->EnsurePropertyCell(*name),
+ JSGlobalPropertyCell);
+}
+
+
MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
ASSERT(!HasFastProperties());
int entry = property_dictionary()->FindEntry(name);
}
// Ensure that the global object has a cell for the given property name.
+ static Handle<JSGlobalPropertyCell> EnsurePropertyCell(
+ Handle<GlobalObject> global,
+ Handle<String> name);
+ // TODO(kmillikin): This function can be eliminated once the stub cache is
+ // full handlified (and the static helper can be written directly).
MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
// Casting.
}
-Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
- Handle<JSObject> holder,
- int index,
- Handle<String> name) {
- CALL_HEAP_FUNCTION(
- isolate(),
- (set_failure(NULL), CompileCallField(*object, *holder, index, *name)),
- Code);
-}
-
-
Handle<Code> StubCache::ComputeCallField(int argc,
Code::Kind kind,
Code::ExtraICState extra_state,
}
+Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
+ Handle<String> name) {
+ return (FLAG_print_code_stubs && !name.is_null())
+ ? GetCodeWithFlags(flags, *name->ToCString())
+ : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
+}
+
+
MaybeObject* StubCompiler::TryGetCodeWithFlags(Code::Flags flags,
const char* name) {
// Check for allocation failures during stub compilation.
MaybeObject* StubCompiler::TryGetCodeWithFlags(Code::Flags flags,
String* name) {
- if (FLAG_print_code_stubs && (name != NULL)) {
+ if (FLAG_print_code_stubs && name != NULL) {
return TryGetCodeWithFlags(flags, *name->ToCString());
}
return TryGetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
}
-MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
+Handle<Code> CallStubCompiler::GetCode(PropertyType type, Handle<String> name) {
+ int argc = arguments_.immediate();
+ Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
+ type,
+ extra_state_,
+ cache_holder_,
+ argc);
+ return GetCodeWithFlags(flags, name);
+}
+
+
+Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) {
+ Handle<String> function_name;
+ if (function->shared()->name()->IsString()) {
+ function_name = Handle<String>(String::cast(function->shared()->name()));
+ }
+ return GetCode(CONSTANT_FUNCTION, function_name);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MaybeObject* CallStubCompiler::TryGetCode(PropertyType type, String* name) {
int argc = arguments_.immediate();
Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
type,
}
-MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MaybeObject* CallStubCompiler::TryGetCode(JSFunction* function) {
String* function_name = NULL;
if (function->shared()->name()->IsString()) {
function_name = String::cast(function->shared()->name());
}
- return GetCode(CONSTANT_FUNCTION, function_name);
+ return TryGetCode(CONSTANT_FUNCTION, function_name);
}
Label* miss);
static void GenerateFastPropertyLoad(MacroAssembler* masm,
- Register dst, Register src,
- JSObject* holder, int index);
+ Register dst,
+ Register src,
+ Handle<JSObject> holder,
+ int index);
static void GenerateLoadArrayLength(MacroAssembler* masm,
Register receiver,
// The function can optionally (when save_at_depth !=
// kInvalidProtoDepth) save the object at the given depth by moving
// it to [esp + kPointerSize].
+ Register CheckPrototypes(Handle<JSObject> object,
+ Register object_reg,
+ Handle<JSObject> holder,
+ Register holder_reg,
+ Register scratch1,
+ Register scratch2,
+ Handle<String> name,
+ Label* miss) {
+ return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
+ scratch2, name, kInvalidProtoDepth, miss);
+ }
+ Register 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);
+
+ // TODO(kmillikin): Eliminate this function when the stub cache is fully
+ // handlified.
Register CheckPrototypes(JSObject* object,
Register object_reg,
JSObject* holder,
scratch2, name, kInvalidProtoDepth, miss);
}
+ // TODO(kmillikin): Eliminate this function when the stub cache is fully
+ // handlified.
Register CheckPrototypes(JSObject* object,
Register object_reg,
JSObject* holder,
protected:
Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
+ Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<String> name);
MUST_USE_RESULT MaybeObject* TryGetCodeWithFlags(Code::Flags flags,
const char* name);
int index,
Handle<String> name);
- MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
- JSObject* holder,
- int index,
- String* name);
-
Handle<Code> CompileCallConstant(Handle<Object> object,
Handle<JSObject> holder,
Handle<JSFunction> function,
const ParameterCount& arguments() { return arguments_; }
- MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
+ Handle<Code> GetCode(PropertyType type, Handle<String> name);
+ Handle<Code> GetCode(Handle<JSFunction> function);
- // Convenience function. Calls GetCode above passing
- // CONSTANT_FUNCTION type and the name of the given function.
- MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
+ // TODO(kmillikin): Eliminate these functions when the stub cache is fully
+ // handlified.
+ MUST_USE_RESULT MaybeObject* TryGetCode(PropertyType type, String* name);
+ MUST_USE_RESULT MaybeObject* TryGetCode(JSFunction* function);
- void GenerateNameCheck(String* name, Label* miss);
+ void GenerateNameCheck(Handle<String> name, Label* miss);
void GenerateGlobalReceiverCheck(JSObject* object,
JSObject* holder,
JSFunction* function,
Label* miss);
- // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
- // be generated.
- MUST_USE_RESULT MaybeObject* GenerateMissBranch();
+ // Generates a jump to CallIC miss stub.
+ void GenerateMissBranch();
+
+ // TODO(kmillikin): Eliminate this function when the stub cache is fully
+ // handlified.
+ MUST_USE_RESULT MaybeObject* TryGenerateMissBranch();
};
}
-MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup(
+void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register properties,
+ Handle<String> name,
+ Register r0) {
+ // 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++) {
+ // r0 points to properties hash.
+ // Compute the masked index: (hash + i + i * i) & mask.
+ Register index = r0;
+ // Capacity is smi 2^n.
+ __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
+ __ decl(index);
+ __ and_(index,
+ Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
+
+ // Scale the index by multiplying by the entry size.
+ ASSERT(StringDictionary::kEntrySize == 3);
+ __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
+
+ Register entity_name = r0;
+ // Having undefined at this place means the name is not contained.
+ ASSERT_EQ(kSmiTagSize, 1);
+ __ movq(entity_name, Operand(properties,
+ index,
+ times_pointer_size,
+ kElementsStartOffset - kHeapObjectTag));
+ __ Cmp(entity_name, masm->isolate()->factory()->undefined_value());
+ __ j(equal, done);
+
+ // Stop if found the property.
+ __ Cmp(entity_name, Handle<String>(name));
+ __ j(equal, miss);
+
+ // Check if the entry name is not a symbol.
+ __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
+ __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ Immediate(kIsSymbolMask));
+ __ j(zero, miss);
+ }
+
+ StringDictionaryLookupStub stub(properties,
+ r0,
+ r0,
+ StringDictionaryLookupStub::NEGATIVE_LOOKUP);
+ __ Push(Handle<Object>(name));
+ __ push(Immediate(name->Hash()));
+ __ CallStub(&stub);
+ __ testq(r0, r0);
+ __ j(not_zero, miss);
+ __ jmp(done);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MaybeObject* StringDictionaryLookupStub::TryGenerateNegativeLookup(
MacroAssembler* masm,
Label* miss,
Label* done,
void Generate(MacroAssembler* masm);
- MUST_USE_RESULT static MaybeObject* GenerateNegativeLookup(
+ static void GenerateNegativeLookup(MacroAssembler* masm,
+ Label* miss,
+ Label* done,
+ Register properties,
+ Handle<String> name,
+ Register r0);
+
+ // TODO(kmillikin): Eliminate this function when the stub cache is fully
+ // handlified.
+ MUST_USE_RESULT static MaybeObject* TryGenerateNegativeLookup(
MacroAssembler* masm,
Label* miss,
Label* done,
// 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 r0,
+ Register r1) {
+ ASSERT(name->IsSymbol());
+ Counters* counters = masm->isolate()->counters();
+ __ IncrementCounter(counters->negative_lookups(), 1);
+ __ IncrementCounter(counters->negative_lookups_miss(), 1);
+
+ __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset));
+
+ const int kInterceptorOrAccessCheckNeededMask =
+ (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
+
+ // Bail out if the receiver has a named interceptor or requires access checks.
+ __ testb(FieldOperand(r0, Map::kBitFieldOffset),
+ Immediate(kInterceptorOrAccessCheckNeededMask));
+ __ j(not_zero, miss_label);
+
+ // Check that receiver is a JSObject.
+ __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
+ __ j(below, miss_label);
+
+ // Load properties array.
+ Register properties = r0;
+ __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
+
+ // Check that the properties array is a dictionary.
+ __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
+ Heap::kHashTableMapRootIndex);
+ __ j(not_equal, miss_label);
+
+ Label done;
+ StringDictionaryLookupStub::GenerateNegativeLookup(masm,
+ miss_label,
+ &done,
+ properties,
+ name,
+ r1);
+ __ bind(&done);
+ __ DecrementCounter(counters->negative_lookups_miss(), 1);
+}
+
+
+// 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,
__ j(not_equal, miss_label);
Label done;
- MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup(
+ MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup(
masm,
miss_label,
&done,
// 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) {
// 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());
+ __ Move(scratch, cell);
+ __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
+ masm->isolate()->factory()->the_hole_value());
+ __ j(not_equal, miss);
+}
+
+
+// TODO(kmillikin): Eliminate this function when the stub cache is fully
+// handlified.
+MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell(
MacroAssembler* masm,
GlobalObject* global,
String* name,
}
+// Calls GenerateCheckPropertyCell for each global object in the prototype chain
+// from object to (but not including) holder.
+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,
+ String* name,
+ Register scratch,
+ Label* miss) {
+ JSObject* current = object;
+ while (current != holder) {
+ if (current->IsGlobalObject()) {
+ // Returns a cell or a failure.
+ MaybeObject* result = TryGenerateCheckPropertyCell(
+ masm,
+ GlobalObject::cast(current),
+ name,
+ scratch,
+ miss);
+ if (result->IsFailure()) return result;
+ }
+ ASSERT(current->IsJSObject());
+ current = JSObject::cast(current->GetPrototype());
+ }
+ return NULL;
+}
+
+
#undef __
#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. On the first
+ // iteration, reg is an alias for object_reg, on later iterations,
+ // it is an alias for holder_reg.
+ Register reg = object_reg;
+ int depth = 0;
+
+ if (save_at_depth == depth) {
+ __ movq(Operand(rsp, kPointerSize), object_reg);
+ }
+
+ // 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);
+
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ reg = holder_reg; // From now on the object will be in holder_reg.
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+ } else {
+ bool in_new_space = heap()->InNewSpace(*prototype);
+ Handle<Map> current_map(current->map());
+ if (in_new_space) {
+ // Save the map in scratch1 for later.
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
+ __ Cmp(scratch1, current_map);
+ } else {
+ __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), current_map);
+ }
+ // Branch on the result of the map check.
+ __ j(not_equal, miss);
+ // 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 (in_new_space) {
+ // The prototype is in new space; we cannot store a reference to it
+ // in the code. Load it from the map.
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
+ } else {
+ // The prototype is in old space; load it directly.
+ __ Move(reg, prototype);
+ }
+ }
+
+ if (save_at_depth == depth) {
+ __ movq(Operand(rsp, kPointerSize), reg);
+ }
+
+ // Go to the next object in the prototype chain.
+ current = prototype;
+ }
+ ASSERT(current.is_identical_to(holder));
+
+ // Log the check depth.
+ LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
+
+ // Check the holder map.
+ __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map()));
+ __ j(not_equal, miss);
+
+ // Perform security check for access to the global object.
+ ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
+ if (current->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,
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;
// 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.
- current = object;
- while (current != holder) {
- if (current->IsGlobalObject()) {
- MaybeObject* cell = GenerateCheckPropertyCell(masm(),
- GlobalObject::cast(current),
- name,
- scratch1,
- miss);
- if (cell->IsFailure()) {
- set_failure(Failure::cast(cell));
- return reg;
- }
- }
- current = JSObject::cast(current->GetPrototype());
- }
+ MaybeObject* result = TryGenerateCheckPropertyCells(masm(),
+ object,
+ holder,
+ name,
+ scratch1,
+ miss);
+ if (result->IsFailure()) set_failure(Failure::cast(result));
// Return the register containing the holder.
return reg;
scratch1, scratch2, scratch3, name, miss);
// Get the value from the properties.
- GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
+ GenerateFastPropertyLoad(masm(), rax, reg, Handle<JSObject>(holder), index);
__ ret(0);
}
// We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder.
GenerateFastPropertyLoad(masm(), rax, holder_reg,
- lookup->holder(), lookup->GetFieldIndex());
+ Handle<JSObject>(lookup->holder()),
+ lookup->GetFieldIndex());
__ ret(0);
} else {
// We found CALLBACKS property in prototype chain of interceptor's
}
-void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
if (kind_ == Code::KEYED_CALL_IC) {
- __ Cmp(rcx, Handle<String>(name));
+ __ Cmp(rcx, name);
__ j(not_equal, miss);
}
}
}
-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_,
}
-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 -------------
// rcx : function name
// rsp[0] : return address
// 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);
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
}
__ 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);
}
Label miss, return_undefined, call_builtin;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
1);
__ 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);
}
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(),
// Restore function name in rcx.
__ Move(rcx, 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);
}
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(),
// Restore function name in rcx.
__ Move(rcx, 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);
}
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ movq(rdx, Operand(rsp, 2 * kPointerSize));
__ bind(&miss);
// rcx: 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);
}
if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
if (cell == NULL) {
__ movq(rdx, Operand(rsp, 2 * kPointerSize));
__ bind(&miss);
// rcx: 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);
}
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();
__ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
__ 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);
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
// 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);
}
// -----------------------------------
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
// Handle load 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);
}
Label miss;
- GenerateNameCheck(name, &miss);
+ GenerateNameCheck(Handle<String>(name), &miss);
// Get the number of arguments.
const int argc = arguments().immediate();
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(counters->call_global_inline_miss(), 1);
- 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);
}
// 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,
- rdx,
- &miss);
+ MaybeObject* cell = TryGenerateCheckPropertyCell(masm(),
+ GlobalObject::cast(last),
+ name,
+ rdx,
+ &miss);
if (cell->IsFailure()) {
miss.Unuse();
return cell;