Commit 737b8573 authored by danno's avatar danno Committed by Commit bot

Reland: Add unoptimized/optimized variants of MathFloor TF code stub

- 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.

Committed: https://crrev.com/8f13b655b8a10dae2116dd18b32f09337bb2d410
Cr-Commit-Position: refs/heads/master@{#29534}

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

Cr-Commit-Position: refs/heads/master@{#29539}
parent 11a831f1
...@@ -353,11 +353,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific( ...@@ -353,11 +353,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
} }
void MathRoundVariantDescriptor::InitializePlatformSpecific( void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
CallInterfaceDescriptorData* data) { 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[] = { Register registers[] = {
r1, // math rounding function r1, // math rounding function
r3, // vector slot id r3, // vector slot id
r4, // type vector
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -389,11 +389,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific( ...@@ -389,11 +389,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
} }
void MathRoundVariantDescriptor::InitializePlatformSpecific( void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
CallInterfaceDescriptorData* data) { 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[] = { Register registers[] = {
x1, // math rounding function x1, // math rounding function
x3, // vector slot id x3, // vector slot id
x4, // type vector
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -94,6 +94,7 @@ namespace internal { ...@@ -94,6 +94,7 @@ namespace internal {
/* TurboFanCodeStubs */ \ /* TurboFanCodeStubs */ \
V(StringLengthTF) \ V(StringLengthTF) \
V(StringAddTF) \ V(StringAddTF) \
/* TurboFanICs */ \
V(MathFloor) \ V(MathFloor) \
/* IC Handler stubs */ \ /* IC Handler stubs */ \
V(ArrayBufferViewLoadField) \ V(ArrayBufferViewLoadField) \
...@@ -216,7 +217,9 @@ class CodeStub BASE_EMBEDDED { ...@@ -216,7 +217,9 @@ class CodeStub BASE_EMBEDDED {
virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0; virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
virtual int GetStackParameterCount() const { return 0; } virtual int GetStackParameterCount() const {
return GetCallInterfaceDescriptor().GetStackParameterCount();
}
virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {} virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
...@@ -360,6 +363,26 @@ struct FakeStubForTesting : public CodeStub { ...@@ -360,6 +363,26 @@ struct FakeStubForTesting : public CodeStub {
Handle<Code> GenerateCode() override; \ Handle<Code> GenerateCode() override; \
DEFINE_CODE_STUB(NAME, SUPER) 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) \ #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
public: \ public: \
Handle<Code> GenerateCode() override; \ Handle<Code> GenerateCode() override; \
...@@ -544,6 +567,33 @@ class TurboFanCodeStub : public CodeStub { ...@@ -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. // Helper interface to prepare to/restore after making runtime calls.
class RuntimeCallHelper { class RuntimeCallHelper {
public: public:
...@@ -610,13 +660,12 @@ class NopRuntimeCallHelper : public RuntimeCallHelper { ...@@ -610,13 +660,12 @@ class NopRuntimeCallHelper : public RuntimeCallHelper {
}; };
class MathFloorStub : public TurboFanCodeStub { class MathFloorStub : public TurboFanIC {
public: public:
explicit MathFloorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit MathFloorStub(Isolate* isolate, TurboFanIC::CallMode mode)
int GetStackParameterCount() const override { return 1; } : TurboFanIC(isolate, mode) {}
Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
DEFINE_CALL_INTERFACE_DESCRIPTOR(MathRoundVariant); DEFINE_TURBOFAN_IC(MathFloor, TurboFanIC, MathRoundVariant);
DEFINE_CODE_STUB(MathFloor, TurboFanCodeStub);
}; };
......
...@@ -332,11 +332,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific( ...@@ -332,11 +332,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
} }
void MathRoundVariantDescriptor::InitializePlatformSpecific( void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
CallInterfaceDescriptorData* data) { 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[] = { Register registers[] = {
edi, // math rounding function edi, // math rounding function
edx, // vector slot id edx, // vector slot id
ebx // type vector
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -359,16 +359,30 @@ ApiAccessorDescriptor::BuildCallInterfaceDescriptorFunctionType( ...@@ -359,16 +359,30 @@ ApiAccessorDescriptor::BuildCallInterfaceDescriptorFunctionType(
} }
Type::FunctionType* Type::FunctionType* MathRoundVariantCallFromUnoptimizedCodeDescriptor::
MathRoundVariantDescriptor::BuildCallInterfaceDescriptorFunctionType( BuildCallInterfaceDescriptorFunctionType(Isolate* isolate,
Isolate* isolate, int paramater_count) { int paramater_count) {
Type::FunctionType* function = Type::FunctionType::New( Type::FunctionType* function = Type::FunctionType::New(
AnyTagged(), Type::Undefined(), 2, isolate->interface_descriptor_zone()); AnyTagged(), Type::Undefined(), 4, isolate->interface_descriptor_zone());
function->InitParameter(0, SmiType()); function->InitParameter(0, Type::Receiver());
function->InitParameter(1, AnyTagged()); function->InitParameter(1, SmiType());
function->InitParameter(2, AnyTagged());
function->InitParameter(3, AnyTagged());
return function; 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 internal
} // namespace v8 } // namespace v8
...@@ -61,7 +61,8 @@ class PlatformInterfaceDescriptor; ...@@ -61,7 +61,8 @@ class PlatformInterfaceDescriptor;
V(MathPowInteger) \ V(MathPowInteger) \
V(ContextOnly) \ V(ContextOnly) \
V(GrowArrayElements) \ V(GrowArrayElements) \
V(MathRoundVariant) V(MathRoundVariantCallFromUnoptimizedCode) \
V(MathRoundVariantCallFromOptimizedCode)
class CallInterfaceDescriptorData { class CallInterfaceDescriptorData {
...@@ -584,10 +585,20 @@ class MathPowIntegerDescriptor : public CallInterfaceDescriptor { ...@@ -584,10 +585,20 @@ class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
}; };
class MathRoundVariantDescriptor : public CallInterfaceDescriptor { class MathRoundVariantCallFromOptimizedCodeDescriptor
: public CallInterfaceDescriptor {
public: public:
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(MathRoundVariantDescriptor, DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
CallInterfaceDescriptor) MathRoundVariantCallFromOptimizedCodeDescriptor, CallInterfaceDescriptor)
};
class MathRoundVariantCallFromUnoptimizedCodeDescriptor
: public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
MathRoundVariantCallFromUnoptimizedCodeDescriptor,
CallInterfaceDescriptor)
}; };
......
...@@ -330,11 +330,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific( ...@@ -330,11 +330,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
} }
void MathRoundVariantDescriptor::InitializePlatformSpecific( void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
CallInterfaceDescriptorData* data) { 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[] = { Register registers[] = {
a1, // math rounding function a1, // math rounding function
a3, // vector slot id a3, // vector slot id
a2, // type vector
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -330,11 +330,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific( ...@@ -330,11 +330,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
} }
void MathRoundVariantDescriptor::InitializePlatformSpecific( void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
CallInterfaceDescriptorData* data) { 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[] = { Register registers[] = {
a1, // math rounding function a1, // math rounding function
a3, // vector slot id a3, // vector slot id
a2, // type vector
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -772,18 +772,28 @@ StringAddTFStub = function StringAddTFStub(call_conv, minor_key) { ...@@ -772,18 +772,28 @@ StringAddTFStub = function StringAddTFStub(call_conv, minor_key) {
return stub; return stub;
} }
var kTurboFanICCallModeMask = 1;
var kTurboFanICCallForUnptimizedCode = 0;
var kTurboFanICCallForOptimizedCode = 1;
MathFloorStub = function MathFloorStub(call_conv, minor_key) { MathFloorStub = function MathFloorStub(call_conv, minor_key) {
var stub = function(f, i, v) { var call_from_optimized_ic = function(f, i, tv, receiver, v) {
// |f| is calling function's JSFunction "use strict";
// |f| is this function's JSFunction
// |i| is TypeFeedbackVector slot # of callee's CallIC for Math.floor call // |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 // |v| is the value to floor
if (f !== %_FixedArrayGet(tv, i|0)) {
return %_CallFunction(receiver, v, f);
}
var r = %_MathFloor(+v); var r = %_MathFloor(+v);
if (%_IsMinusZero(r)) { if (%_IsMinusZero(r)) {
// Collect type feedback when the result of the floor is -0. This is // Collect type feedback when the result of the floor is -0. This is
// accomplished by storing a sentinel in the second, "extra" // accomplished by storing a sentinel in the second, "extra"
// TypeFeedbackVector slot corresponding to the Math.floor CallIC call in // TypeFeedbackVector slot corresponding to the Math.floor CallIC call in
// the caller's TypeVector. // the caller's TypeVector.
%_FixedArraySet(%_GetTypeFeedbackVector(f), ((i|0)+1)|0, 1); %_FixedArraySet(tv, ((i|0)+1)|0, 1);
return -0; return -0;
} }
// Return integers in smi range as smis. // Return integers in smi range as smis.
...@@ -793,7 +803,17 @@ MathFloorStub = function MathFloorStub(call_conv, minor_key) { ...@@ -793,7 +803,17 @@ MathFloorStub = function MathFloorStub(call_conv, minor_key) {
} }
return r; 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;
}
} }
......
...@@ -332,11 +332,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific( ...@@ -332,11 +332,22 @@ void ApiAccessorDescriptor::InitializePlatformSpecific(
} }
void MathRoundVariantDescriptor::InitializePlatformSpecific( void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
CallInterfaceDescriptorData* data) { 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[] = { Register registers[] = {
rdi, // math rounding function rdi, // math rounding function
rdx, // vector slot id rdx, // vector slot id
rbx // type vector
}; };
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
......
...@@ -20,17 +20,17 @@ using namespace v8::internal; ...@@ -20,17 +20,17 @@ using namespace v8::internal;
using namespace v8::internal::compiler; using namespace v8::internal::compiler;
TEST(RunMathFloorStub) { TEST(RunOptimizedMathFloorStub) {
HandleAndZoneScope scope; HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate(); Isolate* isolate = scope.main_isolate();
// Create code and an accompanying descriptor. // Create code and an accompanying descriptor.
MathFloorStub stub(isolate); MathFloorStub stub(isolate, TurboFanIC::CALL_FROM_OPTIMIZED_CODE);
Handle<Code> code = stub.GenerateCode(); Handle<Code> code = stub.GenerateCode();
Zone* zone = scope.main_zone(); Zone* zone = scope.main_zone();
CompilationInfo info(&stub, isolate, zone); CompilationInfo info(&stub, isolate, zone);
CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info); CallDescriptor* descriptor = Linkage::ComputeIncoming(zone, &info);
Handle<FixedArray> tv = isolate->factory()->NewFixedArray(10);
// Create a function to call the code using the descriptor. // Create a function to call the code using the descriptor.
Graph graph(zone); Graph graph(zone);
...@@ -45,10 +45,13 @@ TEST(RunMathFloorStub) { ...@@ -45,10 +45,13 @@ TEST(RunMathFloorStub) {
Node* numberParam = graph.NewNode(common.Parameter(1), start); Node* numberParam = graph.NewNode(common.Parameter(1), start);
Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code); Unique<HeapObject> u = Unique<HeapObject>::CreateImmovable(code);
Node* theCode = graph.NewNode(common.HeapConstant(u)); 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* dummyContext = graph.NewNode(common.NumberConstant(0.0));
Node* call = graph.NewNode(common.Call(descriptor), theCode, Node* call =
js.UndefinedConstant(), js.UndefinedConstant(), graph.NewNode(common.Call(descriptor), theCode, js.UndefinedConstant(),
numberParam, dummyContext, start, start); js.OneConstant(), vector, js.UndefinedConstant(),
numberParam, dummyContext, start, start);
Node* ret = graph.NewNode(common.Return(), call, call, start); Node* ret = graph.NewNode(common.Return(), call, call, start);
Node* end = graph.NewNode(common.End(1), ret); Node* end = graph.NewNode(common.End(1), ret);
graph.SetStart(start); graph.SetStart(start);
......
...@@ -25,30 +25,35 @@ ...@@ -25,30 +25,35 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 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 kExtraTypeFeedbackMinusZeroSentinel = 1;
const kFirstJSFunctionTypeFeedbackIndex = 5;
const kFirstSlotExtraTypeFeedbackIndex = 5; const kFirstSlotExtraTypeFeedbackIndex = 5;
(function(){ (function() {
var floorFunc = function() { var stub1 = builtins.MathFloorStub("MathFloorStub", 1);
Math.floor(NaN); var tempForTypeVector = function(d) {
return Math.round(d);
} }
// Execute the function once to make sure it has a type feedback vector. tempForTypeVector(5);
floorFunc(5); var tv = %GetTypeFeedbackVector(tempForTypeVector);
var stub = builtins.MathFloorStub("MathFloorStub", 0); 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 !== assertTrue(kExtraTypeFeedbackMinusZeroSentinel !==
%FixedArrayGet(%GetTypeFeedbackVector(floorFunc), %FixedArrayGet(tv, kFirstSlotExtraTypeFeedbackIndex));
kFirstSlotExtraTypeFeedbackIndex)); assertEquals(5.0, floorFunc1(5.5));
assertEquals(5.0, stub(floorFunc, 4, 5.5));
assertTrue(kExtraTypeFeedbackMinusZeroSentinel !== assertTrue(kExtraTypeFeedbackMinusZeroSentinel !==
%FixedArrayGet(%GetTypeFeedbackVector(floorFunc), %FixedArrayGet(tv, kFirstSlotExtraTypeFeedbackIndex));
kFirstSlotExtraTypeFeedbackIndex));
// Executing floor such that it returns -0 should set the proper sentinel in // Executing floor such that it returns -0 should set the proper sentinel in
// the feedback vector. // the feedback vector.
assertEquals(-Infinity, 1/stub(floorFunc, 4, -0)); assertEquals(-Infinity, 1/floorFunc1(-0));
assertEquals(kExtraTypeFeedbackMinusZeroSentinel, assertEquals(kExtraTypeFeedbackMinusZeroSentinel,
%FixedArrayGet(%GetTypeFeedbackVector(floorFunc), %FixedArrayGet(tv, kFirstSlotExtraTypeFeedbackIndex));
kFirstSlotExtraTypeFeedbackIndex)); %ClearFunctionTypeFeedback(floorFunc1);
%ClearFunctionTypeFeedback(floorFunc);
})(); })();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment