[Interpreter] Add intrinsics called as stubs.
Adds support for intrinsics which can be called as stubs. Namely: - HasProperty - MathPow - NewObject - NumberToString - RegExpConstructResult - RegExpExec - Substring - ToString - ToName - ToLength - ToNumber - ToObject Also adds interface descriptors for stub calls which have arguments passed on the stack. BUG=v8:4280 LOG=N Review-Url: https://codereview.chromium.org/2051573002 Cr-Commit-Position: refs/heads/master@{#37185}
This commit is contained in:
parent
7a88ff3cc0
commit
485e77519f
@ -554,6 +554,12 @@ Callable CodeFactory::HasProperty(Isolate* isolate) {
|
|||||||
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
Callable CodeFactory::MathPow(Isolate* isolate) {
|
||||||
|
MathPowStub stub(isolate, MathPowStub::ON_STACK);
|
||||||
|
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
|
Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
|
||||||
TailCallMode tail_call_mode) {
|
TailCallMode tail_call_mode) {
|
||||||
|
@ -146,6 +146,8 @@ class CodeFactory final {
|
|||||||
static Callable ConstructFunction(Isolate* isolate);
|
static Callable ConstructFunction(Isolate* isolate);
|
||||||
static Callable HasProperty(Isolate* isolate);
|
static Callable HasProperty(Isolate* isolate);
|
||||||
|
|
||||||
|
static Callable MathPow(Isolate* isolate);
|
||||||
|
|
||||||
static Callable InterpreterPushArgsAndCall(Isolate* isolate,
|
static Callable InterpreterPushArgsAndCall(Isolate* isolate,
|
||||||
TailCallMode tail_call_mode);
|
TailCallMode tail_call_mode);
|
||||||
static Callable InterpreterPushArgsAndConstruct(Isolate* isolate);
|
static Callable InterpreterPushArgsAndConstruct(Isolate* isolate);
|
||||||
|
@ -434,6 +434,12 @@ class CodeStub BASE_EMBEDDED {
|
|||||||
return NAME##Descriptor(isolate()); \
|
return NAME##Descriptor(isolate()); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DEFINE_ON_STACK_CALL_INTERFACE_DESCRIPTOR(PARAMETER_COUNT) \
|
||||||
|
public: \
|
||||||
|
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
|
||||||
|
return OnStackArgsDescriptorBase::ForArgs(isolate(), PARAMETER_COUNT); \
|
||||||
|
}
|
||||||
|
|
||||||
// There are some code stubs we just can't describe right now with a
|
// There are some code stubs we just can't describe right now with a
|
||||||
// CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
|
// CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
|
||||||
// An attempt to retrieve a descriptor will fail.
|
// An attempt to retrieve a descriptor will fail.
|
||||||
@ -1328,14 +1334,18 @@ class MathPowStub: public PlatformCodeStub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
|
CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
|
||||||
if (exponent_type() == TAGGED) {
|
if (exponent_type() == ON_STACK) {
|
||||||
|
return OnStackArgsDescriptorBase::ForArgs(isolate(), 2);
|
||||||
|
} else if (exponent_type() == TAGGED) {
|
||||||
return MathPowTaggedDescriptor(isolate());
|
return MathPowTaggedDescriptor(isolate());
|
||||||
} else if (exponent_type() == INTEGER) {
|
} else if (exponent_type() == INTEGER) {
|
||||||
return MathPowIntegerDescriptor(isolate());
|
return MathPowIntegerDescriptor(isolate());
|
||||||
}
|
} else {
|
||||||
// A CallInterfaceDescriptor doesn't specify double registers (yet).
|
// A CallInterfaceDescriptor doesn't specify double registers (yet).
|
||||||
|
DCHECK_EQ(DOUBLE, exponent_type());
|
||||||
return ContextOnlyDescriptor(isolate());
|
return ContextOnlyDescriptor(isolate());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ExponentType exponent_type() const {
|
ExponentType exponent_type() const {
|
||||||
@ -2083,7 +2093,7 @@ class RegExpExecStub: public PlatformCodeStub {
|
|||||||
public:
|
public:
|
||||||
explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
|
explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
|
||||||
|
|
||||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
|
DEFINE_ON_STACK_CALL_INTERFACE_DESCRIPTOR(4);
|
||||||
DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
|
DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3068,7 +3078,7 @@ class SubStringStub : public PlatformCodeStub {
|
|||||||
public:
|
public:
|
||||||
explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
||||||
|
|
||||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
|
DEFINE_ON_STACK_CALL_INTERFACE_DESCRIPTOR(3);
|
||||||
DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
|
DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -415,6 +415,12 @@ Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
|
|||||||
result_size);
|
result_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* CodeAssembler::CallStubN(Callable const& callable, Node** args,
|
||||||
|
size_t result_size) {
|
||||||
|
Node* target = HeapConstant(callable.code());
|
||||||
|
return CallStubN(callable.descriptor(), target, args, result_size);
|
||||||
|
}
|
||||||
|
|
||||||
Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
|
Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
|
||||||
Node* target, Node* context, Node* arg1,
|
Node* target, Node* context, Node* arg1,
|
||||||
size_t result_size) {
|
size_t result_size) {
|
||||||
@ -502,6 +508,16 @@ Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
|
|||||||
return CallN(call_descriptor, target, args);
|
return CallN(call_descriptor, target, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
|
||||||
|
Node* target, Node** args, size_t result_size) {
|
||||||
|
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
|
||||||
|
isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
|
||||||
|
CallDescriptor::kNoFlags, Operator::kNoProperties,
|
||||||
|
MachineType::AnyTagged(), result_size);
|
||||||
|
|
||||||
|
return CallN(call_descriptor, target, args);
|
||||||
|
}
|
||||||
|
|
||||||
Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
|
Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
|
||||||
Node* arg1, Node* arg2, size_t result_size) {
|
Node* arg1, Node* arg2, size_t result_size) {
|
||||||
Node* target = HeapConstant(callable.code());
|
Node* target = HeapConstant(callable.code());
|
||||||
|
@ -311,6 +311,8 @@ class CodeAssembler {
|
|||||||
Node* arg2, size_t result_size = 1);
|
Node* arg2, size_t result_size = 1);
|
||||||
Node* CallStub(Callable const& callable, Node* context, Node* arg1,
|
Node* CallStub(Callable const& callable, Node* context, Node* arg1,
|
||||||
Node* arg2, Node* arg3, size_t result_size = 1);
|
Node* arg2, Node* arg3, size_t result_size = 1);
|
||||||
|
Node* CallStubN(Callable const& callable, Node** args,
|
||||||
|
size_t result_size = 1);
|
||||||
|
|
||||||
Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
|
Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
|
||||||
Node* context, Node* arg1, size_t result_size = 1);
|
Node* context, Node* arg1, size_t result_size = 1);
|
||||||
@ -325,6 +327,8 @@ class CodeAssembler {
|
|||||||
Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
|
Node* CallStub(const CallInterfaceDescriptor& descriptor, Node* target,
|
||||||
Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
|
Node* context, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
|
||||||
Node* arg5, size_t result_size = 1);
|
Node* arg5, size_t result_size = 1);
|
||||||
|
Node* CallStubN(const CallInterfaceDescriptor& descriptor, Node* target,
|
||||||
|
Node** args, size_t result_size = 1);
|
||||||
|
|
||||||
Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
|
Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
|
||||||
Node* arg2, size_t result_size = 1);
|
Node* arg2, size_t result_size = 1);
|
||||||
|
@ -214,7 +214,6 @@ void MathPowTaggedDescriptor::InitializePlatformSpecific(
|
|||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MathPowIntegerDescriptor::InitializePlatformSpecific(
|
void MathPowIntegerDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {exponent()};
|
Register registers[] = {exponent()};
|
||||||
@ -321,6 +320,48 @@ void ContextOnlyDescriptor::InitializePlatformSpecific(
|
|||||||
data->InitializePlatformSpecific(0, nullptr);
|
data->InitializePlatformSpecific(0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallInterfaceDescriptor OnStackArgsDescriptorBase::ForArgs(
|
||||||
|
Isolate* isolate, int parameter_count) {
|
||||||
|
switch (parameter_count) {
|
||||||
|
case 1:
|
||||||
|
return OnStackWith1ArgsDescriptor(isolate);
|
||||||
|
case 2:
|
||||||
|
return OnStackWith2ArgsDescriptor(isolate);
|
||||||
|
case 3:
|
||||||
|
return OnStackWith3ArgsDescriptor(isolate);
|
||||||
|
case 4:
|
||||||
|
return OnStackWith4ArgsDescriptor(isolate);
|
||||||
|
case 5:
|
||||||
|
return OnStackWith5ArgsDescriptor(isolate);
|
||||||
|
case 6:
|
||||||
|
return OnStackWith6ArgsDescriptor(isolate);
|
||||||
|
case 7:
|
||||||
|
return OnStackWith7ArgsDescriptor(isolate);
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return VoidDescriptor(isolate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionType*
|
||||||
|
OnStackArgsDescriptorBase::BuildCallInterfaceDescriptorFunctionTypeWithArg(
|
||||||
|
Isolate* isolate, int register_parameter_count, int parameter_count) {
|
||||||
|
DCHECK_EQ(0, register_parameter_count);
|
||||||
|
DCHECK_GT(parameter_count, 0);
|
||||||
|
Zone* zone = isolate->interface_descriptor_zone();
|
||||||
|
FunctionType* function =
|
||||||
|
Type::Function(AnyTagged(zone), AnyTagged(zone), parameter_count, zone)
|
||||||
|
->AsFunction();
|
||||||
|
for (int i = 0; i < parameter_count; i++) {
|
||||||
|
function->InitParameter(i, AnyTagged(zone));
|
||||||
|
}
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnStackArgsDescriptorBase::InitializePlatformSpecific(
|
||||||
|
CallInterfaceDescriptorData* data) {
|
||||||
|
data->InitializePlatformSpecific(0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void GrowArrayElementsDescriptor::InitializePlatformSpecific(
|
void GrowArrayElementsDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
|
@ -15,6 +15,14 @@ class PlatformInterfaceDescriptor;
|
|||||||
|
|
||||||
#define INTERFACE_DESCRIPTOR_LIST(V) \
|
#define INTERFACE_DESCRIPTOR_LIST(V) \
|
||||||
V(Void) \
|
V(Void) \
|
||||||
|
V(ContextOnly) \
|
||||||
|
V(OnStackWith1Args) \
|
||||||
|
V(OnStackWith2Args) \
|
||||||
|
V(OnStackWith3Args) \
|
||||||
|
V(OnStackWith4Args) \
|
||||||
|
V(OnStackWith5Args) \
|
||||||
|
V(OnStackWith6Args) \
|
||||||
|
V(OnStackWith7Args) \
|
||||||
V(Load) \
|
V(Load) \
|
||||||
V(LoadGlobal) \
|
V(LoadGlobal) \
|
||||||
V(LoadGlobalWithVector) \
|
V(LoadGlobalWithVector) \
|
||||||
@ -84,7 +92,6 @@ class PlatformInterfaceDescriptor;
|
|||||||
V(StoreGlobalViaContext) \
|
V(StoreGlobalViaContext) \
|
||||||
V(MathPowTagged) \
|
V(MathPowTagged) \
|
||||||
V(MathPowInteger) \
|
V(MathPowInteger) \
|
||||||
V(ContextOnly) \
|
|
||||||
V(GrowArrayElements) \
|
V(GrowArrayElements) \
|
||||||
V(InterpreterDispatch) \
|
V(InterpreterDispatch) \
|
||||||
V(InterpreterPushArgsAndCall) \
|
V(InterpreterPushArgsAndCall) \
|
||||||
@ -278,6 +285,77 @@ class VoidDescriptor : public CallInterfaceDescriptor {
|
|||||||
DECLARE_DESCRIPTOR(VoidDescriptor, CallInterfaceDescriptor)
|
DECLARE_DESCRIPTOR(VoidDescriptor, CallInterfaceDescriptor)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ContextOnlyDescriptor : public CallInterfaceDescriptor {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
|
||||||
|
};
|
||||||
|
|
||||||
|
// The OnStackWith*ArgsDescriptors have a lot of boilerplate. The superclass
|
||||||
|
// OnStackArgsDescriptorBase is not meant to be instantiated directly and has no
|
||||||
|
// public constructors to ensure this is so.contains all the logic, and the
|
||||||
|
//
|
||||||
|
// Use OnStackArgsDescriptorBase::ForArgs(isolate, parameter_count) to
|
||||||
|
// instantiate a descriptor with the number of args.
|
||||||
|
class OnStackArgsDescriptorBase : public CallInterfaceDescriptor {
|
||||||
|
public:
|
||||||
|
static CallInterfaceDescriptor ForArgs(Isolate* isolate, int parameter_count);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OnStackArgsDescriptorBase(Isolate* isolate, CallDescriptors::Key key)
|
||||||
|
: CallInterfaceDescriptor(isolate, key) {}
|
||||||
|
void InitializePlatformSpecific(CallInterfaceDescriptorData* data) override;
|
||||||
|
FunctionType* BuildCallInterfaceDescriptorFunctionTypeWithArg(
|
||||||
|
Isolate* isolate, int register_parameter_count, int parameter_count);
|
||||||
|
};
|
||||||
|
|
||||||
|
class OnStackWith1ArgsDescriptor : public OnStackArgsDescriptorBase {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith1ArgsDescriptor,
|
||||||
|
OnStackArgsDescriptorBase,
|
||||||
|
1)
|
||||||
|
};
|
||||||
|
|
||||||
|
class OnStackWith2ArgsDescriptor : public OnStackArgsDescriptorBase {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith2ArgsDescriptor,
|
||||||
|
OnStackArgsDescriptorBase,
|
||||||
|
2)
|
||||||
|
};
|
||||||
|
|
||||||
|
class OnStackWith3ArgsDescriptor : public OnStackArgsDescriptorBase {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith3ArgsDescriptor,
|
||||||
|
OnStackArgsDescriptorBase,
|
||||||
|
3)
|
||||||
|
};
|
||||||
|
|
||||||
|
class OnStackWith4ArgsDescriptor : public OnStackArgsDescriptorBase {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith4ArgsDescriptor,
|
||||||
|
OnStackArgsDescriptorBase,
|
||||||
|
4)
|
||||||
|
};
|
||||||
|
|
||||||
|
class OnStackWith5ArgsDescriptor : public OnStackArgsDescriptorBase {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith5ArgsDescriptor,
|
||||||
|
OnStackArgsDescriptorBase,
|
||||||
|
5)
|
||||||
|
};
|
||||||
|
|
||||||
|
class OnStackWith6ArgsDescriptor : public OnStackArgsDescriptorBase {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith6ArgsDescriptor,
|
||||||
|
OnStackArgsDescriptorBase,
|
||||||
|
6)
|
||||||
|
};
|
||||||
|
|
||||||
|
class OnStackWith7ArgsDescriptor : public OnStackArgsDescriptorBase {
|
||||||
|
public:
|
||||||
|
DECLARE_DESCRIPTOR_WITH_BASE_AND_FUNCTION_TYPE_ARG(OnStackWith7ArgsDescriptor,
|
||||||
|
OnStackArgsDescriptorBase,
|
||||||
|
7)
|
||||||
|
};
|
||||||
|
|
||||||
// LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs.
|
// LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs.
|
||||||
class LoadDescriptor : public CallInterfaceDescriptor {
|
class LoadDescriptor : public CallInterfaceDescriptor {
|
||||||
@ -774,7 +852,6 @@ class ApiGetterDescriptor : public CallInterfaceDescriptor {
|
|||||||
static const Register CallbackRegister();
|
static const Register CallbackRegister();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
|
class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
|
||||||
public:
|
public:
|
||||||
DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor)
|
DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor)
|
||||||
@ -782,7 +859,6 @@ class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
|
|||||||
static const Register exponent();
|
static const Register exponent();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
|
class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
|
||||||
public:
|
public:
|
||||||
DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor)
|
DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor)
|
||||||
@ -790,12 +866,6 @@ class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
|
|||||||
static const Register exponent();
|
static const Register exponent();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ContextOnlyDescriptor : public CallInterfaceDescriptor {
|
|
||||||
public:
|
|
||||||
DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
|
|
||||||
};
|
|
||||||
|
|
||||||
class VarArgFunctionDescriptor : public CallInterfaceDescriptor {
|
class VarArgFunctionDescriptor : public CallInterfaceDescriptor {
|
||||||
public:
|
public:
|
||||||
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(VarArgFunctionDescriptor,
|
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(VarArgFunctionDescriptor,
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "src/interpreter/interpreter-intrinsics.h"
|
#include "src/interpreter/interpreter-intrinsics.h"
|
||||||
|
|
||||||
|
#include "src/code-factory.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
namespace interpreter {
|
namespace interpreter {
|
||||||
@ -13,7 +15,9 @@ using compiler::Node;
|
|||||||
#define __ assembler_->
|
#define __ assembler_->
|
||||||
|
|
||||||
IntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler)
|
IntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler)
|
||||||
: assembler_(assembler) {}
|
: isolate_(assembler->isolate()),
|
||||||
|
zone_(assembler->zone()),
|
||||||
|
assembler_(assembler) {}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
|
bool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
|
||||||
@ -227,6 +231,80 @@ Node* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) {
|
|||||||
return return_value.value();
|
return return_value.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::IntrinsicAsStubCall(Node* args_reg, Node* context,
|
||||||
|
Callable const& callable) {
|
||||||
|
int param_count = callable.descriptor().GetParameterCount();
|
||||||
|
Node** args = zone()->NewArray<Node*>(param_count + 1); // 1 for context
|
||||||
|
for (int i = 0; i < param_count; i++) {
|
||||||
|
args[i] = __ LoadRegister(args_reg);
|
||||||
|
args_reg = __ NextRegister(args_reg);
|
||||||
|
}
|
||||||
|
args[param_count] = context;
|
||||||
|
|
||||||
|
return __ CallStubN(callable, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::HasProperty(Node* input, Node* arg_count,
|
||||||
|
Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context,
|
||||||
|
CodeFactory::HasProperty(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::MathPow(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::MathPow(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::NewObject(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context,
|
||||||
|
CodeFactory::FastNewObject(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::NumberToString(Node* input, Node* arg_count,
|
||||||
|
Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context,
|
||||||
|
CodeFactory::NumberToString(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::RegExpConstructResult(Node* input, Node* arg_count,
|
||||||
|
Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context,
|
||||||
|
CodeFactory::RegExpConstructResult(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::RegExpExec(Node* input, Node* arg_count,
|
||||||
|
Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context,
|
||||||
|
CodeFactory::RegExpExec(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::SubString(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::SubString(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::ToString(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::ToString(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::ToName(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::ToName(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::ToLength(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::ToLength(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::ToInteger(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::ToInteger(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::ToNumber(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::ToNumber(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* IntrinsicsHelper::ToObject(Node* input, Node* arg_count, Node* context) {
|
||||||
|
return IntrinsicAsStubCall(input, context, CodeFactory::ToObject(isolate()));
|
||||||
|
}
|
||||||
|
|
||||||
Node* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) {
|
Node* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) {
|
||||||
// First argument register contains the function target.
|
// First argument register contains the function target.
|
||||||
Node* function = __ LoadRegister(args_reg);
|
Node* function = __ LoadRegister(args_reg);
|
||||||
|
@ -26,12 +26,25 @@ namespace interpreter {
|
|||||||
// expected number of arguments (-1 denoting argument count is variable).
|
// expected number of arguments (-1 denoting argument count is variable).
|
||||||
#define INTRINSICS_LIST(V) \
|
#define INTRINSICS_LIST(V) \
|
||||||
V(Call, call, -1) \
|
V(Call, call, -1) \
|
||||||
|
V(HasProperty, has_property, 2) \
|
||||||
V(IsArray, is_array, 1) \
|
V(IsArray, is_array, 1) \
|
||||||
V(IsJSProxy, is_js_proxy, 1) \
|
V(IsJSProxy, is_js_proxy, 1) \
|
||||||
V(IsJSReceiver, is_js_receiver, 1) \
|
V(IsJSReceiver, is_js_receiver, 1) \
|
||||||
V(IsRegExp, is_regexp, 1) \
|
V(IsRegExp, is_regexp, 1) \
|
||||||
V(IsSmi, is_smi, 1) \
|
V(IsSmi, is_smi, 1) \
|
||||||
V(IsTypedArray, is_typed_array, 1)
|
V(IsTypedArray, is_typed_array, 1) \
|
||||||
|
V(MathPow, math_pow, 2) \
|
||||||
|
V(NewObject, new_object, 2) \
|
||||||
|
V(NumberToString, number_to_string, 1) \
|
||||||
|
V(RegExpConstructResult, reg_exp_construct_result, 3) \
|
||||||
|
V(RegExpExec, reg_exp_exec, 4) \
|
||||||
|
V(SubString, sub_string, 3) \
|
||||||
|
V(ToString, to_string, 1) \
|
||||||
|
V(ToName, to_name, 1) \
|
||||||
|
V(ToLength, to_length, 1) \
|
||||||
|
V(ToInteger, to_integer, 1) \
|
||||||
|
V(ToNumber, to_number, 1) \
|
||||||
|
V(ToObject, to_object, 1)
|
||||||
|
|
||||||
class IntrinsicsHelper {
|
class IntrinsicsHelper {
|
||||||
public:
|
public:
|
||||||
@ -63,6 +76,9 @@ class IntrinsicsHelper {
|
|||||||
compiler::Node* IsInstanceType(compiler::Node* input, int type);
|
compiler::Node* IsInstanceType(compiler::Node* input, int type);
|
||||||
compiler::Node* CompareInstanceType(compiler::Node* map, int type,
|
compiler::Node* CompareInstanceType(compiler::Node* map, int type,
|
||||||
InstanceTypeCompareMode mode);
|
InstanceTypeCompareMode mode);
|
||||||
|
compiler::Node* IntrinsicAsStubCall(compiler::Node* input,
|
||||||
|
compiler::Node* context,
|
||||||
|
Callable const& callable);
|
||||||
void AbortIfArgCountMismatch(int expected, compiler::Node* actual);
|
void AbortIfArgCountMismatch(int expected, compiler::Node* actual);
|
||||||
|
|
||||||
#define DECLARE_INTRINSIC_HELPER(name, lower_case, count) \
|
#define DECLARE_INTRINSIC_HELPER(name, lower_case, count) \
|
||||||
@ -71,6 +87,11 @@ class IntrinsicsHelper {
|
|||||||
INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER)
|
INTRINSICS_LIST(DECLARE_INTRINSIC_HELPER)
|
||||||
#undef DECLARE_INTRINSIC_HELPER
|
#undef DECLARE_INTRINSIC_HELPER
|
||||||
|
|
||||||
|
Isolate* isolate() { return isolate_; }
|
||||||
|
Zone* zone() { return zone_; }
|
||||||
|
|
||||||
|
Isolate* isolate_;
|
||||||
|
Zone* zone_;
|
||||||
InterpreterAssembler* assembler_;
|
InterpreterAssembler* assembler_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(IntrinsicsHelper);
|
DISALLOW_COPY_AND_ASSIGN(IntrinsicsHelper);
|
||||||
|
@ -212,6 +212,47 @@ TEST(Call) {
|
|||||||
handle(Smi::FromInt(7), isolate), handle(Smi::FromInt(3), isolate)));
|
handle(Smi::FromInt(7), isolate), handle(Smi::FromInt(3), isolate)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(IntrinsicAsStubCall) {
|
||||||
|
HandleAndZoneScope handles;
|
||||||
|
Isolate* isolate = handles.main_isolate();
|
||||||
|
Factory* factory = isolate->factory();
|
||||||
|
InvokeIntrinsicHelper to_number_helper(isolate, handles.main_zone(),
|
||||||
|
Runtime::kInlineToNumber);
|
||||||
|
CHECK_EQ(Smi::FromInt(46),
|
||||||
|
*to_number_helper.Invoke(to_number_helper.NewObject("'46'")));
|
||||||
|
|
||||||
|
InvokeIntrinsicHelper to_integer_helper(isolate, handles.main_zone(),
|
||||||
|
Runtime::kInlineToInteger);
|
||||||
|
CHECK_EQ(Smi::FromInt(502),
|
||||||
|
*to_integer_helper.Invoke(to_integer_helper.NewObject("502.67")));
|
||||||
|
|
||||||
|
InvokeIntrinsicHelper math_pow_helper(isolate, handles.main_zone(),
|
||||||
|
Runtime::kInlineMathPow);
|
||||||
|
CHECK(math_pow_helper
|
||||||
|
.Invoke(math_pow_helper.NewObject("3"),
|
||||||
|
math_pow_helper.NewObject("7"))
|
||||||
|
->SameValue(Smi::FromInt(2187)));
|
||||||
|
|
||||||
|
InvokeIntrinsicHelper has_property_helper(isolate, handles.main_zone(),
|
||||||
|
Runtime::kInlineHasProperty);
|
||||||
|
CHECK_EQ(*factory->true_value(),
|
||||||
|
*has_property_helper.Invoke(
|
||||||
|
has_property_helper.NewObject("'x'"),
|
||||||
|
has_property_helper.NewObject("({ x: 20 })")));
|
||||||
|
CHECK_EQ(*factory->false_value(),
|
||||||
|
*has_property_helper.Invoke(
|
||||||
|
has_property_helper.NewObject("'y'"),
|
||||||
|
has_property_helper.NewObject("({ x: 20 })")));
|
||||||
|
|
||||||
|
InvokeIntrinsicHelper sub_string_helper(isolate, handles.main_zone(),
|
||||||
|
Runtime::kInlineSubString);
|
||||||
|
CHECK(sub_string_helper
|
||||||
|
.Invoke(sub_string_helper.NewObject("'foobar'"),
|
||||||
|
sub_string_helper.NewObject("3"),
|
||||||
|
sub_string_helper.NewObject("6"))
|
||||||
|
->SameValue(*sub_string_helper.NewObject("'bar'")));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace interpreter
|
} // namespace interpreter
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
Loading…
Reference in New Issue
Block a user