Author: [email protected]
Date: Thu May  7 00:18:33 2009
New Revision: 1889

Modified:
    branches/bleeding_edge/src/arm/builtins-arm.cc
    branches/bleeding_edge/src/arm/codegen-arm.cc
    branches/bleeding_edge/test/cctest/test-api.cc

Log:
Port change (r1837) that allows call-as-function handlers to be called
through new to ARM.

Added simple test case of the current behavior.

For consistency, changed a number of occurences of explicit moves to
pc to use Jump instead.
Review URL: http://codereview.chromium.org/115014

Modified: branches/bleeding_edge/src/arm/builtins-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/builtins-arm.cc      (original)
+++ branches/bleeding_edge/src/arm/builtins-arm.cc      Thu May  7 00:18:33 2009
@@ -58,6 +58,16 @@
    //  -- sp[...]: constructor arguments
    // -----------------------------------

+  Label non_function_call;
+  // Check that the function is not a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, &non_function_call);
+  // Check that the function is a JSFunction.
+  __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
+  __ cmp(r2, Operand(JS_FUNCTION_TYPE));
+  __ b(ne, &non_function_call);
+
    // Enter a construct frame.
    __ EnterConstructFrame();

@@ -169,7 +179,17 @@
    __ LeaveConstructFrame();
    __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
    __ add(sp, sp, Operand(kPointerSize));
-  __ mov(pc, Operand(lr));
+  __ Jump(lr);
+
+  // r0: number of arguments
+  // r1: called object
+  __ bind(&non_function_call);
+
+  // Set expected number of arguments to zero (not changing r0).
+  __ mov(r2, Operand(0));
+  __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
+  __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
+          RelocInfo::CODE_TARGET);
  }


@@ -235,7 +255,7 @@
    // Exit the JS frame and remove the parameters (except function), and  
return.
    // Respect ABI stack constraint.
    __ LeaveInternalFrame();
-  __ mov(pc, lr);
+  __ Jump(lr);

    // r0: result
  }
@@ -544,7 +564,7 @@
    // Tear down the internal frame and remove function, receiver and args.
    __ LeaveInternalFrame();
    __ add(sp, sp, Operand(3 * kPointerSize));
-  __ mov(pc, lr);
+  __ Jump(lr);
  }


@@ -663,14 +683,14 @@

    // Exit frame and return.
    LeaveArgumentsAdaptorFrame(masm);
-  __ mov(pc, lr);
+  __ Jump(lr);


    // -------------------------------------------
    // Dont adapt arguments.
    // -------------------------------------------
    __ bind(&dont_adapt_arguments);
-  __ mov(pc, r3);
+  __ Jump(r3);
  }



Modified: branches/bleeding_edge/src/arm/codegen-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/codegen-arm.cc       (original)
+++ branches/bleeding_edge/src/arm/codegen-arm.cc       Thu May  7 00:18:33 2009
@@ -277,7 +277,7 @@
      frame_->Exit();

      __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
-    __ mov(pc, lr);
+    __ Jump(lr);
    }

    // Code generation state must be reset.
@@ -5034,13 +5034,13 @@

    // Nothing to do: The formal number of parameters has already been
    // passed in register r0 by calling function. Just return it.
-  __ mov(pc, lr);
+  __ Jump(lr);

    // Arguments adaptor case: Read the arguments length from the
    // adaptor frame and return it.
    __ bind(&adaptor);
    __ ldr(r0, MemOperand(r2,  
ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ mov(pc, lr);
+  __ Jump(lr);
  }


@@ -5072,7 +5072,7 @@
    __ sub(r3, r0, r1);
    __ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
    __ ldr(r0, MemOperand(r3, kDisplacement));
-  __ mov(pc, lr);
+  __ Jump(lr);

    // Arguments adaptor case: Check index against actual arguments
    // limit found in the arguments adaptor frame. Use unsigned
@@ -5086,7 +5086,7 @@
    __ sub(r3, r0, r1);
    __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
    __ ldr(r0, MemOperand(r3, kDisplacement));
-  __ mov(pc, lr);
+  __ Jump(lr);

    // Slow-case: Handle non-smi or out-of-bounds access to arguments
    // by calling the runtime system.

Modified: branches/bleeding_edge/test/cctest/test-api.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-api.cc      (original)
+++ branches/bleeding_edge/test/cctest/test-api.cc      Thu May  7 00:18:33 2009
@@ -4627,35 +4627,42 @@
    Local<Value> value;
    CHECK(!try_catch.HasCaught());

-  value = Script::Compile(v8_str("obj(42)"))->Run();
+  value = CompileRun("obj(42)");
    CHECK(!try_catch.HasCaught());
    CHECK_EQ(42, value->Int32Value());

-  value = Script::Compile(v8_str("(function(o){return  
o(49)})(obj)"))->Run();
+  value = CompileRun("(function(o){return o(49)})(obj)");
    CHECK(!try_catch.HasCaught());
    CHECK_EQ(49, value->Int32Value());

    // test special case of call as function
-  value = Script::Compile(v8_str("[obj]['0'](45)"))->Run();
+  value = CompileRun("[obj]['0'](45)");
    CHECK(!try_catch.HasCaught());
    CHECK_EQ(45, value->Int32Value());

-  value = Script::Compile(v8_str("obj.call = Function.prototype.call;"
-                                 "obj.call(null, 87)"))->Run();
+  value = CompileRun("obj.call = Function.prototype.call;"
+                     "obj.call(null, 87)");
    CHECK(!try_catch.HasCaught());
    CHECK_EQ(87, value->Int32Value());

    // Regression tests for bug #1116356: Calling call through call/apply
    // must work for non-function receivers.
    const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
-  value = Script::Compile(v8_str(apply_99))->Run();
+  value = CompileRun(apply_99);
    CHECK(!try_catch.HasCaught());
    CHECK_EQ(99, value->Int32Value());

    const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
-  value = Script::Compile(v8_str(call_17))->Run();
+  value = CompileRun(call_17);
    CHECK(!try_catch.HasCaught());
    CHECK_EQ(17, value->Int32Value());
+
+  // Check that the call-as-function handler can be called through
+  // new.  Currently, there is no way to check in the call-as-function
+  // handler if it has been called through new or not.
+  value = CompileRun("new obj(42)");
+  CHECK(!try_catch.HasCaught());
+  CHECK_EQ(42, value->Int32Value());
  }



--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to