Commit c58f3285 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Introduce IncStub and DecStub.

Adds IncStub and DecStub TurboFan code stubs and hooks them up to the
interpreter's Inc and Dec bytecodes (which are used for count
operations, e.g. i++).

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#35720}
parent 11e3ba34
......@@ -317,6 +317,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -347,6 +347,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {x1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -280,6 +280,18 @@ Callable CodeFactory::BitwiseXor(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::Inc(Isolate* isolate) {
IncStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::Dec(Isolate* isolate) {
DecStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::LessThan(Isolate* isolate) {
LessThanStub stub(isolate);
......
......@@ -93,6 +93,8 @@ class CodeFactory final {
static Callable BitwiseAnd(Isolate* isolate);
static Callable BitwiseOr(Isolate* isolate);
static Callable BitwiseXor(Isolate* isolate);
static Callable Inc(Isolate* isolate);
static Callable Dec(Isolate* isolate);
static Callable LessThan(Isolate* isolate);
static Callable LessThanOrEqual(Isolate* isolate);
static Callable GreaterThan(Isolate* isolate);
......
......@@ -1639,6 +1639,168 @@ compiler::Node* BitwiseXorStub::Generate(CodeStubAssembler* assembler,
return result;
}
void IncStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* context = assembler->Parameter(1);
// Shared entry for floating point increment.
Label do_finc(assembler);
Variable var_finc_value(assembler, MachineRepresentation::kFloat64);
// We might need to try again due to ToNumber conversion.
Variable value_var(assembler, MachineRepresentation::kTagged);
Label start(assembler, &value_var);
value_var.Bind(assembler->Parameter(0));
assembler->Goto(&start);
assembler->Bind(&start);
{
Node* value = value_var.value();
Label if_issmi(assembler), if_isnotsmi(assembler);
assembler->Branch(assembler->WordIsSmi(value), &if_issmi, &if_isnotsmi);
assembler->Bind(&if_issmi);
{
// Try fast Smi addition first.
Node* one = assembler->SmiConstant(Smi::FromInt(1));
Node* pair = assembler->SmiAddWithOverflow(value, one);
Node* overflow = assembler->Projection(1, pair);
// Check if the Smi additon overflowed.
Label if_overflow(assembler), if_notoverflow(assembler);
assembler->Branch(overflow, &if_overflow, &if_notoverflow);
assembler->Bind(&if_notoverflow);
assembler->Return(assembler->Projection(0, pair));
assembler->Bind(&if_overflow);
{
var_finc_value.Bind(assembler->SmiToFloat64(value));
assembler->Goto(&do_finc);
}
}
assembler->Bind(&if_isnotsmi);
{
// Check if the value is a HeapNumber.
Label if_valueisnumber(assembler),
if_valuenotnumber(assembler, Label::kDeferred);
Node* value_map = assembler->LoadMap(value);
Node* number_map = assembler->HeapNumberMapConstant();
assembler->Branch(assembler->WordEqual(value_map, number_map),
&if_valueisnumber, &if_valuenotnumber);
assembler->Bind(&if_valueisnumber);
{
// Load the HeapNumber value.
var_finc_value.Bind(assembler->LoadHeapNumberValue(value));
assembler->Goto(&do_finc);
}
assembler->Bind(&if_valuenotnumber);
{
// Convert to a Number first and try again.
Callable callable = CodeFactory::NonNumberToNumber(isolate());
value_var.Bind(assembler->CallStub(callable, context, value));
assembler->Goto(&start);
}
}
}
assembler->Bind(&do_finc);
{
Node* finc_value = var_finc_value.value();
Node* one = assembler->Float64Constant(1.0);
Node* finc_result = assembler->Float64Add(finc_value, one);
Node* result = assembler->ChangeFloat64ToTagged(finc_result);
assembler->Return(result);
}
}
void DecStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* context = assembler->Parameter(1);
// Shared entry for floating point decrement.
Label do_fdec(assembler);
Variable var_fdec_value(assembler, MachineRepresentation::kFloat64);
// We might need to try again due to ToNumber conversion.
Variable value_var(assembler, MachineRepresentation::kTagged);
Label start(assembler, &value_var);
value_var.Bind(assembler->Parameter(0));
assembler->Goto(&start);
assembler->Bind(&start);
{
Node* value = value_var.value();
Label if_issmi(assembler), if_isnotsmi(assembler);
assembler->Branch(assembler->WordIsSmi(value), &if_issmi, &if_isnotsmi);
assembler->Bind(&if_issmi);
{
// Try fast Smi subtraction first.
Node* one = assembler->SmiConstant(Smi::FromInt(1));
Node* pair = assembler->SmiSubWithOverflow(value, one);
Node* overflow = assembler->Projection(1, pair);
// Check if the Smi subtraction overflowed.
Label if_overflow(assembler), if_notoverflow(assembler);
assembler->Branch(overflow, &if_overflow, &if_notoverflow);
assembler->Bind(&if_notoverflow);
assembler->Return(assembler->Projection(0, pair));
assembler->Bind(&if_overflow);
{
var_fdec_value.Bind(assembler->SmiToFloat64(value));
assembler->Goto(&do_fdec);
}
}
assembler->Bind(&if_isnotsmi);
{
// Check if the value is a HeapNumber.
Label if_valueisnumber(assembler),
if_valuenotnumber(assembler, Label::kDeferred);
Node* value_map = assembler->LoadMap(value);
Node* number_map = assembler->HeapNumberMapConstant();
assembler->Branch(assembler->WordEqual(value_map, number_map),
&if_valueisnumber, &if_valuenotnumber);
assembler->Bind(&if_valueisnumber);
{
// Load the HeapNumber value.
var_fdec_value.Bind(assembler->LoadHeapNumberValue(value));
assembler->Goto(&do_fdec);
}
assembler->Bind(&if_valuenotnumber);
{
// Convert to a Number first and try again.
Callable callable = CodeFactory::NonNumberToNumber(isolate());
value_var.Bind(assembler->CallStub(callable, context, value));
assembler->Goto(&start);
}
}
}
assembler->Bind(&do_fdec);
{
Node* fdec_value = var_fdec_value.value();
Node* one = assembler->Float64Constant(1.0);
Node* fdec_result = assembler->Float64Sub(fdec_value, one);
Node* result = assembler->ChangeFloat64ToTagged(fdec_result);
assembler->Return(result);
}
}
namespace {
enum RelationalComparisonMode {
......
......@@ -120,6 +120,8 @@ namespace internal {
V(BitwiseAnd) \
V(BitwiseOr) \
V(BitwiseXor) \
V(Inc) \
V(Dec) \
V(FastCloneShallowObject) \
V(LessThan) \
V(LessThanOrEqual) \
......@@ -776,6 +778,22 @@ class BitwiseXorStub final : public TurboFanCodeStub {
DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(BitwiseXor, TurboFanCodeStub);
};
class IncStub final : public TurboFanCodeStub {
public:
explicit IncStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
DEFINE_TURBOFAN_CODE_STUB(Inc, TurboFanCodeStub);
};
class DecStub final : public TurboFanCodeStub {
public:
explicit DecStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
DEFINE_TURBOFAN_CODE_STUB(Dec, TurboFanCodeStub);
};
class LessThanStub final : public TurboFanCodeStub {
public:
explicit LessThanStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
......
......@@ -1121,9 +1121,11 @@ void BytecodeGraphBuilder::VisitShiftRightLogical() {
void BytecodeGraphBuilder::VisitInc() {
FrameStateBeforeAndAfter states(this);
const Operator* js_op = javascript()->Add(BinaryOperationHints::Any());
// Note: Use subtract -1 here instead of add 1 to ensure we always convert to
// a number, not a string.
const Operator* js_op = javascript()->Subtract(BinaryOperationHints::Any());
Node* node = NewNode(js_op, environment()->LookupAccumulator(),
jsgraph()->OneConstant());
jsgraph()->Constant(-1.0));
environment()->BindAccumulator(node, &states);
}
......
......@@ -321,6 +321,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -66,6 +66,7 @@ class PlatformInterfaceDescriptor;
V(Compare) \
V(BinaryOp) \
V(BinaryOpWithAllocationSite) \
V(CountOp) \
V(StringAdd) \
V(StringCompare) \
V(Keyed) \
......@@ -631,6 +632,10 @@ class BinaryOpWithAllocationSiteDescriptor : public CallInterfaceDescriptor {
CallInterfaceDescriptor)
};
class CountOpDescriptor final : public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR(CountOpDescriptor, CallInterfaceDescriptor)
};
class StringAddDescriptor : public CallInterfaceDescriptor {
public:
......
......@@ -2796,13 +2796,12 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
}
}
// Convert old value into a number.
builder()->CastAccumulatorToNumber();
// Save result for postfix expressions.
if (is_postfix) {
old_value = register_allocator()->outer()->NewRegister();
builder()->StoreAccumulatorInRegister(old_value);
// Convert old value into a number before saving it.
builder()->CastAccumulatorToNumber().StoreAccumulatorInRegister(old_value);
}
// Perform +1/-1 operation.
......
......@@ -814,12 +814,12 @@ void Interpreter::DoShiftRightLogical(InterpreterAssembler* assembler) {
DoBinaryOp<ShiftRightLogicalStub>(assembler);
}
void Interpreter::DoCountOp(Runtime::FunctionId function_id,
void Interpreter::DoCountOp(Callable callable,
InterpreterAssembler* assembler) {
Node* target = __ HeapConstant(callable.code());
Node* value = __ GetAccumulator();
Node* one = __ NumberConstant(1);
Node* context = __ GetContext();
Node* result = __ CallRuntime(function_id, context, value, one);
Node* result = __ CallStub(callable.descriptor(), target, context, value);
__ SetAccumulator(result);
__ Dispatch();
}
......@@ -829,7 +829,7 @@ void Interpreter::DoCountOp(Runtime::FunctionId function_id,
//
// Increments value in the accumulator by one.
void Interpreter::DoInc(InterpreterAssembler* assembler) {
DoCountOp(Runtime::kAdd, assembler);
DoCountOp(CodeFactory::Inc(isolate_), assembler);
}
......@@ -837,7 +837,7 @@ void Interpreter::DoInc(InterpreterAssembler* assembler) {
//
// Decrements value in the accumulator by one.
void Interpreter::DoDec(InterpreterAssembler* assembler) {
DoCountOp(Runtime::kSubtract, assembler);
DoCountOp(CodeFactory::Dec(isolate_), assembler);
}
......
......@@ -81,9 +81,8 @@ class Interpreter {
template <class Generator>
void DoBinaryOp(InterpreterAssembler* assembler);
// Generates code to perform the count operations via |function_id|.
void DoCountOp(Runtime::FunctionId function_id,
InterpreterAssembler* assembler);
// Generates code to perform the count operations via |callable|.
void DoCountOp(Callable callable, InterpreterAssembler* assembler);
// Generates code to perform the comparison operation associated with
// |compare_op|.
......@@ -128,7 +127,7 @@ class Interpreter {
// Generates code to perform a type conversion.
void DoTypeConversionOp(Callable callable, InterpreterAssembler* assembler);
// Generates code ro create a literal via |function_id|.
// Generates code to create a literal via |function_id|.
void DoCreateLiteral(Runtime::FunctionId function_id,
InterpreterAssembler* assembler);
......
......@@ -316,6 +316,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -315,6 +315,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -313,6 +313,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -276,6 +276,12 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3, r2};
......
......@@ -312,6 +312,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -319,6 +319,11 @@ void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void CountOpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void StringAddDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
......
......@@ -247,7 +247,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 38
bytecode array length: 37
bytecodes: [
B(StackCheck),
B(LdaSmi), U8(17),
......@@ -266,7 +266,6 @@ bytecodes: [
B(Add), R(2),
B(Star), R(3),
B(Ldar), R(0),
B(ToNumber),
B(Inc),
B(Star), R(0),
B(Add), R(3),
......
......@@ -684,7 +684,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 35
bytecode array length: 34
bytecodes: [
B(StackCheck),
B(LdaSmi), U8(1),
......@@ -692,7 +692,7 @@ bytecodes: [
B(LdaSmi), U8(10),
B(Star), R(1),
B(Ldar), R(1),
B(JumpIfToBooleanFalse), U8(21),
B(JumpIfToBooleanFalse), U8(20),
B(StackCheck),
B(Ldar), R(0),
B(Star), R(2),
......@@ -700,10 +700,9 @@ bytecodes: [
B(Mul), R(2),
B(Star), R(0),
B(Ldar), R(1),
B(ToNumber),
B(Dec),
B(Star), R(1),
B(Jump), U8(-21),
B(Jump), U8(-20),
B(Ldar), R(0),
B(Return),
]
......@@ -748,7 +747,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 39
bytecode array length: 38
bytecodes: [
B(StackCheck),
B(LdaZero),
......@@ -765,12 +764,11 @@ bytecodes: [
B(LdaSmi), U8(20),
B(TestEqual), R(2),
B(JumpIfFalse), U8(4),
B(Jump), U8(10),
B(Jump), U8(9),
B(Ldar), R(1),
B(ToNumber),
B(Inc),
B(Star), R(1),
B(Jump), U8(-27),
B(Jump), U8(-26),
B(Ldar), R(0),
B(Return),
]
......
......@@ -52,7 +52,7 @@ snippet: "
"
frame size: 5
parameter count: 1
bytecode array length: 75
bytecode array length: 72
bytecodes: [
B(StackCheck),
B(LdaZero),
......@@ -63,7 +63,7 @@ bytecodes: [
B(Star), R(3),
B(LdaSmi), U8(10),
B(TestLessThan), R(3),
B(JumpIfFalse), U8(57),
B(JumpIfFalse), U8(54),
B(StackCheck),
B(LdaZero),
B(Star), R(2),
......@@ -71,10 +71,9 @@ bytecodes: [
B(Star), R(3),
B(LdaSmi), U8(3),
B(TestLessThan), R(3),
B(JumpIfFalse), U8(35),
B(JumpIfFalse), U8(33),
B(StackCheck),
B(Ldar), R(0),
B(ToNumber),
B(Inc),
B(Star), R(0),
B(Ldar), R(1),
......@@ -85,17 +84,15 @@ bytecodes: [
B(LdaSmi), U8(12),
B(TestEqual), R(4),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Jump), U8(16),
B(Ldar), R(2),
B(ToNumber),
B(Inc),
B(Star), R(2),
B(Jump), U8(-41),
B(Jump), U8(-39),
B(Ldar), R(1),
B(ToNumber),
B(Inc),
B(Star), R(1),
B(Jump), U8(-63),
B(Jump), U8(-60),
B(Ldar), R(0),
B(Return),
]
......
......@@ -13,12 +13,11 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecode array length: 9
bytecodes: [
B(StackCheck),
B(LdaSmi), U8(1),
B(Star), R(0),
B(ToNumber),
B(Inc),
B(Star), R(0),
B(Return),
......@@ -57,12 +56,11 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecode array length: 9
bytecodes: [
B(StackCheck),
B(LdaSmi), U8(1),
B(Star), R(0),
B(ToNumber),
B(Dec),
B(Star), R(0),
B(Return),
......@@ -129,7 +127,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 22
bytecode array length: 21
bytecodes: [
B(StackCheck),
B(CreateObjectLiteral), U8(0), U8(0), U8(5),
......@@ -137,7 +135,6 @@ bytecodes: [
B(Star), R(0),
B(Star), R(1),
B(LoadIC), R(1), U8(1), U8(1),
B(ToNumber),
B(Dec),
B(StoreICSloppy), R(1), U8(1), U8(3),
B(Return),
......@@ -187,7 +184,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 29
bytecode array length: 28
bytecodes: [
B(StackCheck),
B(LdaConstant), U8(0),
......@@ -199,7 +196,6 @@ bytecodes: [
B(Ldar), R(0),
B(Star), R(3),
B(KeyedLoadIC), R(2), U8(1),
B(ToNumber),
B(Inc),
B(KeyedStoreICSloppy), R(2), R(3), U8(3),
B(Return),
......@@ -217,7 +213,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 27
bytecode array length: 26
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(1),
......@@ -227,7 +223,6 @@ bytecodes: [
B(CreateClosure), U8(0), U8(0),
B(Star), R(0),
B(LdaContextSlot), R(context), U8(4),
B(ToNumber),
B(Inc),
B(StaContextSlot), R(context), U8(4),
B(Return),
......
......@@ -53,13 +53,12 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 26
bytecode array length: 25
bytecodes: [
B(StackCheck),
B(StackCheck),
B(LdaSmi), U8(10),
B(Star), R(1),
B(ToNumber),
B(Inc),
B(Star), R(1),
B(Star), R(0),
......@@ -68,7 +67,7 @@ bytecodes: [
B(Star), R(1),
B(LdaSmi), U8(20),
B(Star), R(1),
B(Jump), U8(-21),
B(Jump), U8(-20),
B(LdaUndefined),
B(Return),
]
......
......@@ -16,11 +16,10 @@ snippet: "
"
frame size: 0
parameter count: 1
bytecode array length: 10
bytecode array length: 9
bytecodes: [
B(StackCheck),
B(LdaGlobal), U8(0), U8(1),
B(ToNumber),
B(Inc),
B(StaGlobalSloppy), U8(0), U8(3),
B(Return),
......@@ -64,11 +63,10 @@ snippet: "
"
frame size: 0
parameter count: 1
bytecode array length: 10
bytecode array length: 9
bytecodes: [
B(StackCheck),
B(LdaGlobal), U8(0), U8(1),
B(ToNumber),
B(Dec),
B(StaGlobalStrict), U8(0), U8(3),
B(Return),
......
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