Add unoptimized/optimized variants of MathFloor TF code stub
authordanno <danno@chromium.org>
Wed, 8 Jul 2015 14:43:07 +0000 (07:43 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 8 Jul 2015 14:43:25 +0000 (14:43 +0000)
- Add a TurboFanIC class, derived from TurboFanCodeStub, that
  automatically distinguishes between versions of the IC called from
  optimized and unoptimized code.
- Add appropriate InterfaceDescriptors for both the versions of the
  stub called from unoptimized and optimized code
- Change the MathFloor TF stub generator to output either the
  for-optimized or for-unoptimized version based on the minor_key
  parameter.

Review URL: https://codereview.chromium.org/1225943002

Cr-Commit-Position: refs/heads/master@{#29534}

12 files changed:
src/arm/interface-descriptors-arm.cc
src/arm64/interface-descriptors-arm64.cc
src/code-stubs.h
src/ia32/interface-descriptors-ia32.cc
src/interface-descriptors.cc
src/interface-descriptors.h
src/mips/interface-descriptors-mips.cc
src/mips64/interface-descriptors-mips64.cc
src/runtime.js
src/x64/interface-descriptors-x64.cc
test/cctest/compiler/test-run-stubs.cc
test/mjsunit/compiler/stubs/floor-stub.js

index 67f65f5..3dd5fab 100644 (file)
@@ -353,11 +353,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
 }
 
 
-void MathRoundVariantDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
+void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      r1,  // math rounding function
+      r3,  // vector slot id
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
+void MathRoundVariantCallFromOptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   Register registers[] = {
       r1,  // math rounding function
       r3,  // vector slot id
+      r4,  // type vector
   };
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
index 62e6f2a..8412c46 100644 (file)
@@ -389,11 +389,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
 }
 
 
