[es6] Introduce %ToInteger and %ToLength.
This adds ES6 compliant Object::ToInteger, Object::ToInt32, Object::ToUint32 and Object::ToLength, and replaces the old Execution wrappers of those abstract operations (which were not using the correct ToPrimitive). This also introduces proper %ToInteger and %ToLength runtime entries, with a fast path %_ToInteger supported in fullcodegen and Crankshaft (for now). Internal JavaScript code should use TO_INTEGER and TO_LENGTH respectively. CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_layout_dbg,v8_linux_nosnap_dbg BUG=v8:4307 LOG=n Review URL: https://codereview.chromium.org/1378533002 Cr-Commit-Position: refs/heads/master@{#30993}
This commit is contained in:
parent
2839811584
commit
93b2b2622b
@ -224,7 +224,7 @@ void Accessors::ArrayLengthSetter(
|
||||
uint32_t length = 0;
|
||||
if (!FastAsArrayLength(isolate, length_obj, &length)) {
|
||||
Handle<Object> uint32_v;
|
||||
if (!Execution::ToUint32(isolate, length_obj).ToHandle(&uint32_v)) {
|
||||
if (!Object::ToUint32(isolate, length_obj).ToHandle(&uint32_v)) {
|
||||
isolate->OptionalRescheduleException(false);
|
||||
return;
|
||||
}
|
||||
|
15
src/api.cc
15
src/api.cc
@ -2937,7 +2937,7 @@ MaybeLocal<Integer> Value::ToInteger(Local<Context> context) const {
|
||||
PREPARE_FOR_EXECUTION(context, "ToInteger", Integer);
|
||||
Local<Integer> result;
|
||||
has_pending_exception =
|
||||
!ToLocal<Integer>(i::Execution::ToInteger(isolate, obj), &result);
|
||||
!ToLocal<Integer>(i::Object::ToInteger(isolate, obj), &result);
|
||||
RETURN_ON_FAILED_EXECUTION(Integer);
|
||||
RETURN_ESCAPED(result);
|
||||
}
|
||||
@ -2954,7 +2954,7 @@ MaybeLocal<Int32> Value::ToInt32(Local<Context> context) const {
|
||||
Local<Int32> result;
|
||||
PREPARE_FOR_EXECUTION(context, "ToInt32", Int32);
|
||||
has_pending_exception =
|
||||
!ToLocal<Int32>(i::Execution::ToInt32(isolate, obj), &result);
|
||||
!ToLocal<Int32>(i::Object::ToInt32(isolate, obj), &result);
|
||||
RETURN_ON_FAILED_EXECUTION(Int32);
|
||||
RETURN_ESCAPED(result);
|
||||
}
|
||||
@ -2969,9 +2969,9 @@ MaybeLocal<Uint32> Value::ToUint32(Local<Context> context) const {
|
||||
auto obj = Utils::OpenHandle(this);
|
||||
if (obj->IsSmi()) return ToApiHandle<Uint32>(obj);
|
||||
Local<Uint32> result;
|
||||
PREPARE_FOR_EXECUTION(context, "ToUInt32", Uint32);
|
||||
PREPARE_FOR_EXECUTION(context, "ToUint32", Uint32);
|
||||
has_pending_exception =
|
||||
!ToLocal<Uint32>(i::Execution::ToUint32(isolate, obj), &result);
|
||||
!ToLocal<Uint32>(i::Object::ToUint32(isolate, obj), &result);
|
||||
RETURN_ON_FAILED_EXECUTION(Uint32);
|
||||
RETURN_ESCAPED(result);
|
||||
}
|
||||
@ -3265,8 +3265,7 @@ Maybe<int64_t> Value::IntegerValue(Local<Context> context) const {
|
||||
num = obj;
|
||||
} else {
|
||||
PREPARE_FOR_EXECUTION_PRIMITIVE(context, "IntegerValue", int64_t);
|
||||
has_pending_exception =
|
||||
!i::Execution::ToInteger(isolate, obj).ToHandle(&num);
|
||||
has_pending_exception = !i::Object::ToInteger(isolate, obj).ToHandle(&num);
|
||||
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int64_t);
|
||||
}
|
||||
return Just(num->IsSmi() ? static_cast<int64_t>(i::Smi::cast(*num)->value())
|
||||
@ -3292,7 +3291,7 @@ Maybe<int32_t> Value::Int32Value(Local<Context> context) const {
|
||||
if (obj->IsNumber()) return Just(NumberToInt32(*obj));
|
||||
PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Int32Value", int32_t);
|
||||
i::Handle<i::Object> num;
|
||||
has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
|
||||
has_pending_exception = !i::Object::ToInt32(isolate, obj).ToHandle(&num);
|
||||
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(int32_t);
|
||||
return Just(num->IsSmi() ? i::Smi::cast(*num)->value()
|
||||
: static_cast<int32_t>(num->Number()));
|
||||
@ -3311,7 +3310,7 @@ Maybe<uint32_t> Value::Uint32Value(Local<Context> context) const {
|
||||
if (obj->IsNumber()) return Just(NumberToUint32(*obj));
|
||||
PREPARE_FOR_EXECUTION_PRIMITIVE(context, "Uint32Value", uint32_t);
|
||||
i::Handle<i::Object> num;
|
||||
has_pending_exception = !i::Execution::ToUint32(isolate, obj).ToHandle(&num);
|
||||
has_pending_exception = !i::Object::ToUint32(isolate, obj).ToHandle(&num);
|
||||
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(uint32_t);
|
||||
return Just(num->IsSmi() ? static_cast<uint32_t>(i::Smi::cast(*num)->value())
|
||||
: static_cast<uint32_t>(num->Number()));
|
||||
|
@ -1000,11 +1000,11 @@ bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
|
||||
false);
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
|
||||
Object::ToLength(isolate, val), false);
|
||||
// TODO(caitp): Support larger element indexes (up to 2^53-1).
|
||||
if (!val->ToUint32(&length)) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, val, Execution::ToLength(isolate, val), false);
|
||||
val->ToUint32(&length);
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,6 +246,8 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
|
||||
case Runtime::kInlineGetPrototype:
|
||||
case Runtime::kInlineRegExpExec:
|
||||
case Runtime::kInlineSubString:
|
||||
case Runtime::kInlineToInteger:
|
||||
case Runtime::kInlineToLength:
|
||||
case Runtime::kInlineToName:
|
||||
case Runtime::kInlineToNumber:
|
||||
case Runtime::kInlineToObject:
|
||||
|
@ -83,7 +83,6 @@ enum BindingFlags {
|
||||
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
|
||||
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
|
||||
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
|
||||
V(TO_LENGTH_FUN_INDEX, JSFunction, to_length_fun) \
|
||||
V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun)
|
||||
|
||||
|
||||
@ -159,7 +158,6 @@ enum BindingFlags {
|
||||
V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
|
||||
to_complete_property_descriptor) \
|
||||
V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \
|
||||
V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
|
||||
V(TYPE_ERROR_FUNCTION_INDEX, JSFunction, type_error_function) \
|
||||
V(URI_ERROR_FUNCTION_INDEX, JSFunction, uri_error_function) \
|
||||
NATIVE_CONTEXT_JS_BUILTINS(V)
|
||||
|
@ -438,18 +438,6 @@ MaybeHandle<Object> Execution::ToDetailString(
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Execution::ToInteger(
|
||||
Isolate* isolate, Handle<Object> obj) {
|
||||
RETURN_NATIVE_CALL(to_integer, { obj });
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Execution::ToLength(
|
||||
Isolate* isolate, Handle<Object> obj) {
|
||||
RETURN_NATIVE_CALL(to_length, { obj });
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
|
||||
Handle<Object> time_obj = isolate->factory()->NewNumber(time);
|
||||
RETURN_NATIVE_CALL(create_date, { time_obj });
|
||||
@ -459,12 +447,6 @@ MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
|
||||
#undef RETURN_NATIVE_CALL
|
||||
|
||||
|
||||
MaybeHandle<Object> Execution::ToInt32(Isolate* isolate, Handle<Object> obj) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(obj), Object);
|
||||
return isolate->factory()->NewNumberFromInt(DoubleToInt32(obj->Number()));
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
|
||||
Handle<JSReceiver> receiver;
|
||||
if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
|
||||
@ -475,12 +457,6 @@ 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(obj), Object);
|
||||
return isolate->factory()->NewNumberFromUint(DoubleToUint32(obj->Number()));
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
|
||||
Handle<String> flags) {
|
||||
Isolate* isolate = pattern->GetIsolate();
|
||||
|
@ -52,23 +52,6 @@ class Execution final : public AllStatic {
|
||||
Handle<Object> argv[],
|
||||
MaybeHandle<Object>* exception_out = NULL);
|
||||
|
||||
// ECMA-262 9.4
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToInteger(
|
||||
Isolate* isolate, Handle<Object> obj);
|
||||
|
||||
// ECMA-262 9.5
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToInt32(
|
||||
Isolate* isolate, Handle<Object> obj);
|
||||
|
||||
// ECMA-262 9.6
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToUint32(
|
||||
Isolate* isolate, Handle<Object> obj);
|
||||
|
||||
|
||||
// ES6, draft 10-14-14, section 7.1.15
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToLength(
|
||||
Isolate* isolate, Handle<Object> obj);
|
||||
|
||||
// ECMA-262 9.8
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToDetailString(
|
||||
Isolate* isolate, Handle<Object> obj);
|
||||
|
@ -3766,6 +3766,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into r0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(r0, &done_convert);
|
||||
__ Push(r0);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(r0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -3476,6 +3476,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into x0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(x0, &done_convert);
|
||||
__ Push(x0);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(x0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -480,49 +480,50 @@ class FullCodeGenerator: public AstVisitor {
|
||||
void EmitKeyedCallWithLoadIC(Call* expr, Expression* key);
|
||||
void EmitKeyedSuperCallWithLoadIC(Call* expr);
|
||||
|
||||
#define FOR_EACH_FULL_CODE_INTRINSIC(F) \
|
||||
F(IsSmi) \
|
||||
F(IsArray) \
|
||||
F(IsTypedArray) \
|
||||
F(IsRegExp) \
|
||||
F(IsJSProxy) \
|
||||
F(IsConstructCall) \
|
||||
F(Call) \
|
||||
F(CallFunction) \
|
||||
F(DefaultConstructorCallSuper) \
|
||||
F(ArgumentsLength) \
|
||||
F(Arguments) \
|
||||
F(ValueOf) \
|
||||
F(SetValueOf) \
|
||||
F(IsDate) \
|
||||
F(DateField) \
|
||||
F(StringCharFromCode) \
|
||||
F(StringCharAt) \
|
||||
F(OneByteSeqStringSetChar) \
|
||||
F(TwoByteSeqStringSetChar) \
|
||||
F(ObjectEquals) \
|
||||
F(IsFunction) \
|
||||
F(IsSpecObject) \
|
||||
F(IsSimdValue) \
|
||||
F(MathPow) \
|
||||
F(IsMinusZero) \
|
||||
F(HasCachedArrayIndex) \
|
||||
F(GetCachedArrayIndex) \
|
||||
F(FastOneByteArrayJoin) \
|
||||
F(GeneratorNext) \
|
||||
F(GeneratorThrow) \
|
||||
F(DebugBreakInOptimizedCode) \
|
||||
F(ClassOf) \
|
||||
F(StringCharCodeAt) \
|
||||
F(StringAdd) \
|
||||
F(SubString) \
|
||||
F(RegExpExec) \
|
||||
F(RegExpConstructResult) \
|
||||
F(NumberToString) \
|
||||
F(ToString) \
|
||||
F(ToName) \
|
||||
F(ToObject) \
|
||||
F(DebugIsActive) \
|
||||
#define FOR_EACH_FULL_CODE_INTRINSIC(F) \
|
||||
F(IsSmi) \
|
||||
F(IsArray) \
|
||||
F(IsTypedArray) \
|
||||
F(IsRegExp) \
|
||||
F(IsJSProxy) \
|
||||
F(IsConstructCall) \
|
||||
F(Call) \
|
||||
F(CallFunction) \
|
||||
F(DefaultConstructorCallSuper) \
|
||||
F(ArgumentsLength) \
|
||||
F(Arguments) \
|
||||
F(ValueOf) \
|
||||
F(SetValueOf) \
|
||||
F(IsDate) \
|
||||
F(DateField) \
|
||||
F(StringCharFromCode) \
|
||||
F(StringCharAt) \
|
||||
F(OneByteSeqStringSetChar) \
|
||||
F(TwoByteSeqStringSetChar) \
|
||||
F(ObjectEquals) \
|
||||
F(IsFunction) \
|
||||
F(IsSpecObject) \
|
||||
F(IsSimdValue) \
|
||||
F(MathPow) \
|
||||
F(IsMinusZero) \
|
||||
F(HasCachedArrayIndex) \
|
||||
F(GetCachedArrayIndex) \
|
||||
F(FastOneByteArrayJoin) \
|
||||
F(GeneratorNext) \
|
||||
F(GeneratorThrow) \
|
||||
F(DebugBreakInOptimizedCode) \
|
||||
F(ClassOf) \
|
||||
F(StringCharCodeAt) \
|
||||
F(StringAdd) \
|
||||
F(SubString) \
|
||||
F(RegExpExec) \
|
||||
F(RegExpConstructResult) \
|
||||
F(ToInteger) \
|
||||
F(NumberToString) \
|
||||
F(ToString) \
|
||||
F(ToName) \
|
||||
F(ToObject) \
|
||||
F(DebugIsActive) \
|
||||
F(CreateIterResultObject)
|
||||
|
||||
#define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
|
||||
|
@ -3664,6 +3664,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into eax and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(eax, &done_convert, Label::kNear);
|
||||
__ Push(eax);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -3778,6 +3778,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into v0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(v0, &done_convert);
|
||||
__ Push(v0);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -3781,6 +3781,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into v0 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(v0, &done_convert);
|
||||
__ Push(v0);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(v0);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -3780,6 +3780,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into r3 and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(r3, &done_convert);
|
||||
__ Push(r3);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(r3);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -3661,6 +3661,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into rax and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(rax, &done_convert, Label::kNear);
|
||||
__ Push(rax);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(rax);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -3655,6 +3655,23 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(1, args->length());
|
||||
|
||||
// Load the argument into eax and convert it.
|
||||
VisitForAccumulatorValue(args->at(0));
|
||||
|
||||
// Convert the object to an integer.
|
||||
Label done_convert;
|
||||
__ JumpIfSmi(eax, &done_convert, Label::kNear);
|
||||
__ Push(eax);
|
||||
__ CallRuntime(Runtime::kToInteger, 1);
|
||||
__ bind(&done_convert);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK_EQ(args->length(), 1);
|
||||
|
@ -774,6 +774,10 @@ const uint64_t kHoleNanInt64 =
|
||||
(static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
|
||||
|
||||
|
||||
// ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER
|
||||
const double kMaxSafeInteger = 9007199254740991.0; // 2^53-1
|
||||
|
||||
|
||||
// The order of this enum has to be kept in sync with the predicates below.
|
||||
enum VariableMode {
|
||||
// User declared variables:
|
||||
|
@ -20,7 +20,7 @@ function InnerArrayIncludes(searchElement, fromIndex, array, length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var n = $toInteger(fromIndex);
|
||||
var n = TO_INTEGER(fromIndex);
|
||||
|
||||
var k;
|
||||
if (n >= 0) {
|
||||
@ -49,7 +49,7 @@ function ArrayIncludes(searchElement, fromIndex) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.includes");
|
||||
|
||||
var array = TO_OBJECT(this);
|
||||
var length = $toLength(array.length);
|
||||
var length = TO_LENGTH(array.length);
|
||||
|
||||
return InnerArrayIncludes(searchElement, fromIndex, array, length);
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ function ArrayCopyWithin(target, start, end) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
|
||||
|
||||
var array = TO_OBJECT(this);
|
||||
var length = $toLength(array.length);
|
||||
var length = TO_LENGTH(array.length);
|
||||
|
||||
return InnerArrayCopyWithin(target, start, end, array, length);
|
||||
}
|
||||
@ -110,7 +110,7 @@ function ArrayFind(predicate, thisArg) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
|
||||
|
||||
var array = TO_OBJECT(this);
|
||||
var length = $toInteger(array.length);
|
||||
var length = TO_INTEGER(array.length);
|
||||
|
||||
return InnerArrayFind(predicate, thisArg, array, length);
|
||||
}
|
||||
@ -135,7 +135,7 @@ function ArrayFindIndex(predicate, thisArg) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
|
||||
|
||||
var array = TO_OBJECT(this);
|
||||
var length = $toInteger(array.length);
|
||||
var length = TO_INTEGER(array.length);
|
||||
|
||||
return InnerArrayFindIndex(predicate, thisArg, array, length);
|
||||
}
|
||||
@ -233,7 +233,7 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
|
||||
k++;
|
||||
}
|
||||
} else {
|
||||
var len = $toLength(items.length);
|
||||
var len = TO_LENGTH(items.length);
|
||||
result = %IsConstructor(this) ? new this(len) : new GlobalArray(len);
|
||||
|
||||
for (k = 0; k < len; ++k) {
|
||||
|
@ -41,7 +41,7 @@ function CheckSharedInteger32TypedArray(ia) {
|
||||
|
||||
function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) {
|
||||
CheckSharedIntegerTypedArray(sta);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(sta)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -52,7 +52,7 @@ function AtomicsCompareExchangeJS(sta, index, oldValue, newValue) {
|
||||
|
||||
function AtomicsLoadJS(sta, index) {
|
||||
CheckSharedIntegerTypedArray(sta);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(sta)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -61,7 +61,7 @@ function AtomicsLoadJS(sta, index) {
|
||||
|
||||
function AtomicsStoreJS(sta, index, value) {
|
||||
CheckSharedIntegerTypedArray(sta);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(sta)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -71,7 +71,7 @@ function AtomicsStoreJS(sta, index, value) {
|
||||
|
||||
function AtomicsAddJS(ia, index, value) {
|
||||
CheckSharedIntegerTypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -81,7 +81,7 @@ function AtomicsAddJS(ia, index, value) {
|
||||
|
||||
function AtomicsSubJS(ia, index, value) {
|
||||
CheckSharedIntegerTypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -91,7 +91,7 @@ function AtomicsSubJS(ia, index, value) {
|
||||
|
||||
function AtomicsAndJS(ia, index, value) {
|
||||
CheckSharedIntegerTypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -101,7 +101,7 @@ function AtomicsAndJS(ia, index, value) {
|
||||
|
||||
function AtomicsOrJS(ia, index, value) {
|
||||
CheckSharedIntegerTypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -111,7 +111,7 @@ function AtomicsOrJS(ia, index, value) {
|
||||
|
||||
function AtomicsXorJS(ia, index, value) {
|
||||
CheckSharedIntegerTypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -121,7 +121,7 @@ function AtomicsXorJS(ia, index, value) {
|
||||
|
||||
function AtomicsExchangeJS(ia, index, value) {
|
||||
CheckSharedIntegerTypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -137,7 +137,7 @@ function AtomicsIsLockFreeJS(size) {
|
||||
|
||||
function AtomicsFutexWaitJS(ia, index, value, timeout) {
|
||||
CheckSharedInteger32TypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
@ -156,20 +156,20 @@ function AtomicsFutexWaitJS(ia, index, value, timeout) {
|
||||
|
||||
function AtomicsFutexWakeJS(ia, index, count) {
|
||||
CheckSharedInteger32TypedArray(ia);
|
||||
index = $toInteger(index);
|
||||
index = TO_INTEGER(index);
|
||||
if (index < 0 || index >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
}
|
||||
count = MathMax(0, $toInteger(count));
|
||||
count = MathMax(0, TO_INTEGER(count));
|
||||
return %AtomicsFutexWake(ia, index, count);
|
||||
}
|
||||
|
||||
function AtomicsFutexWakeOrRequeueJS(ia, index1, count, value, index2) {
|
||||
CheckSharedInteger32TypedArray(ia);
|
||||
index1 = $toInteger(index1);
|
||||
count = MathMax(0, $toInteger(count));
|
||||
index1 = TO_INTEGER(index1);
|
||||
count = MathMax(0, TO_INTEGER(count));
|
||||
value = TO_INT32(value);
|
||||
index2 = $toInteger(index2);
|
||||
index2 = TO_INTEGER(index2);
|
||||
if (index1 < 0 || index1 >= %_TypedArrayGetLength(ia) ||
|
||||
index2 < 0 || index2 >= %_TypedArrayGetLength(ia)) {
|
||||
return UNDEFINED;
|
||||
|
@ -12217,6 +12217,33 @@ void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateToInteger(CallRuntime* call) {
|
||||
DCHECK_EQ(1, call->arguments()->length());
|
||||
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
||||
HValue* input = Pop();
|
||||
if (input->type().IsSmi()) {
|
||||
return ast_context()->ReturnValue(input);
|
||||
} else {
|
||||
IfBuilder if_inputissmi(this);
|
||||
if_inputissmi.If<HIsSmiAndBranch>(input);
|
||||
if_inputissmi.Then();
|
||||
{
|
||||
// Return the input value.
|
||||
Push(input);
|
||||
Add<HSimulate>(call->id(), FIXED_SIMULATE);
|
||||
}
|
||||
if_inputissmi.Else();
|
||||
{
|
||||
Add<HPushArguments>(input);
|
||||
Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToInteger), 1));
|
||||
Add<HSimulate>(call->id(), FIXED_SIMULATE);
|
||||
}
|
||||
if_inputissmi.End();
|
||||
return ast_context()->ReturnValue(Pop());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
|
||||
DCHECK_EQ(1, call->arguments()->length());
|
||||
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
|
||||
|
@ -2223,6 +2223,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
|
||||
F(OneByteSeqStringSetChar) \
|
||||
F(TwoByteSeqStringSetChar) \
|
||||
F(ObjectEquals) \
|
||||
F(ToInteger) \
|
||||
F(ToObject) \
|
||||
F(ToString) \
|
||||
F(IsFunction) \
|
||||
|
@ -217,7 +217,7 @@ function JSONStringify(value, replacer, space) {
|
||||
}
|
||||
var gap;
|
||||
if (IS_NUMBER(space)) {
|
||||
space = MathMax(0, MathMin($toInteger(space), 10));
|
||||
space = MathMax(0, MathMin(TO_INTEGER(space), 10));
|
||||
gap = %_SubString(" ", 0, space);
|
||||
} else if (IS_STRING(space)) {
|
||||
if (space.length > 10) {
|
||||
|
@ -141,12 +141,12 @@ define kBoundArgumentsStartIndex = 2;
|
||||
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
|
||||
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
|
||||
macro NUMBER_IS_FINITE(arg) = (%_IsSmi(%IS_VAR(arg)) || ((arg == arg) && (arg != 1/0) && (arg != -1/0)));
|
||||
macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToInteger(ToNumber(arg)));
|
||||
macro TO_INTEGER_FOR_SIDE_EFFECT(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : ToNumber(arg));
|
||||
macro TO_INTEGER(arg) = (%_ToInteger(arg));
|
||||
macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToIntegerMapMinusZero(ToNumber(arg)));
|
||||
macro TO_INT32(arg) = (arg | 0);
|
||||
macro TO_UINT32(arg) = (arg >>> 0);
|
||||
macro TO_LENGTH_OR_UINT32(arg) = (harmony_tolength ? $toLength(arg) : TO_UINT32(arg));
|
||||
macro TO_LENGTH(arg) = (%ToLength(arg));
|
||||
macro TO_LENGTH_OR_UINT32(arg) = (harmony_tolength ? TO_LENGTH(arg) : TO_UINT32(arg));
|
||||
macro TO_STRING(arg) = (%_ToString(arg));
|
||||
macro TO_NUMBER_INLINE(arg) = (IS_NUMBER(%IS_VAR(arg)) ? arg : $nonNumberToNumber(arg));
|
||||
macro TO_OBJECT(arg) = (%_ToObject(arg));
|
||||
|
@ -330,7 +330,7 @@ function ConvertAcceptListToTypeMap(arg) {
|
||||
|
||||
if (!IS_SPEC_OBJECT(arg)) throw MakeTypeError(kObserveInvalidAccept);
|
||||
|
||||
var len = $toInteger(arg.length);
|
||||
var len = TO_INTEGER(arg.length);
|
||||
if (len < 0) len = 0;
|
||||
|
||||
return TypeMapCreateFromList(arg, len);
|
||||
|
@ -132,6 +132,27 @@ MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
|
||||
return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
|
||||
return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
|
||||
return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
|
||||
while (true) {
|
||||
@ -159,6 +180,19 @@ MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
|
||||
double len = DoubleToInteger(input->Number());
|
||||
if (len <= 0.0) {
|
||||
len = 0.0;
|
||||
} else if (len >= kMaxSafeInteger) {
|
||||
len = kMaxSafeInteger;
|
||||
}
|
||||
return isolate->factory()->NewNumber(len);
|
||||
}
|
||||
|
||||
|
||||
bool Object::BooleanValue() {
|
||||
if (IsBoolean()) return IsTrue();
|
||||
if (IsSmi()) return Smi::cast(this)->value() != 0;
|
||||
|
@ -1127,10 +1127,26 @@ class Object {
|
||||
// ES6 section 7.1.3 ToNumber
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToNumber(Handle<Object> input);
|
||||
|
||||
// ES6 section 7.1.4 ToInteger
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToInteger(Isolate* isolate,
|
||||
Handle<Object> input);
|
||||
|
||||
// ES6 section 7.1.5 ToInt32
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToInt32(Isolate* isolate,
|
||||
Handle<Object> input);
|
||||
|
||||
// ES6 section 7.1.6 ToUint32
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToUint32(Isolate* isolate,
|
||||
Handle<Object> input);
|
||||
|
||||
// ES6 section 7.1.12 ToString
|
||||
MUST_USE_RESULT static MaybeHandle<String> ToString(Isolate* isolate,
|
||||
Handle<Object> input);
|
||||
|
||||
// ES6 section 7.1.15 ToLength
|
||||
MUST_USE_RESULT static MaybeHandle<Object> ToLength(Isolate* isolate,
|
||||
Handle<Object> input);
|
||||
|
||||
// ES6 section 7.3.9 GetMethod
|
||||
MUST_USE_RESULT static MaybeHandle<Object> GetMethod(
|
||||
Handle<JSReceiver> receiver, Handle<Name> name);
|
||||
|
@ -15,8 +15,6 @@ var $NaN;
|
||||
var $nonNumberToNumber;
|
||||
var $sameValue;
|
||||
var $sameValueZero;
|
||||
var $toInteger;
|
||||
var $toLength;
|
||||
var $toNumber;
|
||||
var $toPositiveInteger;
|
||||
|
||||
@ -97,7 +95,7 @@ function REFLECT_APPLY_PREPARE(args) {
|
||||
throw %make_type_error(kWrongArgs, "Reflect.apply");
|
||||
}
|
||||
|
||||
length = %to_length_fun(args.length);
|
||||
length = TO_LENGTH(args.length);
|
||||
|
||||
// We can handle any number of apply arguments if the stack is
|
||||
// big enough, but sanity check the value to avoid overflow when
|
||||
@ -147,7 +145,7 @@ function REFLECT_CONSTRUCT_PREPARE(
|
||||
throw %make_type_error(kWrongArgs, "Reflect.construct");
|
||||
}
|
||||
|
||||
length = %to_length_fun(args.length);
|
||||
length = TO_LENGTH(args.length);
|
||||
|
||||
// We can handle any number of apply arguments if the stack is
|
||||
// big enough, but sanity check the value to avoid overflow when
|
||||
@ -216,21 +214,6 @@ function ToString(x) {
|
||||
}
|
||||
|
||||
|
||||
// ECMA-262, section 9.4, page 34.
|
||||
function ToInteger(x) {
|
||||
if (%_IsSmi(x)) return x;
|
||||
return %NumberToInteger(ToNumber(x));
|
||||
}
|
||||
|
||||
|
||||
// ES6, draft 08-24-14, section 7.1.15
|
||||
function ToLength(arg) {
|
||||
arg = ToInteger(arg);
|
||||
if (arg < 0) return 0;
|
||||
return arg < kMaxSafeInteger ? arg : kMaxSafeInteger;
|
||||
}
|
||||
|
||||
|
||||
// ES5, section 9.12
|
||||
function SameValue(x, y) {
|
||||
if (typeof x != typeof y) return false;
|
||||
@ -348,8 +331,6 @@ $NaN = %GetRootNaN();
|
||||
$nonNumberToNumber = NonNumberToNumber;
|
||||
$sameValue = SameValue;
|
||||
$sameValueZero = SameValueZero;
|
||||
$toInteger = ToInteger;
|
||||
$toLength = ToLength;
|
||||
$toNumber = ToNumber;
|
||||
$toPositiveInteger = ToPositiveInteger;
|
||||
|
||||
@ -363,14 +344,11 @@ $toPositiveInteger = ToPositiveInteger;
|
||||
%InstallToContext([
|
||||
"concat_iterable_to_array", ConcatIterableToArray,
|
||||
"non_number_to_number", NonNumberToNumber,
|
||||
"to_integer_fun", ToInteger,
|
||||
"to_length_fun", ToLength,
|
||||
"to_number_fun", ToNumber,
|
||||
]);
|
||||
|
||||
utils.Export(function(to) {
|
||||
to.ToBoolean = ToBoolean;
|
||||
to.ToLength = ToLength;
|
||||
to.ToNumber = ToNumber;
|
||||
to.ToString = ToString;
|
||||
});
|
||||
|
@ -171,15 +171,6 @@ RUNTIME_FUNCTION(Runtime_NumberToStringSkipCache) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_NumberToInteger) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
|
||||
CONVERT_DOUBLE_ARG_CHECKED(number, 0);
|
||||
return *isolate->factory()->NewNumber(DoubleToInteger(number));
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 1);
|
||||
|
@ -1446,6 +1446,28 @@ RUNTIME_FUNCTION(Runtime_ToNumber) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ToInteger) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||
Object::ToInteger(isolate, input));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ToLength) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
|
||||
Handle<Object> result;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
|
||||
Object::ToLength(isolate, input));
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ToString) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
|
@ -413,7 +413,6 @@ namespace internal {
|
||||
F(StringParseFloat, 1, 1) \
|
||||
F(NumberToString, 1, 1) \
|
||||
F(NumberToStringSkipCache, 1, 1) \
|
||||
F(NumberToInteger, 1, 1) \
|
||||
F(NumberToIntegerMapMinusZero, 1, 1) \
|
||||
F(NumberToSmi, 1, 1) \
|
||||
F(NumberImul, 2, 1) \
|
||||
@ -485,6 +484,8 @@ namespace internal {
|
||||
F(ToPrimitive_Number, 1, 1) \
|
||||
F(ToPrimitive_String, 1, 1) \
|
||||
F(ToNumber, 1, 1) \
|
||||
F(ToInteger, 1, 1) \
|
||||
F(ToLength, 1, 1) \
|
||||
F(ToString, 1, 1) \
|
||||
F(ToName, 1, 1) \
|
||||
F(Equals, 2, 1) \
|
||||
|
@ -155,8 +155,7 @@ function StringMatchJS(regexp) {
|
||||
if (IS_REGEXP(regexp)) {
|
||||
// Emulate RegExp.prototype.exec's side effect in step 5, even though
|
||||
// value is discarded.
|
||||
var lastIndex = regexp.lastIndex;
|
||||
TO_INTEGER_FOR_SIDE_EFFECT(lastIndex);
|
||||
var lastIndex = TO_INTEGER(regexp.lastIndex);
|
||||
if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0);
|
||||
var result = %StringMatch(subject, regexp, RegExpLastMatchInfo);
|
||||
if (result !== null) $regexpLastMatchInfoOverride = null;
|
||||
@ -227,8 +226,7 @@ function StringReplace(search, replace) {
|
||||
if (IS_REGEXP(search)) {
|
||||
// Emulate RegExp.prototype.exec's side effect in step 5, even if
|
||||
// value is discarded.
|
||||
var lastIndex = search.lastIndex;
|
||||
TO_INTEGER_FOR_SIDE_EFFECT(lastIndex);
|
||||
var lastIndex = TO_INTEGER(search.lastIndex);
|
||||
|
||||
if (!IS_CALLABLE(replace)) {
|
||||
replace = TO_STRING(replace);
|
||||
@ -936,7 +934,7 @@ function StringRepeat(count) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.repeat");
|
||||
|
||||
var s = TO_STRING(this);
|
||||
var n = $toInteger(count);
|
||||
var n = TO_INTEGER(count);
|
||||
// The maximum string length is stored in a smi, so a longer repeat
|
||||
// must result in a range error.
|
||||
if (n < 0 || n > %_MaxSmi()) throw MakeRangeError(kInvalidCountValue);
|
||||
@ -966,7 +964,7 @@ function StringStartsWith(searchString /* position */) { // length == 1
|
||||
if (%_ArgumentsLength() > 1) {
|
||||
var arg = %_Arguments(1); // position
|
||||
if (!IS_UNDEFINED(arg)) {
|
||||
pos = $toInteger(arg);
|
||||
pos = TO_INTEGER(arg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1005,7 +1003,7 @@ function StringEndsWith(searchString /* position */) { // length == 1
|
||||
if (%_ArgumentsLength() > 1) {
|
||||
var arg = %_Arguments(1); // position
|
||||
if (!IS_UNDEFINED(arg)) {
|
||||
pos = $toInteger(arg);
|
||||
pos = TO_INTEGER(arg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1115,7 +1113,7 @@ function StringRaw(callSite) {
|
||||
var numberOfSubstitutions = %_ArgumentsLength();
|
||||
var cooked = TO_OBJECT(callSite);
|
||||
var raw = TO_OBJECT(cooked.raw);
|
||||
var literalSegments = $toLength(raw.length);
|
||||
var literalSegments = TO_LENGTH(raw.length);
|
||||
if (literalSegments <= 0) return "";
|
||||
|
||||
var result = TO_STRING(raw[0]);
|
||||
|
@ -334,7 +334,7 @@ function TypedArraySet(obj, offset) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
l = $toLength(l);
|
||||
l = TO_LENGTH(l);
|
||||
if (intOffset + l > this.length) {
|
||||
throw MakeRangeError(kTypedArraySetSourceTooLarge);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user