[runtime] Move binary operator fallbacks into the runtime.

Replace the ADD, SUB, etc. builtins with proper runtime implementations,
and expose them as runtime calls that can be used by the code stubs and
the interpreter (for now).

Also remove all the support runtime functions for ADD, SUB and friends,
namely %NumberAdd, %NumberSub, and so on.

R=mstarzinger@chromium.org
CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_layout_dbg,v8_linux_nosnap_dbg

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

Cr-Commit-Position: refs/heads/master@{#30680}
This commit is contained in:
bmeurer 2015-09-10 06:04:15 -07:00 committed by Commit bot
parent a1c1e2bd44
commit a1b2ec60b0
31 changed files with 746 additions and 609 deletions

View File

@ -1169,6 +1169,7 @@ source_set("v8_base") {
"src/runtime/runtime-numbers.cc",
"src/runtime/runtime-object.cc",
"src/runtime/runtime-observe.cc",
"src/runtime/runtime-operators.cc",
"src/runtime/runtime-proxy.cc",
"src/runtime/runtime-regexp.cc",
"src/runtime/runtime-scopes.cc",

View File

@ -231,7 +231,7 @@ void Accessors::ArrayLengthSetter(
}
Handle<Object> number_v;
if (!Object::ToNumber(isolate, length_obj).ToHandle(&number_v)) {
if (!Object::ToNumber(length_obj).ToHandle(&number_v)) {
isolate->OptionalRescheduleException(false);
return;
}

View File

@ -2920,8 +2920,7 @@ MaybeLocal<Number> Value::ToNumber(Local<Context> context) const {
if (obj->IsNumber()) return ToApiHandle<Number>(obj);
PREPARE_FOR_EXECUTION(context, "ToNumber", Number);
Local<Number> result;
has_pending_exception =
!ToLocal<Number>(i::Object::ToNumber(isolate, obj), &result);
has_pending_exception = !ToLocal<Number>(i::Object::ToNumber(obj), &result);
RETURN_ON_FAILED_EXECUTION(Number);
RETURN_ESCAPED(result);
}
@ -3245,7 +3244,7 @@ Maybe<double> Value::NumberValue(Local<Context> context) const {
if (obj->IsNumber()) return Just(obj->Number());
PREPARE_FOR_EXECUTION_PRIMITIVE(context, "NumberValue", double);
i::Handle<i::Object> num;
has_pending_exception = !i::Object::ToNumber(isolate, obj).ToHandle(&num);
has_pending_exception = !i::Object::ToNumber(obj).ToHandle(&num);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(double);
return Just(num->Number());
}

View File

@ -271,36 +271,10 @@ Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
}
Node* InterpreterAssembler::CallJSBuiltin(int context_index, Node* receiver,
Node** js_args, int js_arg_count) {
Node* global_object = LoadContextSlot(Context::GLOBAL_OBJECT_INDEX);
Node* native_context =
LoadObjectField(global_object, GlobalObject::kNativeContextOffset);
Node* function = LoadContextSlot(native_context, context_index);
Node* context = LoadObjectField(function, JSFunction::kContextOffset);
int index = 0;
Node** args = zone()->NewArray<Node*>(js_arg_count + 2);
args[index++] = receiver;
for (int i = 0; i < js_arg_count; i++) {
args[index++] = js_args[i];
}
args[index++] = context;
CallDescriptor* descriptor = Linkage::GetJSCallDescriptor(
zone(), false, js_arg_count + 1, CallDescriptor::kNoFlags);
return raw_assembler_->CallN(descriptor, function, args);
}
Node* InterpreterAssembler::CallJSBuiltin(int context_index, Node* receiver) {
return CallJSBuiltin(context_index, receiver, nullptr, 0);
}
Node* InterpreterAssembler::CallJSBuiltin(int context_index, Node* receiver,
Node* arg1) {
return CallJSBuiltin(context_index, receiver, &arg1, 1);
Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* arg1, Node* arg2) {
return raw_assembler_->CallRuntime2(function_id, arg1, arg2,
ContextTaggedPointer());
}

View File

@ -12,6 +12,7 @@
#include "src/builtins.h"
#include "src/frames.h"
#include "src/interpreter/bytecodes.h"
#include "src/runtime/runtime.h"
namespace v8 {
namespace internal {
@ -86,9 +87,8 @@ class InterpreterAssembler {
Node* CallIC(CallInterfaceDescriptor descriptor, Node* target, Node* arg1,
Node* arg2, Node* arg3, Node* arg4, Node* arg5);
// Call JS builtin.
Node* CallJSBuiltin(int context_index, Node* receiver);
Node* CallJSBuiltin(int context_index, Node* receiver, Node* arg1);
// Call runtime function.
Node* CallRuntime(Runtime::FunctionId function_id, Node* arg1, Node* arg2);
// Returns from the function.
void Return();

View File

@ -284,7 +284,7 @@ bool CallDescriptor::UsesOnlyRegisters() const {
CallDescriptor* Linkage::GetRuntimeCallDescriptor(
Zone* zone, Runtime::FunctionId function_id, int js_parameter_count,
Operator::Properties properties) {
Operator::Properties properties, bool needs_frame_state) {
const size_t function_count = 1;
const size_t num_args_count = 1;
const size_t context_count = 1;
@ -327,7 +327,8 @@ CallDescriptor* Linkage::GetRuntimeCallDescriptor(
locations.AddParam(regloc(kContextRegister));
types.AddParam(kMachAnyTagged);
CallDescriptor::Flags flags = Linkage::FrameStateInputCount(function_id) > 0
CallDescriptor::Flags flags =
needs_frame_state && (Linkage::FrameStateInputCount(function_id) > 0)
? CallDescriptor::kNeedsFrameState
: CallDescriptor::kNoFlags;

View File

@ -273,7 +273,7 @@ class Linkage : public ZoneObject {
CallDescriptor::Flags flags);
static CallDescriptor* GetRuntimeCallDescriptor(
Zone* zone, Runtime::FunctionId function, int parameter_count,
Operator::Properties properties);
Operator::Properties properties, bool needs_frame_state = true);
static CallDescriptor* GetStubCallDescriptor(
Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,

View File

@ -179,19 +179,36 @@ Node* RawMachineAssembler::CallFunctionStub0(Node* function, Node* receiver,
Node* RawMachineAssembler::CallRuntime1(Runtime::FunctionId function,
Node* arg0, Node* context,
Node* frame_state) {
Node* arg1, Node* context) {
CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
zone(), function, 1, Operator::kNoProperties);
zone(), function, 1, Operator::kNoProperties, false);
Node* centry = HeapConstant(CEntryStub(isolate(), 1).GetCode());
Node* ref = NewNode(
common()->ExternalConstant(ExternalReference(function, isolate())));
Node* arity = Int32Constant(1);
Node* call = graph()->NewNode(common()->Call(descriptor), centry, arg0, ref,
arity, context, frame_state, graph()->start(),
graph()->start());
Node* call =
graph()->NewNode(common()->Call(descriptor), centry, arg1, ref, arity,
context, graph()->start(), graph()->start());
schedule()->AddNode(CurrentBlock(), call);
return call;
}
Node* RawMachineAssembler::CallRuntime2(Runtime::FunctionId function,
Node* arg1, Node* arg2, Node* context) {
CallDescriptor* descriptor = Linkage::GetRuntimeCallDescriptor(
zone(), function, 2, Operator::kNoProperties, false);
Node* centry = HeapConstant(CEntryStub(isolate(), 1).GetCode());
Node* ref = NewNode(
common()->ExternalConstant(ExternalReference(function, isolate())));
Node* arity = Int32Constant(2);
Node* call =
graph()->NewNode(common()->Call(descriptor), centry, arg1, arg2, ref,
arity, context, graph()->start(), graph()->start());
schedule()->AddNode(CurrentBlock(), call);
return call;
}

View File

@ -485,9 +485,11 @@ class RawMachineAssembler {
// Call through CallFunctionStub with lazy deopt and frame-state.
Node* CallFunctionStub0(Node* function, Node* receiver, Node* context,
Node* frame_state, CallFunctionFlags flags);
// Call to a runtime function with zero arguments.
Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context,
Node* frame_state);
// Call to a runtime function with one arguments.
Node* CallRuntime1(Runtime::FunctionId function, Node* arg0, Node* context);
// Call to a runtime function with two arguments.
Node* CallRuntime2(Runtime::FunctionId function, Node* arg1, Node* arg2,
Node* context);
// Call to a C function with zero arguments.
Node* CallCFunction0(MachineType return_type, Node* function);
// Call to a C function with one parameter.

View File

@ -91,15 +91,7 @@ enum BindingFlags {
#define NATIVE_CONTEXT_JS_BUILTINS(V) \
V(ADD_BUILTIN_INDEX, JSFunction, add_builtin) \
V(ADD_STRONG_BUILTIN_INDEX, JSFunction, add_strong_builtin) \
V(APPLY_PREPARE_BUILTIN_INDEX, JSFunction, apply_prepare_builtin) \
V(BIT_AND_BUILTIN_INDEX, JSFunction, bit_and_builtin) \
V(BIT_AND_STRONG_BUILTIN_INDEX, JSFunction, bit_and_strong_builtin) \
V(BIT_OR_BUILTIN_INDEX, JSFunction, bit_or_builtin) \
V(BIT_OR_STRONG_BUILTIN_INDEX, JSFunction, bit_or_strong_builtin) \
V(BIT_XOR_BUILTIN_INDEX, JSFunction, bit_xor_builtin) \
V(BIT_XOR_STRONG_BUILTIN_INDEX, JSFunction, bit_xor_strong_builtin) \
V(CALL_FUNCTION_PROXY_AS_CONSTRUCTOR_BUILTIN_INDEX, JSFunction, \
call_function_proxy_as_constructor_builtin) \
V(CALL_NON_FUNCTION_AS_CONSTRUCTOR_BUILTIN_INDEX, JSFunction, \
@ -108,28 +100,14 @@ enum BindingFlags {
V(COMPARE_STRONG_BUILTIN_INDEX, JSFunction, compare_strong_builtin) \
V(CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, JSFunction, \
concat_iterable_to_array_builtin) \
V(DIV_BUILTIN_INDEX, JSFunction, div_builtin) \
V(DIV_STRONG_BUILTIN_INDEX, JSFunction, div_strong_builtin) \
V(EQUALS_BUILTIN_INDEX, JSFunction, equals_builtin) \
V(MOD_BUILTIN_INDEX, JSFunction, mod_builtin) \
V(MOD_STRONG_BUILTIN_INDEX, JSFunction, mod_strong_builtin) \
V(MUL_BUILTIN_INDEX, JSFunction, mul_builtin) \
V(MUL_STRONG_BUILTIN_INDEX, JSFunction, mul_strong_builtin) \
V(REFLECT_APPLY_PREPARE_BUILTIN_INDEX, JSFunction, \
reflect_apply_prepare_builtin) \
V(REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, JSFunction, \
reflect_construct_prepare_builtin) \
V(SAR_BUILTIN_INDEX, JSFunction, sar_builtin) \
V(SAR_STRONG_BUILTIN_INDEX, JSFunction, sar_strong_builtin) \
V(SHL_BUILTIN_INDEX, JSFunction, shl_builtin) \
V(SHL_STRONG_BUILTIN_INDEX, JSFunction, shl_strong_builtin) \
V(SHR_BUILTIN_INDEX, JSFunction, shr_builtin) \
V(SHR_STRONG_BUILTIN_INDEX, JSFunction, shr_strong_builtin) \
V(STACK_OVERFLOW_BUILTIN_INDEX, JSFunction, stack_overflow_builtin) \
V(STRING_ADD_LEFT_BUILTIN_INDEX, JSFunction, string_add_left_builtin) \
V(STRING_ADD_RIGHT_BUILTIN_INDEX, JSFunction, string_add_right_builtin) \
V(SUB_BUILTIN_INDEX, JSFunction, sub_builtin) \
V(SUB_STRONG_BUILTIN_INDEX, JSFunction, sub_strong_builtin)
V(STRING_ADD_RIGHT_BUILTIN_INDEX, JSFunction, string_add_right_builtin)
#define NATIVE_CONTEXT_IMPORTED_FIELDS(V) \

View File

@ -557,8 +557,7 @@ MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
MaybeHandle<Object> Execution::ToInt32(Isolate* isolate, Handle<Object> obj) {
ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(isolate, obj),
Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(obj), Object);
return isolate->factory()->NewNumberFromInt(DoubleToInt32(obj->Number()));
}
@ -574,8 +573,7 @@ MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
MaybeHandle<Object> Execution::ToUint32(Isolate* isolate, Handle<Object> obj) {
ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(isolate, obj),
Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(obj), Object);
return isolate->factory()->NewNumberFromUint(DoubleToUint32(obj->Number()));
}

View File

@ -11080,10 +11080,57 @@ HValue* HGraphBuilder::BuildBinaryOperation(
// inline several instructions (including the two pushes) for every tagged
// operation in optimized code, which is more expensive, than a stub call.
if (graph()->info()->IsStub() && is_non_primitive) {
HValue* function =
AddLoadJSBuiltin(BinaryOpIC::TokenToContextIndex(op, strength));
Runtime::FunctionId function_id;
switch (op) {
default:
UNREACHABLE();
case Token::ADD:
function_id =
is_strong(strength) ? Runtime::kAdd_Strong : Runtime::kAdd;
break;
case Token::SUB:
function_id = is_strong(strength) ? Runtime::kSubtract_Strong
: Runtime::kSubtract;
break;
case Token::MUL:
function_id = is_strong(strength) ? Runtime::kMultiply_Strong
: Runtime::kMultiply;
break;
case Token::DIV:
function_id =
is_strong(strength) ? Runtime::kDivide_Strong : Runtime::kDivide;
break;
case Token::MOD:
function_id =
is_strong(strength) ? Runtime::kModulus_Strong : Runtime::kModulus;
break;
case Token::BIT_OR:
function_id = is_strong(strength) ? Runtime::kBitwiseOr_Strong
: Runtime::kBitwiseOr;
break;
case Token::BIT_AND:
function_id = is_strong(strength) ? Runtime::kBitwiseAnd_Strong
: Runtime::kBitwiseAnd;
break;
case Token::BIT_XOR:
function_id = is_strong(strength) ? Runtime::kBitwiseXor_Strong
: Runtime::kBitwiseXor;
break;
case Token::SAR:
function_id = is_strong(strength) ? Runtime::kShiftRight_Strong
: Runtime::kShiftRight;
break;
case Token::SHR:
function_id = is_strong(strength) ? Runtime::kShiftRightLogical_Strong
: Runtime::kShiftRightLogical;
break;
case Token::SHL:
function_id = is_strong(strength) ? Runtime::kShiftLeft_Strong
: Runtime::kShiftLeft;
break;
}
Add<HPushArguments>(left, right);
instr = AddUncasted<HInvokeFunction>(function, 2);
instr = AddUncasted<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
} else {
if (is_strong(strength) && Token::IsBitOp(op)) {
// TODO(conradw): This is not efficient, but is necessary to prevent
@ -11133,7 +11180,7 @@ HValue* HGraphBuilder::BuildBinaryOperation(
instr = AddUncasted<HBitwise>(op, left, right, strength);
break;
case Token::BIT_OR: {
HValue* operand, *shift_amount;
HValue *operand, *shift_amount;
if (left_type->Is(Type::Signed32()) &&
right_type->Is(Type::Signed32()) &&
MatchRotateRight(left, right, &operand, &shift_amount)) {

View File

@ -2645,13 +2645,67 @@ MaybeHandle<Object> BinaryOpIC::Transition(
BinaryOpICState state(isolate(), target()->extra_ic_state());
// Compute the actual result using the builtin for the binary operation.
Object* builtin = isolate()->native_context()->get(
TokenToContextIndex(state.op(), state.strength()));
Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
Handle<Object> result;
switch (state.op()) {
default:
UNREACHABLE();
case Token::ADD:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result, Execution::Call(isolate(), function, left, 1, &right),
isolate(), result,
Object::Add(isolate(), left, right, state.strength()), Object);
break;
case Token::SUB:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::Subtract(isolate(), left, right, state.strength()), Object);
break;
case Token::MUL:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::Multiply(isolate(), left, right, state.strength()), Object);
break;
case Token::DIV:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::Divide(isolate(), left, right, state.strength()), Object);
break;
case Token::MOD:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::Modulus(isolate(), left, right, state.strength()), Object);
break;
case Token::BIT_OR:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::BitwiseOr(isolate(), left, right, state.strength()), Object);
break;
case Token::BIT_AND:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::BitwiseAnd(isolate(), left, right, state.strength()), Object);
break;
case Token::BIT_XOR:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::BitwiseXor(isolate(), left, right, state.strength()), Object);
break;
case Token::SAR:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::ShiftRight(isolate(), left, right, state.strength()), Object);
break;
case Token::SHR:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::ShiftRightLogical(isolate(), left, right, state.strength()),
Object);
break;
case Token::SHL:
ASSIGN_RETURN_ON_EXCEPTION(
isolate(), result,
Object::ShiftLeft(isolate(), left, right, state.strength()), Object);
break;
}
// Do not try to update the target if the code was marked for lazy
// deoptimization. (Since we do not relocate addresses in these
@ -2885,63 +2939,6 @@ RUNTIME_FUNCTION(Runtime_Unreachable) {
}
int BinaryOpIC::TokenToContextIndex(Token::Value op, Strength strength) {
if (is_strong(strength)) {
switch (op) {
default: UNREACHABLE();
case Token::ADD:
return Context::ADD_STRONG_BUILTIN_INDEX;
case Token::SUB:
return Context::SUB_STRONG_BUILTIN_INDEX;
case Token::MUL:
return Context::MUL_STRONG_BUILTIN_INDEX;
case Token::DIV:
return Context::DIV_STRONG_BUILTIN_INDEX;
case Token::MOD:
return Context::MOD_STRONG_BUILTIN_INDEX;
case Token::BIT_OR:
return Context::BIT_OR_STRONG_BUILTIN_INDEX;
case Token::BIT_AND:
return Context::BIT_AND_STRONG_BUILTIN_INDEX;
case Token::BIT_XOR:
return Context::BIT_XOR_STRONG_BUILTIN_INDEX;
case Token::SAR:
return Context::SAR_STRONG_BUILTIN_INDEX;
case Token::SHR:
return Context::SHR_STRONG_BUILTIN_INDEX;
case Token::SHL:
return Context::SHL_STRONG_BUILTIN_INDEX;
}
} else {
switch (op) {
default: UNREACHABLE();
case Token::ADD:
return Context::ADD_BUILTIN_INDEX;
case Token::SUB:
return Context::SUB_BUILTIN_INDEX;
case Token::MUL:
return Context::MUL_BUILTIN_INDEX;
case Token::DIV:
return Context::DIV_BUILTIN_INDEX;
case Token::MOD:
return Context::MOD_BUILTIN_INDEX;
case Token::BIT_OR:
return Context::BIT_OR_BUILTIN_INDEX;
case Token::BIT_AND:
return Context::BIT_AND_BUILTIN_INDEX;
case Token::BIT_XOR:
return Context::BIT_XOR_BUILTIN_INDEX;
case Token::SAR:
return Context::SAR_BUILTIN_INDEX;
case Token::SHR:
return Context::SHR_BUILTIN_INDEX;
case Token::SHL:
return Context::SHL_BUILTIN_INDEX;
}
}
}
Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
ToBooleanStub stub(isolate(), target()->extra_ic_state());
bool to_boolean_value = stub.UpdateStatus(object);

View File

@ -618,8 +618,6 @@ class BinaryOpIC : public IC {
public:
explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {}
static int TokenToContextIndex(Token::Value op, Strength strength);
MaybeHandle<Object> Transition(Handle<AllocationSite> allocation_site,
Handle<Object> left,
Handle<Object> right) WARN_UNUSED_RESULT;

View File

@ -269,14 +269,14 @@ void Interpreter::DoKeyedStoreIC(compiler::InterpreterAssembler* assembler) {
}
void Interpreter::DoBinaryOp(int builtin_context_index,
void Interpreter::DoBinaryOp(Runtime::FunctionId function_id,
compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy): Call ICs which back-patch bytecode with type specialized
// operations, instead of calling builtins directly.
Node* reg_index = __ BytecodeOperandReg(0);
Node* lhs = __ LoadRegister(reg_index);
Node* rhs = __ GetAccumulator();
Node* result = __ CallJSBuiltin(builtin_context_index, lhs, rhs);
Node* result = __ CallRuntime(function_id, lhs, rhs);
__ SetAccumulator(result);
__ Dispatch();
}
@ -286,7 +286,7 @@ void Interpreter::DoBinaryOp(int builtin_context_index,
//
// Add register <src> to accumulator.
void Interpreter::DoAdd(compiler::InterpreterAssembler* assembler) {
DoBinaryOp(Context::ADD_BUILTIN_INDEX, assembler);
DoBinaryOp(Runtime::kAdd, assembler);
}
@ -294,7 +294,7 @@ void Interpreter::DoAdd(compiler::InterpreterAssembler* assembler) {
//
// Subtract register <src> from accumulator.
void Interpreter::DoSub(compiler::InterpreterAssembler* assembler) {
DoBinaryOp(Context::SUB_BUILTIN_INDEX, assembler);
DoBinaryOp(Runtime::kSubtract, assembler);
}
@ -302,7 +302,7 @@ void Interpreter::DoSub(compiler::InterpreterAssembler* assembler) {
//
// Multiply accumulator by register <src>.
void Interpreter::DoMul(compiler::InterpreterAssembler* assembler) {
DoBinaryOp(Context::MUL_BUILTIN_INDEX, assembler);
DoBinaryOp(Runtime::kMultiply, assembler);
}
@ -310,7 +310,7 @@ void Interpreter::DoMul(compiler::InterpreterAssembler* assembler) {
//
// Divide register <src> by accumulator.
void Interpreter::DoDiv(compiler::InterpreterAssembler* assembler) {
DoBinaryOp(Context::DIV_BUILTIN_INDEX, assembler);
DoBinaryOp(Runtime::kDivide, assembler);
}
@ -318,7 +318,7 @@ void Interpreter::DoDiv(compiler::InterpreterAssembler* assembler) {
//
// Modulo register <src> by accumulator.
void Interpreter::DoMod(compiler::InterpreterAssembler* assembler) {
DoBinaryOp(Context::MOD_BUILTIN_INDEX, assembler);
DoBinaryOp(Runtime::kModulus, assembler);
}

View File

@ -11,6 +11,7 @@
#include "src/base/macros.h"
#include "src/builtins.h"
#include "src/interpreter/bytecodes.h"
#include "src/runtime/runtime.h"
namespace v8 {
namespace internal {
@ -48,8 +49,8 @@ class Interpreter {
BYTECODE_LIST(DECLARE_BYTECODE_HANDLER_GENERATOR)
#undef DECLARE_BYTECODE_HANDLER_GENERATOR
// Generates code to perform the binary operations via |binop_builtin|.
void DoBinaryOp(int builtin_context_index,
// Generates code to perform the binary operations via |function_id|.
void DoBinaryOp(Runtime::FunctionId function_id,
compiler::InterpreterAssembler* assembler);
// Generates code to perform a property load via |ic|.

View File

@ -386,8 +386,8 @@ BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue(
SerializeString(Handle<String>::cast(value));
} else if (class_name == isolate_->heap()->Number_string()) {
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate_, value, Object::ToNumber(isolate_, object), EXCEPTION);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate_, value, Object::ToNumber(object),
EXCEPTION);
if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
SerializeHeapNumber(Handle<HeapNumber>::cast(value));
} else if (class_name == isolate_->heap()->Boolean_string()) {

View File

@ -93,11 +93,12 @@ MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
// static
MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) {
MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
while (true) {
if (input->IsNumber()) {
return input;
}
Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
if (input->IsOddball()) {
return handle(Handle<Oddball>::cast(input)->to_number(), isolate);
}
@ -193,6 +194,203 @@ Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
}
// static
MaybeHandle<Object> Object::Multiply(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumber(lhs->Number() * rhs->Number());
}
// static
MaybeHandle<Object> Object::Divide(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumber(lhs->Number() / rhs->Number());
}
// static
MaybeHandle<Object> Object::Modulus(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumber(modulo(lhs->Number(), rhs->Number()));
}
// static
MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (lhs->IsNumber() && rhs->IsNumber()) {
return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
} else if (lhs->IsString() && rhs->IsString()) {
return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
Handle<String>::cast(rhs));
} else if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
if (lhs->IsString() || rhs->IsString()) {
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
Object);
return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
Handle<String>::cast(rhs));
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
}
// static
MaybeHandle<Object> Object::Subtract(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumber(lhs->Number() - rhs->Number());
}
// static
MaybeHandle<Object> Object::ShiftLeft(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs)
<< (NumberToUint32(*rhs) & 0x1F));
}
// static
MaybeHandle<Object> Object::ShiftRight(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) >>
(NumberToUint32(*rhs) & 0x1F));
}
// static
MaybeHandle<Object> Object::ShiftRightLogical(Isolate* isolate,
Handle<Object> lhs,
Handle<Object> rhs,
Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumberFromUint(NumberToUint32(*lhs) >>
(NumberToUint32(*rhs) & 0x1F));
}
// static
MaybeHandle<Object> Object::BitwiseAnd(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) &
NumberToInt32(*rhs));
}
// static
MaybeHandle<Object> Object::BitwiseOr(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) |
NumberToInt32(*rhs));
}
// static
MaybeHandle<Object> Object::BitwiseXor(Isolate* isolate, Handle<Object> lhs,
Handle<Object> rhs, Strength strength) {
if (!lhs->IsNumber() || !rhs->IsNumber()) {
if (is_strong(strength)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kStrongImplicitConversion),
Object);
}
ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
}
return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) ^
NumberToInt32(*rhs));
}
bool Object::IsPromise(Handle<Object> object) {
if (!object->IsJSObject()) return false;
auto js_object = Handle<JSObject>::cast(object);
@ -3416,8 +3614,7 @@ MaybeHandle<Object> Object::SetDataProperty(LookupIterator* it,
if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), to_assign,
Object::ToNumber(it->isolate(), value),
Object);
Object::ToNumber(value), Object);
// ToNumber above might modify the receiver, causing the cached
// holder_map to mismatch the actual holder->map() after this point.
// Reload the map to be in consistent state. Other cached state cannot