-void MathRoundVariantDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
+void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      x1,  // math rounding function
+      x3,  // vector slot id
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
+void MathRoundVariantCallFromOptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   Register registers[] = {
       x1,  // math rounding function
       x3,  // vector slot id
+      x4,  // type vector
   };
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
index c06c6c1..a798d5e 100644 (file)
@@ -94,6 +94,7 @@ namespace internal {
   /* TurboFanCodeStubs */                   \
   V(StringLengthTF)                         \
   V(StringAddTF)                            \
+  /* TurboFanICs */                         \
   V(MathFloor)                              \
   /* IC Handler stubs */                    \
   V(ArrayBufferViewLoadField)               \
@@ -216,7 +217,9 @@ class CodeStub BASE_EMBEDDED {
 
   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
 
-  virtual int GetStackParameterCount() const { return 0; }
+  virtual int GetStackParameterCount() const {
+    return GetCallInterfaceDescriptor().GetStackParameterCount();
+  }
 
   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
 
@@ -360,6 +363,26 @@ struct FakeStubForTesting : public CodeStub {
   Handle<Code> GenerateCode() override;                               \
   DEFINE_CODE_STUB(NAME, SUPER)
 
+#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                          \
+ public:                                                                \
+  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
+    return DESC##Descriptor(isolate());                                 \
+  };                                                                    \
+  DEFINE_CODE_STUB(NAME, SUPER)
+
+#define DEFINE_TURBOFAN_IC(NAME, SUPER, DESC)                           \
+ public:                                                                \
+  CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
+    if (GetCallMode() == CALL_FROM_OPTIMIZED_CODE) {                    \
+      return DESC##CallFromOptimizedCodeDescriptor(isolate());          \
+    } else {                                                            \
+      return DESC##CallFromUnoptimizedCodeDescriptor(isolate());        \
+    }                                                                   \
+  };                                                                    \
+                                                                        \
+ protected:                                                             \
+  DEFINE_CODE_STUB(NAME, SUPER)
+
 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
  public:                                      \
   Handle<Code> GenerateCode() override;       \
@@ -544,6 +567,33 @@ class TurboFanCodeStub : public CodeStub {
 };
 
 
+class TurboFanIC : public TurboFanCodeStub {
+ public:
+  enum CallMode { CALL_FROM_UNOPTIMIZED_CODE, CALL_FROM_OPTIMIZED_CODE };
+
+ protected:
+  explicit TurboFanIC(Isolate* isolate, CallMode mode)
+      : TurboFanCodeStub(isolate) {
+    minor_key_ = CallModeBits::encode(mode);
+  }
+
+  CallMode GetCallMode() const { return CallModeBits::decode(minor_key_); }
+
+  void set_sub_minor_key(uint32_t key) {
+    minor_key_ = SubMinorKeyBits::update(minor_key_, key);
+  }
+
+  uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
+
+  static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
+
+ private:
+  class CallModeBits : public BitField<CallMode, 0, 1> {};
+  class SubMinorKeyBits : public BitField<int, 1, kSubMinorKeyBits> {};
+  DEFINE_CODE_STUB_BASE(TurboFanIC, TurboFanCodeStub);
+};
+
+
 // Helper interface to prepare to/restore after making runtime calls.
 class RuntimeCallHelper {
  public:
@@ -610,13 +660,12 @@ class NopRuntimeCallHelper : public RuntimeCallHelper {
 };
 
 
-class MathFloorStub : public TurboFanCodeStub {
+class MathFloorStub : public TurboFanIC {
  public:
-  explicit MathFloorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
-  int GetStackParameterCount() const override { return 1; }
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(MathRoundVariant);
-  DEFINE_CODE_STUB(MathFloor, TurboFanCodeStub);
+  explicit MathFloorStub(Isolate* isolate, TurboFanIC::CallMode mode)
+      : TurboFanIC(isolate, mode) {}
+  Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
+  DEFINE_TURBOFAN_IC(MathFloor, TurboFanIC, MathRoundVariant);
 };
 
 
index 4eefa94..be0b2cd 100644 (file)
@@ -332,11 +332,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
 }
 
 
-void MathRoundVariantDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
+void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      edi,  // math rounding function
+      edx,  // vector slot id
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
+void MathRoundVariantCallFromOptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   Register registers[] = {
       edi,  // math rounding function
       edx,  // vector slot id
+      ebx   // type vector
   };
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
index fa41eb0..1e8cc2e 100644 (file)
@@ -359,16 +359,30 @@ ApiAccessorDescriptor::BuildCallInterfaceDescriptorFunctionType(
 }
 
 
-Type::FunctionType*
-MathRoundVariantDescriptor::BuildCallInterfaceDescriptorFunctionType(
-    Isolate* isolate, int paramater_count) {
+Type::FunctionType* MathRoundVariantCallFromUnoptimizedCodeDescriptor::
+    BuildCallInterfaceDescriptorFunctionType(Isolate* isolate,
+                                             int paramater_count) {
   Type::FunctionType* function = Type::FunctionType::New(
-      AnyTagged(), Type::Undefined(), 2, isolate->interface_descriptor_zone());
-  function->InitParameter(0, SmiType());
-  function->InitParameter(1, AnyTagged());
+      AnyTagged(), Type::Undefined(), 4, isolate->interface_descriptor_zone());
+  function->InitParameter(0, Type::Receiver());
+  function->InitParameter(1, SmiType());
+  function->InitParameter(2, AnyTagged());
+  function->InitParameter(3, AnyTagged());
   return function;
 }
 
 
+Type::FunctionType* MathRoundVariantCallFromOptimizedCodeDescriptor::
+    BuildCallInterfaceDescriptorFunctionType(Isolate* isolate,
+                                             int paramater_count) {
+  Type::FunctionType* function = Type::FunctionType::New(
+      AnyTagged(), Type::Undefined(), 5, isolate->interface_descriptor_zone());
+  function->InitParameter(0, Type::Receiver());
+  function->InitParameter(1, SmiType());
+  function->InitParameter(2, AnyTagged());
+  function->InitParameter(3, AnyTagged());
+  function->InitParameter(4, AnyTagged());
+  return function;
+}
 }  // namespace internal
 }  // namespace v8
index f206b55..7fa70f1 100644 (file)
@@ -61,7 +61,8 @@ class PlatformInterfaceDescriptor;
   V(MathPowInteger)                           \
   V(ContextOnly)                              \
   V(GrowArrayElements)                        \
-  V(MathRoundVariant)
+  V(MathRoundVariantCallFromUnoptimizedCode)  \
+  V(MathRoundVariantCallFromOptimizedCode)
 
 
 class CallInterfaceDescriptorData {
@@ -584,10 +585,20 @@ class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
 };
 
 
