}
-Object* LoadStubCompiler::CompileLoadNonexistent(JSObject* object) {
- // ----------- S t a t e -------------
- // -- r2 : name
- // -- lr : return address
- // -- [sp] : receiver
- // -----------------------------------
- Label miss;
-
- // Load receiver.
- __ ldr(r0, MemOperand(sp, 0));
-
- // Check the maps of the full prototype chain.
- JSObject* last = object;
- while (last->GetPrototype() != Heap::null_value()) {
- last = JSObject::cast(last->GetPrototype());
- }
- CheckPrototypes(object, r0, last, r3, r1, Heap::empty_string(), &miss);
-
- // Return undefined if maps of the full prototype chain is still the same.
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
- __ Ret();
-
- __ bind(&miss);
- GenerateLoadMiss(masm(), Code::LOAD_IC);
-
- // Return the generated code.
- return GetCode(NONEXISTENT, Heap::empty_string());
-}
-
-
Object* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder,
int index,
CONSTANT_TRANSITION = 6, // only in fast mode
NULL_DESCRIPTOR = 7, // only in fast mode
// All properties before MAP_TRANSITION are real.
- FIRST_PHANTOM_PROPERTY_TYPE = MAP_TRANSITION,
- // There are no IC stubs for NULL_DESCRIPTORS. Therefore,
- // NULL_DESCRIPTOR can be used as the type flag for IC stubs for
- // nonexistent properties.
- NONEXISTENT = NULL_DESCRIPTOR
+ FIRST_PHANTOM_PROPERTY_TYPE = MAP_TRANSITION
};
}
-Object* LoadStubCompiler::CompileLoadNonexistent(JSObject* object) {
- // ----------- S t a t e -------------
- // -- eax : receiver
- // -- ecx : name
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
-
- // Check the maps of the full prototype chain.
- JSObject* last = object;
- while (last->GetPrototype() != Heap::null_value()) {
- last = JSObject::cast(last->GetPrototype());
- }
- CheckPrototypes(object, eax, last, ebx, edx, Heap::empty_string(), &miss);
-
- // Return undefined if maps of the full prototype chain is still the same.
- __ mov(eax, Factory::undefined_value());
- __ ret(0);
-
- __ bind(&miss);
- GenerateLoadMiss(masm(), Code::LOAD_IC);
-
- // Return the generated code.
- return GetCode(NONEXISTENT, Heap::empty_string());
-}
-
Object* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder,
State state,
Handle<Object> object,
Handle<String> name) {
- // Bail out if the result is not cachable.
- if (!lookup->IsCacheable()) return;
+ // Bail out if we didn't find a result.
+ if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
// Loading properties from values is not common, so don't try to
// deal with non-JS objects here.
// Set the target to the pre monomorphic stub to delay
// setting the monomorphic state.
code = pre_monomorphic_stub();
- } else if (!lookup->IsProperty()) {
- // Nonexistent property. The result is undefined.
- code = StubCache::ComputeLoadNonexistent(*name, *receiver);
} else {
// Compute monomorphic stub.
switch (lookup->type()) {
}
-Object* StubCache::ComputeLoadNonexistent(String* name, JSObject* receiver) {
- // The code stub for loading nonexistent properties can be reused
- // for all names, so we use the empty_string as the name in the map
- // code cache.
- Code::Flags flags =
- Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
- Object* code = receiver->map()->FindInCodeCache(Heap::empty_string(), flags);
- if (code->IsUndefined()) {
- LoadStubCompiler compiler;
- code = compiler.CompileLoadNonexistent(receiver);
- if (code->IsFailure()) return code;
- PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG,
- Code::cast(code),
- Heap::empty_string()));
- Object* result = receiver->map()->UpdateCodeCache(Heap::empty_string(),
- Code::cast(code));
- if (result->IsFailure()) return result;
- }
- return Set(name, receiver->map(), Code::cast(code));
-}
-
-
Object* StubCache::ComputeLoadField(String* name,
JSObject* receiver,
JSObject* holder,
// Computes the right stub matching. Inserts the result in the
// cache before returning. This might compile a stub if needed.
- static Object* ComputeLoadNonexistent(String* name, JSObject* receiver);
-
static Object* ComputeLoadField(String* name,
JSObject* receiver,
JSObject* holder,
class LoadStubCompiler: public StubCompiler {
public:
- Object* CompileLoadNonexistent(JSObject* object);
-
Object* CompileLoadField(JSObject* object,
JSObject* holder,
int index,
String* name);
-
Object* CompileLoadCallback(String* name,
JSObject* object,
JSObject* holder,
AccessorInfo* callback);
-
Object* CompileLoadConstant(JSObject* object,
JSObject* holder,
Object* value,
String* name);
-
Object* CompileLoadInterceptor(JSObject* object,
JSObject* holder,
String* name);
JSObject* object,
JSObject* holder,
int index);
-
Object* CompileLoadCallback(String* name,
JSObject* object,
JSObject* holder,
AccessorInfo* callback);
-
Object* CompileLoadConstant(String* name,
JSObject* object,
JSObject* holder,
Object* value);
-
Object* CompileLoadInterceptor(JSObject* object,
JSObject* holder,
String* name);
-
Object* CompileLoadArrayLength(String* name);
Object* CompileLoadStringLength(String* name);
Object* CompileLoadFunctionPrototype(String* name);
}
-Object* LoadStubCompiler::CompileLoadNonexistent(JSObject* object) {
- // ----------- S t a t e -------------
- // -- rcx : name
- // -- rsp[0] : return address
- // -- rsp[8] : receiver
- // -----------------------------------
- Label miss;
-
- // Load receiver.
- __ movq(rax, Operand(rsp, kPointerSize));
-
- // Check the maps of the full prototype chain.
- JSObject* last = object;
- while (last->GetPrototype() != Heap::null_value()) {
- last = JSObject::cast(last->GetPrototype());
- }
- CheckPrototypes(object, rax, last, rbx, rdx, Heap::empty_string(), &miss);
-
- // Return undefined if maps of the full prototype chain is still the same.
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- __ ret(0);
-
- __ bind(&miss);
- GenerateLoadMiss(masm(), Code::LOAD_IC);
-
- // Return the generated code.
- return GetCode(NONEXISTENT, Heap::empty_string());
-}
-
-
Object* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder,
int index,