View File

@ -1102,8 +1102,7 @@ class Object {
Handle<Object> input, ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
// ES6 section 7.1.3 ToNumber
MUST_USE_RESULT static MaybeHandle<Object> ToNumber(Isolate* isolate,
Handle<Object> input);
MUST_USE_RESULT static MaybeHandle<Object> ToNumber(Handle<Object> input);
// ES6 section 7.1.12 ToString
MUST_USE_RESULT static MaybeHandle<String> ToString(Isolate* isolate,
@ -1116,6 +1115,47 @@ class Object {
// ES6 section 12.5.6 The typeof Operator
static Handle<String> TypeOf(Isolate* isolate, Handle<Object> object);
// ES6 section 12.6 Multiplicative Operators
MUST_USE_RESULT static MaybeHandle<Object> Multiply(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> Divide(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> Modulus(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
// ES6 section 12.7 Additive Operators
MUST_USE_RESULT static MaybeHandle<Object> Add(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> Subtract(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
// ES6 section 12.8 Bitwise Shift Operators
MUST_USE_RESULT static MaybeHandle<Object> ShiftLeft(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> ShiftRight(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> ShiftRightLogical(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
// ES6 section 12.11 Binary Bitwise Operators
MUST_USE_RESULT static MaybeHandle<Object> BitwiseAnd(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> BitwiseOr(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> BitwiseXor(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
MUST_USE_RESULT static MaybeHandle<Object> GetProperty(
LookupIterator* it, LanguageMode language_mode = SLOPPY);

View File

@ -156,35 +156,6 @@ function COMPARE_STRONG(x, ncr) {
-----------------------------------
*/
// ECMA-262, section 11.6.1, page 50.
function ADD(x) {
// Fast case: Check for number operands and do the addition.
if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
// Default implementation.
var a = %to_primitive(this, NO_HINT);
var b = %to_primitive(x, NO_HINT);
if (IS_STRING(a)) {
return %_StringAdd(a, %to_string_fun(b));
} else if (IS_STRING(b)) {
return %_StringAdd(%non_string_to_string(a), b);
} else {
return %NumberAdd(%to_number_fun(a), %to_number_fun(b));
}
}
// Strong mode ADD throws if an implicit conversion would be performed
function ADD_STRONG(x) {
if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
throw %make_type_error(kStrongImplicitConversion);
}
// Left operand (this) is already a string.
function STRING_ADD_LEFT(y) {
if (!IS_STRING(y)) {
@ -216,209 +187,6 @@ function STRING_ADD_RIGHT(y) {
}
// ECMA-262, section 11.6.2, page 50.
function SUB(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberSub(x, y);
}
// Strong mode SUB throws if an implicit conversion would be performed
function SUB_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberSub(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.5.1, page 48.
function MUL(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberMul(x, y);
}
// Strong mode MUL throws if an implicit conversion would be performed
function MUL_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberMul(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.5.2, page 49.
function DIV(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberDiv(x, y);
}
// Strong mode DIV throws if an implicit conversion would be performed
function DIV_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberDiv(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.5.3, page 49.
function MOD(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberMod(x, y);
}
// Strong mode MOD throws if an implicit conversion would be performed
function MOD_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberMod(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
/* -------------------------------------------
- - - B i t o p e r a t i o n s - - -
-------------------------------------------
*/
// ECMA-262, section 11.10, page 57.
function BIT_OR(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberOr(x, y);
}
// Strong mode BIT_OR throws if an implicit conversion would be performed
function BIT_OR_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberOr(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.10, page 57.
function BIT_AND(y) {
var x;
if (IS_NUMBER(this)) {
x = this;
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
} else {
x = %non_number_to_number(this);
// Make sure to convert the right operand to a number before
// bailing out in the fast case, but after converting the
// left operand. This ensures that valueOf methods on the right
// operand are always executed.
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
// Optimize for the case where we end up AND'ing a value
// that doesn't convert to a number. This is common in
// certain benchmarks.
if (NUMBER_IS_NAN(x)) return 0;
}
return %NumberAnd(x, y);
}
// Strong mode BIT_AND throws if an implicit conversion would be performed
function BIT_AND_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberAnd(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.10, page 57.
function BIT_XOR(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberXor(x, y);
}
// Strong mode BIT_XOR throws if an implicit conversion would be performed
function BIT_XOR_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberXor(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.7.1, page 51.
function SHL(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberShl(x, y);
}
// Strong mode SHL throws if an implicit conversion would be performed
function SHL_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberShl(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.7.2, page 51.
function SAR(y) {
var x;
if (IS_NUMBER(this)) {
x = this;
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
} else {
x = %non_number_to_number(this);
// Make sure to convert the right operand to a number before
// bailing out in the fast case, but after converting the
// left operand. This ensures that valueOf methods on the right
// operand are always executed.
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
// Optimize for the case where we end up shifting a value
// that doesn't convert to a number. This is common in
// certain benchmarks.
if (NUMBER_IS_NAN(x)) return 0;
}
return %NumberSar(x, y);
}
// Strong mode SAR throws if an implicit conversion would be performed
function SAR_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberSar(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
// ECMA-262, section 11.7.3, page 52.
function SHR(y) {
var x = IS_NUMBER(this) ? this : %non_number_to_number(this);
if (!IS_NUMBER(y)) y = %non_number_to_number(y);
return %NumberShr(x, y);
}
// Strong mode SHR throws if an implicit conversion would be performed
function SHR_STRONG(y) {
if (IS_NUMBER(this) && IS_NUMBER(y)) {
return %NumberShr(this, y);
}
throw %make_type_error(kStrongImplicitConversion);
}
/* -----------------------------
- - - H e l p e r s - - -
-----------------------------
@ -781,40 +549,18 @@ $toPrimitive = ToPrimitive;
$toString = ToString;
%InstallToContext([
"add_builtin", ADD,
"add_strong_builtin", ADD_STRONG,
"apply_prepare_builtin", APPLY_PREPARE,
"bit_and_builtin", BIT_AND,
"bit_and_strong_builtin", BIT_AND_STRONG,
"bit_or_builtin", BIT_OR,
"bit_or_strong_builtin", BIT_OR_STRONG,
"bit_xor_builtin", BIT_XOR,
"bit_xor_strong_builtin", BIT_XOR_STRONG,
"call_function_proxy_as_constructor_builtin", CALL_FUNCTION_PROXY_AS_CONSTRUCTOR,
"call_non_function_as_constructor_builtin", CALL_NON_FUNCTION_AS_CONSTRUCTOR,
"compare_builtin", COMPARE,
"compare_strong_builtin", COMPARE_STRONG,
"concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY,
"div_builtin", DIV,
"div_strong_builtin", DIV_STRONG,
"equals_builtin", EQUALS,
"mod_builtin", MOD,
"mod_strong_builtin", MOD_STRONG,
"mul_builtin", MUL,
"mul_strong_builtin", MUL_STRONG,
"reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE,
"reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE,
"sar_builtin", SAR,
"sar_strong_builtin", SAR_STRONG,
"shl_builtin", SHL,
"shl_strong_builtin", SHL_STRONG,
"shr_builtin", SHR,
"shr_strong_builtin", SHR_STRONG,
"stack_overflow_builtin", STACK_OVERFLOW,
"string_add_left_builtin", STRING_ADD_LEFT,
"string_add_right_builtin", STRING_ADD_RIGHT,
"sub_builtin", SUB,
"sub_strong_builtin", SUB_STRONG,
]);
%InstallToContext([

View File

@ -352,8 +352,7 @@ RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
Handle<Object> value;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
Object::ToNumber(isolate, date));
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date));
icu::SimpleDateFormat* date_format =
DateFormat::UnpackDateFormat(isolate, date_format_holder);
@ -446,8 +445,7 @@ RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
Handle<Object> value;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
Object::ToNumber(isolate, number));
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(number));
icu::DecimalFormat* number_format =
NumberFormat::UnpackNumberFormat(isolate, number_format_holder);

View File

@ -220,56 +220,6 @@ RUNTIME_FUNCTION(Runtime_NumberToSmi) {
}
RUNTIME_FUNCTION(Runtime_NumberAdd) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
return *isolate->factory()->NewNumber(x + y);
}
RUNTIME_FUNCTION(Runtime_NumberSub) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
return *isolate->factory()->NewNumber(x - y);
}
RUNTIME_FUNCTION(Runtime_NumberMul) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
return *isolate->factory()->NewNumber(x * y);
}
RUNTIME_FUNCTION(Runtime_NumberDiv) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
return *isolate->factory()->NewNumber(x / y);
}
RUNTIME_FUNCTION(Runtime_NumberMod) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_DOUBLE_ARG_CHECKED(x, 0);
CONVERT_DOUBLE_ARG_CHECKED(y, 1);
return *isolate->factory()->NewNumber(modulo(x, y));
}
RUNTIME_FUNCTION(Runtime_NumberImul) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
@ -283,67 +233,6 @@ RUNTIME_FUNCTION(Runtime_NumberImul) {
}
RUNTIME_FUNCTION(Runtime_NumberOr) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
return *isolate->factory()->NewNumberFromInt(x | y);
}
RUNTIME_FUNCTION(Runtime_NumberAnd) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
return *isolate->factory()->NewNumberFromInt(x & y);
}
RUNTIME_FUNCTION(Runtime_NumberXor) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
return *isolate->factory()->NewNumberFromInt(x ^ y);
}
RUNTIME_FUNCTION(Runtime_NumberShl) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f));
}
RUNTIME_FUNCTION(Runtime_NumberShr) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f));
}
RUNTIME_FUNCTION(Runtime_NumberSar) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
return *isolate->factory()->NewNumberFromInt(
ArithmeticShiftRight(x, y & 0x1f));
}
RUNTIME_FUNCTION(Runtime_NumberEquals) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 2);

View File

@ -1459,8 +1459,7 @@ RUNTIME_FUNCTION(Runtime_ToNumber) {
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::ToNumber(isolate, input));
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::ToNumber(input));
return *result;
}

View File

@ -0,0 +1,277 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/arguments.h"
#include "src/isolate-inl.h"
#include "src/runtime/runtime-utils.h"
namespace v8 {
namespace internal {
RUNTIME_FUNCTION(Runtime_Multiply) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::Multiply(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_Multiply_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::Multiply(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_Divide) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::Divide(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_Divide_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::Divide(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_Modulus) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::Modulus(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_Modulus_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::Modulus(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_Add) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::Add(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_Add_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::Add(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_Subtract) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::Subtract(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_Subtract_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::Subtract(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_ShiftLeft) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::ShiftLeft(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_ShiftLeft_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::ShiftLeft(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_ShiftRight) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::ShiftRight(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_ShiftRight_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::ShiftRight(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_ShiftRightLogical) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::ShiftRightLogical(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_ShiftRightLogical_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
Object::ShiftRightLogical(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_BitwiseAnd) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::BitwiseAnd(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_BitwiseAnd_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::BitwiseAnd(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_BitwiseOr) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::BitwiseOr(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_BitwiseOr_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::BitwiseOr(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
RUNTIME_FUNCTION(Runtime_BitwiseXor) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::BitwiseXor(isolate, lhs, rhs));
return *result;
}
RUNTIME_FUNCTION(Runtime_BitwiseXor_Strong) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, lhs, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, rhs, 1);
Handle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, Object::BitwiseXor(isolate, lhs, rhs, Strength::STRONG));
return *result;
}
} // namespace internal
} // namespace v8

View File

@ -405,18 +405,7 @@ namespace internal {
F(NumberToInteger, 1, 1) \
F(NumberToIntegerMapMinusZero, 1, 1) \
F(NumberToSmi, 1, 1) \
F(NumberAdd, 2, 1) \
F(NumberSub, 2, 1) \
F(NumberMul, 2, 1) \
F(NumberDiv, 2, 1) \
F(NumberMod, 2, 1) \
F(NumberImul, 2, 1) \
F(NumberOr, 2, 1) \
F(NumberAnd, 2, 1) \
F(NumberXor, 2, 1) \
F(NumberShl, 2, 1) \
F(NumberShr, 2, 1) \
F(NumberSar, 2, 1) \
F(NumberEquals, 2, 1) \
F(NumberCompare, 3, 1) \
F(SmiLexicographicCompare, 2, 1) \
@ -511,6 +500,30 @@ namespace internal {
F(GetObjectContextNotifierPerformChange, 1, 1)
#define FOR_EACH_INTRINSIC_OPERATORS(F) \
F(Multiply, 2, 1) \
F(Multiply_Strong, 2, 1) \
F(Divide, 2, 1) \
F(Divide_Strong, 2, 1) \
F(Modulus, 2, 1) \
F(Modulus_Strong, 2, 1) \
F(Add, 2, 1) \
F(Add_Strong, 2, 1) \
F(Subtract, 2, 1) \
F(Subtract_Strong, 2, 1) \
F(ShiftLeft, 2, 1) \
F(ShiftLeft_Strong, 2, 1) \
F(ShiftRight, 2, 1) \
F(ShiftRight_Strong, 2, 1) \
F(ShiftRightLogical, 2, 1) \
F(ShiftRightLogical_Strong, 2, 1) \
F(BitwiseAnd, 2, 1) \
F(BitwiseAnd_Strong, 2, 1) \
F(BitwiseOr, 2, 1) \
F(BitwiseOr_Strong, 2, 1) \
F(BitwiseXor, 2, 1) \
F(BitwiseXor_Strong, 2, 1)
#define FOR_EACH_INTRINSIC_PROXY(F) \
F(CreateJSProxy, 2, 1) \
F(CreateJSFunctionProxy, 4, 1) \
@ -1065,6 +1078,7 @@ namespace internal {
FOR_EACH_INTRINSIC_NUMBERS(F) \
FOR_EACH_INTRINSIC_OBJECT(F) \
FOR_EACH_INTRINSIC_OBSERVE(F) \
FOR_EACH_INTRINSIC_OPERATORS(F) \
FOR_EACH_INTRINSIC_PROXY(F) \
FOR_EACH_INTRINSIC_REGEXP(F) \
FOR_EACH_INTRINSIC_SCOPES(F) \

View File

@ -134,11 +134,10 @@ TEST(ConstructorCall) {
// TODO(titzer): factor these out into test-runtime-calls.cc
TEST(RuntimeCallCPP2) {
FLAG_allow_natives_syntax = true;
FunctionTester T("(function(a,b) { return %NumberAdd(a, b); })");
FunctionTester T("(function(a,b) { return %NumberImul(a, b); })");
T.CheckCall(T.Val(65), T.Val(42), T.Val(23));
T.CheckCall(T.Val(19), T.Val(42), T.Val(-23));
T.CheckCall(T.Val(6.5), T.Val(4.2), T.Val(2.3));
T.CheckCall(T.Val(2730), T.Val(42), T.Val(65));
T.CheckCall(T.Val(798), T.Val(42), T.Val(19));
}

View File

@ -82,6 +82,3 @@ testTraceNativeConstructor(Date); // Does ToNumber on argument.
testNotOmittedBuiltin(function(){ [thrower, 2].sort(function (a,b) {
(b < a) - (a < b); });
}, "QuickSort");
// Not omitted even though ADD from runtime.js is a non-native builtin.
testNotOmittedBuiltin(function(){ thrower + 2; }, "ADD");

View File

@ -328,33 +328,15 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
}
TARGET_TEST_F(InterpreterAssemblerTest, CallJSBuiltin) {
TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
Node* receiver = m.IntPtrConstant(1234);
Node* call_js_builtin_0 =
m.CallJSBuiltin(Context::SUB_BUILTIN_INDEX, receiver);
Matcher<Node*> load_globals_matcher = m.IsLoad(
kMachAnyTagged, IsParameter(Linkage::kInterpreterContextParameter),
IsIntPtrConstant(Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
Matcher<Node*> load_native_context_matcher = m.IsLoad(
kMachAnyTagged, load_globals_matcher,
IsIntPtrConstant(GlobalObject::kNativeContextOffset - kHeapObjectTag));
Matcher<Node*> function_matcher = m.IsLoad(
kMachAnyTagged, load_native_context_matcher,
IsIntPtrConstant(Context::SlotOffset(Context::SUB_BUILTIN_INDEX)));
Matcher<Node*> context_matcher =
m.IsLoad(kMachAnyTagged, function_matcher,
IsIntPtrConstant(JSFunction::kContextOffset - kHeapObjectTag));
EXPECT_THAT(call_js_builtin_0,
m.IsCall(_, function_matcher, receiver, context_matcher));
Node* arg1 = m.Int32Constant(0xabcd);
Node* call_js_builtin_1 =
m.CallJSBuiltin(Context::SUB_BUILTIN_INDEX, receiver, arg1);
EXPECT_THAT(call_js_builtin_1,
m.IsCall(_, function_matcher, receiver, arg1, context_matcher));
Node* arg1 = m.Int32Constant(2);
Node* arg2 = m.Int32Constant(3);
Node* call_runtime = m.CallRuntime(Runtime::kAdd, arg1, arg2);
EXPECT_THAT(call_runtime,
m.IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
IsParameter(Linkage::kInterpreterContextParameter)));
}
}

View File

@ -45,8 +45,6 @@ PASS myFunctionWithApply.aliasedApply(myObject, ['arg1']) is [myObject, "myFunct
PASS myFunctionWithApply.apply(myObject, arg1Array) is [myFunctionWithApply, "myFunctionWithApply.apply", myObject]
PASS forwarder(myFunctionWithApply, myObject, arg1Array) is [myFunctionWithApply, "myFunctionWithApply.apply", myObject]
PASS myFunctionWithApply.aliasedApply(myObject, arg1Array) is [myObject, "myFunctionWithApply", "arg1"]
PASS myFunction.apply(null, new Array(500000)) threw exception RangeError: Maximum call stack size exceeded.
PASS myFunction.apply(null, new Array(1 << 30)) threw exception RangeError: Maximum call stack size exceeded.
PASS recurseArguments.apply(null, new Array(50000)) threw exception RangeError: Maximum call stack size exceeded.
PASS successfullyParsed is true

View File

@ -68,18 +68,5 @@ shouldBe("myFunctionWithApply.apply(myObject, arg1Array)", '[myFunctionWithApply
shouldBe("forwarder(myFunctionWithApply, myObject, arg1Array)", '[myFunctionWithApply, "myFunctionWithApply.apply", myObject]');
shouldBe("myFunctionWithApply.aliasedApply(myObject, arg1Array)", '[myObject, "myFunctionWithApply", "arg1"]');
function stackOverflowTest() {
try {
var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z;
stackOverflowTest();
} catch(e) {
// Blow the stack with a sparse array
shouldThrow("myFunction.apply(null, new Array(500000))");
// Blow the stack with a sparse array that is sufficiently large to cause int overflow
shouldThrow("myFunction.apply(null, new Array(1 << 30))");
}
}
stackOverflowTest();
// Blow the stack recursing with arguments
shouldThrow("recurseArguments.apply(null, new Array(50000))");

View File

@ -911,6 +911,7 @@
'../../src/runtime/runtime-numbers.cc',
'../../src/runtime/runtime-object.cc',
'../../src/runtime/runtime-observe.cc',
'../../src/runtime/runtime-operators.cc',
'../../src/runtime/runtime-proxy.cc',
'../../src/runtime/runtime-regexp.cc',
'../../src/runtime/runtime-scopes.cc',