-class MathRoundVariantDescriptor : public CallInterfaceDescriptor {
+class MathRoundVariantCallFromOptimizedCodeDescriptor
+    : public CallInterfaceDescriptor {
  public:
-  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(MathRoundVariantDescriptor,
-                                               CallInterfaceDescriptor)
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
+      MathRoundVariantCallFromOptimizedCodeDescriptor, CallInterfaceDescriptor)
+};
+
+
+class MathRoundVariantCallFromUnoptimizedCodeDescriptor
+    : public CallInterfaceDescriptor {
+ public:
+  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
+      MathRoundVariantCallFromUnoptimizedCodeDescriptor,
+      CallInterfaceDescriptor)
 };
 
 
index 0379da0..0c00833 100644 (file)
@@ -330,11 +330,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
 }
 
 
-void MathRoundVariantDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
+void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      a1,  // math rounding function
+      a3,  // vector slot id
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
+void MathRoundVariantCallFromOptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   Register registers[] = {
       a1,  // math rounding function
       a3,  // vector slot id
+      a2,  // type vector
   };
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
index 689bbbb..47cc092 100644 (file)
@@ -330,11 +330,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
 }
 
 
-void MathRoundVariantDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
+void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      a1,  // math rounding function
+      a3,  // vector slot id
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
+void MathRoundVariantCallFromOptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   Register registers[] = {
       a1,  // math rounding function
       a3,  // vector slot id
+      a2,  // type vector
   };
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
index fa71432..03ffbae 100644 (file)
@@ -772,18 +772,28 @@ StringAddTFStub = function StringAddTFStub(call_conv, minor_key) {
   return stub;
 }
 
+const kTurboFanICCallModeMask = 1;
+const kTurboFanICCallForUnptimizedCode = 0;
+const kTurboFanICCallForOptimizedCode = 1;
+
 MathFloorStub = function MathFloorStub(call_conv, minor_key) {
-  var stub = function(f, i, v) {
-    // |f| is calling function's JSFunction
+  var call_from_optimized_ic = function(f, i, tv, receiver, v) {
+    "use strict";
+    // |f| is this function's JSFunction
     // |i| is TypeFeedbackVector slot # of callee's CallIC for Math.floor call
+    // |receiver| is receiver, should not be used
+    // |tv| is the calling function's type vector
     // |v| is the value to floor
+    if (f !== %_FixedArrayGet(tv, i|0)) {
+      return %_CallFunction(receiver, v, f);
+    }
     var r = %_MathFloor(+v);
     if (%_IsMinusZero(r)) {
       // Collect type feedback when the result of the floor is -0. This is
       // accomplished by storing a sentinel in the second, "extra"
       // TypeFeedbackVector slot corresponding to the Math.floor CallIC call in
       // the caller's TypeVector.
-      %_FixedArraySet(%_GetTypeFeedbackVector(f), ((i|0)+1)|0, 1);
+      %_FixedArraySet(tv, ((i|0)+1)|0, 1);
       return -0;
     }
     // Return integers in smi range as smis.
@@ -793,7 +803,17 @@ MathFloorStub = function MathFloorStub(call_conv, minor_key) {
     }
     return r;
   }
-  return stub;
+  var call_mode = (minor_key & kTurboFanICCallModeMask);
+  if (call_mode == kTurboFanICCallForOptimizedCode) {
+    return call_from_optimized_ic;
+  } else {
+    %SetForceInlineFlag(call_from_optimized_ic);
+    var call_from_unoptimized_ic = function(f, i, receiver, v) {
+      var tv = %_GetTypeFeedbackVector(%_GetCallerJSFunction());
+      return call_from_optimized_ic(f, i, tv, receiver, v);
+    }
+    return call_from_unoptimized_ic;
+  }
 }
 
 
index 7602403..4f43569 100644 (file)
@@ -332,11 +332,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
 }
 
 
-void MathRoundVariantDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
+void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
+  Register registers[] = {
+      rdi,  // math rounding function
+      rdx,  // vector slot id
+  };
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
+void MathRoundVariantCallFromOptimizedCodeDescriptor::
+    InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
   Register registers[] = {
       rdi,  // math rounding function
       rdx,  // vector slot id
+      rbx   // type vector
   };
   data->InitializePlatformSpecific(arraysize(registers), registers);
 }
index 9c7998d..4d2a363 100644 (file)
@@ -20,17 +20,17 @@ using namespace v8::internal;
 using namespace v8::internal::compiler;
 
 
