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(
}
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);
}
......
......@@ -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);
}
......
......@@ -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);
};
......
......@@ -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);
}
......
......@@ -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
......@@ -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)
};
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -772,18 +772,28 @@ StringAddTFStub = function StringAddTFStub(call_conv, minor_key) {
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.
......@@ -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;
}
}
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -25,30 +25,35 @@
// (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);
})();
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