| Index: src/arm/stub-cache-arm.cc
|
| ===================================================================
|
| --- src/arm/stub-cache-arm.cc (revision 3853)
|
| +++ src/arm/stub-cache-arm.cc (working copy)
|
| @@ -408,51 +408,6 @@
|
| }
|
|
|
|
|
| -template <class Compiler>
|
| -static void CompileLoadInterceptor(Compiler* compiler,
|
| - StubCompiler* stub_compiler,
|
| - MacroAssembler* masm,
|
| - JSObject* object,
|
| - JSObject* holder,
|
| - String* name,
|
| - LookupResult* lookup,
|
| - Register receiver,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - Label* miss) {
|
| - ASSERT(holder->HasNamedInterceptor());
|
| - ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
|
| -
|
| - // Check that the receiver isn't a smi.
|
| - __ BranchOnSmi(receiver, miss);
|
| -
|
| - // Check that the maps haven't changed.
|
| - Register reg =
|
| - stub_compiler->CheckPrototypes(object, receiver, holder,
|
| - scratch1, scratch2, name, miss);
|
| -
|
| - if (lookup->IsValid() && lookup->IsCacheable()) {
|
| - compiler->CompileCacheable(masm,
|
| - stub_compiler,
|
| - receiver,
|
| - reg,
|
| - scratch1,
|
| - scratch2,
|
| - holder,
|
| - lookup,
|
| - name,
|
| - miss);
|
| - } else {
|
| - compiler->CompileRegular(masm,
|
| - receiver,
|
| - reg,
|
| - scratch2,
|
| - holder,
|
| - miss);
|
| - }
|
| -}
|
| -
|
| -
|
| static void PushInterceptorArguments(MacroAssembler* masm,
|
| Register receiver,
|
| Register holder,
|
| @@ -619,110 +574,50 @@
|
| };
|
|
|
|
|
| -class CallInterceptorCompiler BASE_EMBEDDED {
|
| - public:
|
| - CallInterceptorCompiler(const ParameterCount& arguments, Register name)
|
| - : arguments_(arguments), argc_(arguments.immediate()), name_(name) {}
|
| +static void CompileLoadInterceptor(LoadInterceptorCompiler* compiler,
|
| + StubCompiler* stub_compiler,
|
| + MacroAssembler* masm,
|
| + JSObject* object,
|
| + JSObject* holder,
|
| + String* name,
|
| + LookupResult* lookup,
|
| + Register receiver,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Label* miss) {
|
| + ASSERT(holder->HasNamedInterceptor());
|
| + ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
|
|
|
| - void CompileCacheable(MacroAssembler* masm,
|
| - StubCompiler* stub_compiler,
|
| - Register receiver,
|
| - Register holder,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - JSObject* holder_obj,
|
| - LookupResult* lookup,
|
| - String* name,
|
| - Label* miss_label) {
|
| - JSFunction* function = 0;
|
| - bool optimize = false;
|
| - // So far the most popular case for failed interceptor is
|
| - // CONSTANT_FUNCTION sitting below.
|
| - if (lookup->type() == CONSTANT_FUNCTION) {
|
| - function = lookup->GetConstantFunction();
|
| - // JSArray holder is a special case for call constant function
|
| - // (see the corresponding code).
|
| - if (function->is_compiled() && !holder_obj->IsJSArray()) {
|
| - optimize = true;
|
| - }
|
| - }
|
| + // Check that the receiver isn't a smi.
|
| + __ BranchOnSmi(receiver, miss);
|
|
|
| - if (!optimize) {
|
| - CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label);
|
| - return;
|
| - }
|
| + // Check that the maps haven't changed.
|
| + Register reg =
|
| + stub_compiler->CheckPrototypes(object, receiver, holder,
|
| + scratch1, scratch2, name, miss);
|
|
|
| - // Constant functions cannot sit on global object.
|
| - ASSERT(!lookup->holder()->IsGlobalObject());
|
| -
|
| - __ EnterInternalFrame();
|
| - __ push(holder); // Save the holder.
|
| - __ push(name_); // Save the name.
|
| -
|
| - CompileCallLoadPropertyWithInterceptor(masm,
|
| - receiver,
|
| - holder,
|
| - name_,
|
| - holder_obj);
|
| -
|
| - ASSERT(!r0.is(name_));
|
| - ASSERT(!r0.is(scratch1));
|
| - __ pop(name_); // Restore the name.
|
| - __ pop(scratch1); // Restore the holder.
|
| - __ LeaveInternalFrame();
|
| -
|
| - // Compare with no_interceptor_result_sentinel.
|
| - __ LoadRoot(scratch2, Heap::kNoInterceptorResultSentinelRootIndex);
|
| - __ cmp(r0, scratch2);
|
| - Label invoke;
|
| - __ b(ne, &invoke);
|
| -
|
| - stub_compiler->CheckPrototypes(holder_obj, scratch1,
|
| - lookup->holder(), scratch1,
|
| - scratch2,
|
| - name,
|
| - miss_label);
|
| - GenerateCallConstFunction(masm, function, arguments_);
|
| -
|
| - __ bind(&invoke);
|
| - }
|
| -
|
| - void CompileRegular(MacroAssembler* masm,
|
| - Register receiver,
|
| - Register holder,
|
| - Register scratch,
|
| - JSObject* holder_obj,
|
| - Label* miss_label) {
|
| - __ EnterInternalFrame();
|
| - // Save the name_ register across the call.
|
| - __ push(name_);
|
| -
|
| - PushInterceptorArguments(masm,
|
| + if (lookup->IsValid() && lookup->IsCacheable()) {
|
| + compiler->CompileCacheable(masm,
|
| + stub_compiler,
|
| + receiver,
|
| + reg,
|
| + scratch1,
|
| + scratch2,
|
| + holder,
|
| + lookup,
|
| + name,
|
| + miss);
|
| + } else {
|
| + compiler->CompileRegular(masm,
|
| receiver,
|
| + reg,
|
| + scratch2,
|
| holder,
|
| - name_,
|
| - holder_obj);
|
| -
|
| - ExternalReference ref = ExternalReference(
|
| - IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
|
| - __ mov(r0, Operand(5));
|
| - __ mov(r1, Operand(ref));
|
| -
|
| - CEntryStub stub(1);
|
| - __ CallStub(&stub);
|
| -
|
| - // Restore the name_ register.
|
| - __ pop(name_);
|
| - __ LeaveInternalFrame();
|
| + miss);
|
| }
|
| +}
|
|
|
| - private:
|
| - const ParameterCount& arguments_;
|
| - int argc_;
|
| - Register name_;
|
| -};
|
|
|
| -
|
| #undef __
|
| #define __ ACCESS_MASM(masm())
|
|
|
| @@ -764,7 +659,7 @@
|
| object = JSObject::cast(object->GetPrototype());
|
| }
|
|
|
| - // Return the register containin the holder.
|
| + // Return the register containing the holder.
|
| return result;
|
| }
|
|
|
| @@ -1075,36 +970,103 @@
|
| // ----------- S t a t e -------------
|
| // -- lr: return address
|
| // -----------------------------------
|
| + ASSERT(holder->HasNamedInterceptor());
|
| + ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
|
| Label miss;
|
|
|
| + const Register receiver = r0;
|
| + const Register name_reg = r1;
|
| + const Register holder_reg = r2;
|
| + const Register scratch = r3;
|
| +
|
| // Get the number of arguments.
|
| const int argc = arguments().immediate();
|
|
|
| LookupResult lookup;
|
| LookupPostInterceptor(holder, name, &lookup);
|
|
|
| - // Get the receiver from the stack into r0.
|
| - __ ldr(r0, MemOperand(sp, argc * kPointerSize));
|
| - // Load the name from the stack into r1.
|
| - __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
|
| + // Load the receiver from the stack.
|
| + __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
|
| + // Load the name from the stack.
|
| + __ ldr(name_reg, MemOperand(sp, (argc + 1) * kPointerSize));
|
|
|
| - CallInterceptorCompiler compiler(arguments(), r1);
|
| - CompileLoadInterceptor(&compiler,
|
| - this,
|
| - masm(),
|
| - JSObject::cast(object),
|
| - holder,
|
| - name,
|
| - &lookup,
|
| - r0,
|
| - r2,
|
| - r3,
|
| - &miss);
|
| + // Check that the receiver isn't a smi.
|
| + __ BranchOnSmi(receiver, &miss);
|
|
|
| + // Check that the maps haven't changed.
|
| + Register reg =
|
| + CheckPrototypes(JSObject::cast(object), receiver, holder,
|
| + holder_reg, scratch, name, &miss);
|
| + if (!reg.is(holder_reg)) {
|
| + __ mov(holder_reg, reg);
|
| + }
|
| +
|
| + // If we call a constant function when the interceptor returns
|
| + // the no-result sentinel, generate code that optimizes this case.
|
| + if (lookup.IsValid() &&
|
| + lookup.IsCacheable() &&
|
| + lookup.type() == CONSTANT_FUNCTION &&
|
| + lookup.GetConstantFunction()->is_compiled() &&
|
| + !holder->IsJSArray()) {
|
| + // Constant functions cannot sit on global object.
|
| + ASSERT(!lookup.holder()->IsGlobalObject());
|
| +
|
| + // Call the interceptor.
|
| + __ EnterInternalFrame();
|
| + __ push(holder_reg);
|
| + __ push(name_reg);
|
| + CompileCallLoadPropertyWithInterceptor(masm(),
|
| + receiver,
|
| + holder_reg,
|
| + name_reg,
|
| + holder);
|
| + __ pop(name_reg);
|
| + __ pop(holder_reg);
|
| + __ LeaveInternalFrame();
|
| + // r0 no longer contains the receiver.
|
| +
|
| + // If interceptor returns no-result sentinal, call the constant function.
|
| + __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
|
| + __ cmp(r0, scratch);
|
| + Label invoke;
|
| + __ b(ne, &invoke);
|
| + // Check the prototypes between the interceptor's holder and the
|
| + // constant function's holder.
|
| + CheckPrototypes(holder, holder_reg,
|
| + lookup.holder(), r0,
|
| + scratch,
|
| + name,
|
| + &miss);
|
| + GenerateCallConstFunction(masm(),
|
| + lookup.GetConstantFunction(),
|
| + arguments());
|
| + __ bind(&invoke);
|
| +
|
| + } else {
|
| + // Call a runtime function to load the interceptor property.
|
| + __ EnterInternalFrame();
|
| + __ push(name_reg);
|
| +
|
| + PushInterceptorArguments(masm(), receiver, holder_reg, name_reg, holder);
|
| +
|
| + ExternalReference ref = ExternalReference(
|
| + IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
|
| + __ mov(r0, Operand(5));
|
| + __ mov(r1, Operand(ref));
|
| +
|
| + CEntryStub stub(1);
|
| + __ CallStub(&stub);
|
| +
|
| + __ pop(name_reg);
|
| + __ LeaveInternalFrame();
|
| + }
|
| +
|
| +
|
| // Move returned value, the function to call, to r1.
|
| + // Neither receiver nor name contain their original value at this point.
|
| __ mov(r1, r0);
|
| // Restore receiver.
|
| - __ ldr(r0, MemOperand(sp, argc * kPointerSize));
|
| + __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
|
|
|
| GenerateCallFunction(masm(), object, arguments(), &miss);
|
|
|
|
|