-TEST(RunMathFloorStub) {
+TEST(RunOptimizedMathFloorStub) {
   HandleAndZoneScope scope;
   Isolate* isolate = scope.main_isolate();
 
   // Create code and an accompanying descriptor.
-  MathFloorStub stub(isolate);
+  MathFloorStub stub(isolate, TurboFanIC::CALL_FROM_OPTIMIZED_CODE);
   Handle<Code> code = stub.GenerateCode();
   Zone* zone = scope.main_zone();
-
   CompilationInfo info(&stub, isolate, zone);
   CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info);
+  Handle<FixedArray> tv = isolate->factory()->NewFixedArray(10);
 
   // Create a function to call the code using the descriptor.
   Graph graph(zone);
@@ -45,10 +45,13 @@ TEST(RunMathFloorStub) {
   Node* numberParam = graph.NewNode(common.Parameter(1), start);
   Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code);
   Node* theCode = graph.NewNode(common.HeapConstant(u));
+  Unique<HeapObject> tvu = Unique<HeapObject>::CreateImmovable(tv);
+  Node* vector = graph.NewNode(common.HeapConstant(tvu));
   Node* dummyContext = graph.NewNode(common.NumberConstant(0.0));
-  Node* call = graph.NewNode(common.Call(descriptor), theCode,
-                             js.UndefinedConstant(), js.UndefinedConstant(),
-                             numberParam, dummyContext, start, start);
+  Node* call =
+      graph.NewNode(common.Call(descriptor), theCode, js.UndefinedConstant(),
+                    js.OneConstant(), vector, js.UndefinedConstant(),
+                    numberParam, dummyContext, start, start);
   Node* ret = graph.NewNode(common.Return(), call, call, start);
   Node* end = graph.NewNode(common.End(1), ret);
   graph.SetStart(start);
index e3fc9b6..08cbef7 100644 (file)
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --allow-natives-syntax --expose-natives-as=builtins --noalways-opt
+// Flags: --allow-natives-syntax --expose-natives-as=builtins --noalways-opt --turbo-filter=*
 
 const kExtraTypeFeedbackMinusZeroSentinel = 1;
+const kFirstJSFunctionTypeFeedbackIndex = 5;
 const kFirstSlotExtraTypeFeedbackIndex = 5;
 
-(function(){
-  var floorFunc = function() {
-    Math.floor(NaN);
+(function()  {
+  var stub1 = builtins.MathFloorStub("MathFloorStub", 1);
+  var tempForTypeVector = function(d) {
+    return Math.round(d);
   }
-  // Execute the function once to make sure it has a type feedback vector.
-  floorFunc(5);
-  var stub = builtins.MathFloorStub("MathFloorStub", 0);
+  tempForTypeVector(5);
+  var tv = %GetTypeFeedbackVector(tempForTypeVector);
+  var floorFunc1 = function(v, first) {
+    if (first) return;
+    return stub1(stub1, kFirstSlotExtraTypeFeedbackIndex - 1, tv, undefined, v);
+  };
+  %OptimizeFunctionOnNextCall(stub1);
+  floorFunc1(5, true);
+  %FixedArraySet(tv, kFirstSlotExtraTypeFeedbackIndex - 1, stub1);
   assertTrue(kExtraTypeFeedbackMinusZeroSentinel !==
-             %FixedArrayGet(%GetTypeFeedbackVector(floorFunc),
-                            kFirstSlotExtraTypeFeedbackIndex));
-  assertEquals(5.0, stub(floorFunc, 4, 5.5));
+             %FixedArrayGet(tv, kFirstSlotExtraTypeFeedbackIndex));
+  assertEquals(5.0, floorFunc1(5.5));
   assertTrue(kExtraTypeFeedbackMinusZeroSentinel !==
-             %FixedArrayGet(%GetTypeFeedbackVector(floorFunc),
-                            kFirstSlotExtraTypeFeedbackIndex));
+             %FixedArrayGet(tv, kFirstSlotExtraTypeFeedbackIndex));
   // Executing floor such that it returns -0 should set the proper sentinel in
   // the feedback vector.
-  assertEquals(-Infinity, 1/stub(floorFunc, 4, -0));
+  assertEquals(-Infinity, 1/floorFunc1(-0));
   assertEquals(kExtraTypeFeedbackMinusZeroSentinel,
-               %FixedArrayGet(%GetTypeFeedbackVector(floorFunc),
-                              kFirstSlotExtraTypeFeedbackIndex));
-  %ClearFunctionTypeFeedback(floorFunc);
+               %FixedArrayGet(tv, kFirstSlotExtraTypeFeedbackIndex));
+  %ClearFunctionTypeFeedback(floorFunc1);
 })();