}
-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);
}
}
-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);
}
/* TurboFanCodeStubs */ \
V(StringLengthTF) \
V(StringAddTF) \
+ /* TurboFanICs */ \
V(MathFloor) \
/* IC Handler stubs */ \
V(ArrayBufferViewLoadField) \
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
- virtual int GetStackParameterCount() const { return 0; }
+ virtual int GetStackParameterCount() const {
+ return GetCallInterfaceDescriptor().GetStackParameterCount();
+ }
virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
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; \
};
+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:
};
-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);
};
}
-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);
}
}
-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
V(MathPowInteger) \
V(ContextOnly) \
V(GrowArrayElements) \
- V(MathRoundVariant)
+ V(MathRoundVariantCallFromUnoptimizedCode) \
+ V(MathRoundVariantCallFromOptimizedCode)
class CallInterfaceDescriptorData {
};
-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)
};
}
-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);
}
}
-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);
}
return stub;
}
+var kTurboFanICCallModeMask = 1;
+var kTurboFanICCallForUnptimizedCode = 0;
+var 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.
}
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;
+ }
}
}
-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);
}
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);
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);
// (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);
})();