[runtime] Port simple String.prototype.indexOf cases to TF Builtin
Many websites use simple calls to String.prototype.indexOf with either a one character ASCII needle or needles bigger than the search string. This CL adds a TFJ builtin for these simple cases, giving up to factor 5 speedup. Drive-by-fix: Add default Object type to Arguments.at BUG= Review-Url: https://codereview.chromium.org/2539093002 Cr-Commit-Position: refs/heads/master@{#41760}
This commit is contained in:
parent
63279611b2
commit
89f159b042
@ -41,7 +41,8 @@ class Arguments BASE_EMBEDDED {
|
||||
index * kPointerSize));
|
||||
}
|
||||
|
||||
template <class S> Handle<S> at(int index) {
|
||||
template <class S = Object>
|
||||
Handle<S> at(int index) {
|
||||
Object** value = &((*this)[index]);
|
||||
// This cast checks that the object we're accessing does indeed have the
|
||||
// expected type.
|
||||
|
@ -35,7 +35,9 @@
|
||||
#include "src/assembler.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "src/api.h"
|
||||
#include "src/base/cpu.h"
|
||||
#include "src/base/functional.h"
|
||||
@ -1551,6 +1553,14 @@ ExternalReference ExternalReference::ieee754_tanh_function(Isolate* isolate) {
|
||||
Redirect(isolate, FUNCTION_ADDR(base::ieee754::tanh), BUILTIN_FP_CALL));
|
||||
}
|
||||
|
||||
void* libc_memchr(void* string, int character, size_t search_length) {
|
||||
return memchr(string, character, search_length);
|
||||
}
|
||||
|
||||
ExternalReference ExternalReference::libc_memchr_function(Isolate* isolate) {
|
||||
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memchr)));
|
||||
}
|
||||
|
||||
ExternalReference ExternalReference::page_flags(Page* page) {
|
||||
return ExternalReference(reinterpret_cast<Address>(page) +
|
||||
MemoryChunk::kFlagsOffset);
|
||||
|
@ -1029,6 +1029,8 @@ class ExternalReference BASE_EMBEDDED {
|
||||
static ExternalReference ieee754_tan_function(Isolate* isolate);
|
||||
static ExternalReference ieee754_tanh_function(Isolate* isolate);
|
||||
|
||||
static ExternalReference libc_memchr_function(Isolate* isolate);
|
||||
|
||||
static ExternalReference page_flags(Page* page);
|
||||
|
||||
static ExternalReference ForDeoptEntry(Address entry);
|
||||
@ -1117,6 +1119,7 @@ V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ExternalReference);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility functions
|
||||
void* libc_memchr(void* string, int character, size_t search_length);
|
||||
|
||||
inline int NumberOfBitsSet(uint32_t x) {
|
||||
unsigned int num_bits_set;
|
||||
|
@ -151,7 +151,7 @@ MUST_USE_RESULT static Object* CallJsIntrinsic(Isolate* isolate,
|
||||
int argc = args.length() - 1;
|
||||
ScopedVector<Handle<Object>> argv(argc);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
argv[i] = args.at<Object>(i + 1);
|
||||
argv[i] = args.at(i + 1);
|
||||
}
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate,
|
||||
|
@ -209,7 +209,7 @@ BUILTIN(DateConstructor_ConstructStub) {
|
||||
if (argc == 0) {
|
||||
time_val = JSDate::CurrentTimeValue(isolate);
|
||||
} else if (argc == 1) {
|
||||
Handle<Object> value = args.at<Object>(1);
|
||||
Handle<Object> value = args.at(1);
|
||||
if (value->IsJSDate()) {
|
||||
time_val = Handle<JSDate>::cast(value)->value()->Number();
|
||||
} else {
|
||||
@ -226,37 +226,37 @@ BUILTIN(DateConstructor_ConstructStub) {
|
||||
} else {
|
||||
Handle<Object> year_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
|
||||
Object::ToNumber(args.at<Object>(1)));
|
||||
Object::ToNumber(args.at(1)));
|
||||
Handle<Object> month_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
|
||||
Object::ToNumber(args.at<Object>(2)));
|
||||
Object::ToNumber(args.at(2)));
|
||||
double year = year_object->Number();
|
||||
double month = month_object->Number();
|
||||
double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
|
||||
if (argc >= 3) {
|
||||
Handle<Object> date_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
|
||||
Object::ToNumber(args.at<Object>(3)));
|
||||
Object::ToNumber(args.at(3)));
|
||||
date = date_object->Number();
|
||||
if (argc >= 4) {
|
||||
Handle<Object> hours_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hours_object,
|
||||
Object::ToNumber(args.at(4)));
|
||||
hours = hours_object->Number();
|
||||
if (argc >= 5) {
|
||||
Handle<Object> minutes_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, minutes_object,
|
||||
Object::ToNumber(args.at(5)));
|
||||
minutes = minutes_object->Number();
|
||||
if (argc >= 6) {
|
||||
Handle<Object> seconds_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, seconds_object,
|
||||
Object::ToNumber(args.at(6)));
|
||||
seconds = seconds_object->Number();
|
||||
if (argc >= 7) {
|
||||
Handle<Object> ms_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms_object,
|
||||
Object::ToNumber(args.at(7)));
|
||||
ms = ms_object->Number();
|
||||
}
|
||||
}
|
||||
@ -306,38 +306,37 @@ BUILTIN(DateUTC) {
|
||||
if (argc >= 1) {
|
||||
Handle<Object> year_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
|
||||
Object::ToNumber(args.at<Object>(1)));
|
||||
Object::ToNumber(args.at(1)));
|
||||
year = year_object->Number();
|
||||
if (argc >= 2) {
|
||||
Handle<Object> month_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
|
||||
Object::ToNumber(args.at<Object>(2)));
|
||||
Object::ToNumber(args.at(2)));
|
||||
month = month_object->Number();
|
||||
if (argc >= 3) {
|
||||
Handle<Object> date_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, date_object, Object::ToNumber(args.at<Object>(3)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
|
||||
Object::ToNumber(args.at(3)));
|
||||
date = date_object->Number();
|
||||
if (argc >= 4) {
|
||||
Handle<Object> hours_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hours_object,
|
||||
Object::ToNumber(args.at(4)));
|
||||
hours = hours_object->Number();
|
||||
if (argc >= 5) {
|
||||
Handle<Object> minutes_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, minutes_object,
|
||||
Object::ToNumber(args.at(5)));
|
||||
minutes = minutes_object->Number();
|
||||
if (argc >= 6) {
|
||||
Handle<Object> seconds_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, seconds_object,
|
||||
Object::ToNumber(args.at<Object>(6)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, seconds_object,
|
||||
Object::ToNumber(args.at(6)));
|
||||
seconds = seconds_object->Number();
|
||||
if (argc >= 7) {
|
||||
Handle<Object> ms_object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
|
||||
isolate, ms_object, Object::ToNumber(args.at(7)));
|
||||
ms = ms_object->Number();
|
||||
}
|
||||
}
|
||||
@ -394,11 +393,11 @@ BUILTIN(DatePrototypeSetFullYear) {
|
||||
dt = day;
|
||||
}
|
||||
if (argc >= 2) {
|
||||
Handle<Object> month = args.at<Object>(2);
|
||||
Handle<Object> month = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
|
||||
m = month->Number();
|
||||
if (argc >= 3) {
|
||||
Handle<Object> date = args.at<Object>(3);
|
||||
Handle<Object> date = args.at(3);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
|
||||
dt = date->Number();
|
||||
}
|
||||
@ -425,15 +424,15 @@ BUILTIN(DatePrototypeSetHours) {
|
||||
double s = (time_within_day / 1000) % 60;
|
||||
double milli = time_within_day % 1000;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> min = args.at<Object>(2);
|
||||
Handle<Object> min = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
|
||||
m = min->Number();
|
||||
if (argc >= 3) {
|
||||
Handle<Object> sec = args.at<Object>(3);
|
||||
Handle<Object> sec = args.at(3);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
|
||||
s = sec->Number();
|
||||
if (argc >= 4) {
|
||||
Handle<Object> ms = args.at<Object>(4);
|
||||
Handle<Object> ms = args.at(4);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
|
||||
milli = ms->Number();
|
||||
}
|
||||
@ -482,11 +481,11 @@ BUILTIN(DatePrototypeSetMinutes) {
|
||||
double s = (time_within_day / 1000) % 60;
|
||||
double milli = time_within_day % 1000;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> sec = args.at<Object>(2);
|
||||
Handle<Object> sec = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
|
||||
s = sec->Number();
|
||||
if (argc >= 3) {
|
||||
Handle<Object> ms = args.at<Object>(3);
|
||||
Handle<Object> ms = args.at(3);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
|
||||
milli = ms->Number();
|
||||
}
|
||||
@ -514,7 +513,7 @@ BUILTIN(DatePrototypeSetMonth) {
|
||||
double m = month->Number();
|
||||
double dt = day;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> date = args.at<Object>(2);
|
||||
Handle<Object> date = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
|
||||
dt = date->Number();
|
||||
}
|
||||
@ -541,7 +540,7 @@ BUILTIN(DatePrototypeSetSeconds) {
|
||||
double s = sec->Number();
|
||||
double milli = time_within_day % 1000;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> ms = args.at<Object>(2);
|
||||
Handle<Object> ms = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
|
||||
milli = ms->Number();
|
||||
}
|
||||
@ -595,11 +594,11 @@ BUILTIN(DatePrototypeSetUTCFullYear) {
|
||||
dt = day;
|
||||
}
|
||||
if (argc >= 2) {
|
||||
Handle<Object> month = args.at<Object>(2);
|
||||
Handle<Object> month = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
|
||||
m = month->Number();
|
||||
if (argc >= 3) {
|
||||
Handle<Object> date = args.at<Object>(3);
|
||||
Handle<Object> date = args.at(3);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
|
||||
dt = date->Number();
|
||||
}
|
||||
@ -625,15 +624,15 @@ BUILTIN(DatePrototypeSetUTCHours) {
|
||||
double s = (time_within_day / 1000) % 60;
|
||||
double milli = time_within_day % 1000;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> min = args.at<Object>(2);
|
||||
Handle<Object> min = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
|
||||
m = min->Number();
|
||||
if (argc >= 3) {
|
||||
Handle<Object> sec = args.at<Object>(3);
|
||||
Handle<Object> sec = args.at(3);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
|
||||
s = sec->Number();
|
||||
if (argc >= 4) {
|
||||
Handle<Object> ms = args.at<Object>(4);
|
||||
Handle<Object> ms = args.at(4);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
|
||||
milli = ms->Number();
|
||||
}
|
||||
@ -680,11 +679,11 @@ BUILTIN(DatePrototypeSetUTCMinutes) {
|
||||
double s = (time_within_day / 1000) % 60;
|
||||
double milli = time_within_day % 1000;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> sec = args.at<Object>(2);
|
||||
Handle<Object> sec = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
|
||||
s = sec->Number();
|
||||
if (argc >= 3) {
|
||||
Handle<Object> ms = args.at<Object>(3);
|
||||
Handle<Object> ms = args.at(3);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
|
||||
milli = ms->Number();
|
||||
}
|
||||
@ -711,7 +710,7 @@ BUILTIN(DatePrototypeSetUTCMonth) {
|
||||
double m = month->Number();
|
||||
double dt = day;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> date = args.at<Object>(2);
|
||||
Handle<Object> date = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
|
||||
dt = date->Number();
|
||||
}
|
||||
@ -737,7 +736,7 @@ BUILTIN(DatePrototypeSetUTCSeconds) {
|
||||
double s = sec->Number();
|
||||
double milli = time_within_day % 1000;
|
||||
if (argc >= 2) {
|
||||
Handle<Object> ms = args.at<Object>(2);
|
||||
Handle<Object> ms = args.at(2);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
|
||||
milli = ms->Number();
|
||||
}
|
||||
@ -837,7 +836,7 @@ BUILTIN(DatePrototypeToPrimitive) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
|
||||
Handle<Object> hint = args.at<Object>(1);
|
||||
Handle<Object> hint = args.at(1);
|
||||
RETURN_RESULT_OR_FAILURE(isolate, JSDate::ToPrimitive(receiver, hint));
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,7 @@ MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate,
|
||||
if (i > 1) builder.AppendCharacter(',');
|
||||
Handle<String> param;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, param, Object::ToString(isolate, args.at<Object>(i)),
|
||||
Object);
|
||||
isolate, param, Object::ToString(isolate, args.at(i)), Object);
|
||||
param = String::Flatten(param);
|
||||
builder.AppendString(param);
|
||||
// If the formal parameters string include ) - an illegal
|
||||
@ -68,8 +67,7 @@ MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate,
|
||||
if (argc > 0) {
|
||||
Handle<String> body;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
|
||||
Object);
|
||||
isolate, body, Object::ToString(isolate, args.at(argc)), Object);
|
||||
builder.AppendString(body);
|
||||
}
|
||||
builder.AppendCString("\n})");
|
||||
@ -180,9 +178,9 @@ Object* DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
|
||||
Handle<Object> this_arg = isolate->factory()->undefined_value();
|
||||
ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
|
||||
if (args.length() > 1) {
|
||||
this_arg = args.at<Object>(1);
|
||||
this_arg = args.at(1);
|
||||
for (int i = 2; i < args.length(); ++i) {
|
||||
argv[i - 2] = args.at<Object>(i);
|
||||
argv[i - 2] = args.at(i);
|
||||
}
|
||||
}
|
||||
Handle<JSBoundFunction> function;
|
||||
|
@ -360,7 +360,7 @@ BUILTIN(MathHypot) {
|
||||
bool one_arg_is_nan = false;
|
||||
List<double> abs_values(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Handle<Object> x = args.at<Object>(i + 1);
|
||||
Handle<Object> x = args.at(i + 1);
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
|
||||
double abs_value = std::abs(x->Number());
|
||||
|
||||
|
@ -336,7 +336,7 @@ TF_BUILTIN(NumberParseInt, CodeStubAssembler) {
|
||||
// ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits )
|
||||
BUILTIN(NumberPrototypeToExponential) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
|
||||
|
||||
// Unwrap the receiver {value}.
|
||||
@ -379,7 +379,7 @@ BUILTIN(NumberPrototypeToExponential) {
|
||||
// ES6 section 20.1.3.3 Number.prototype.toFixed ( fractionDigits )
|
||||
BUILTIN(NumberPrototypeToFixed) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
|
||||
|
||||
// Unwrap the receiver {value}.
|
||||
@ -422,7 +422,7 @@ BUILTIN(NumberPrototypeToFixed) {
|
||||
// ES6 section 20.1.3.4 Number.prototype.toLocaleString ( [ r1 [ , r2 ] ] )
|
||||
BUILTIN(NumberPrototypeToLocaleString) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
|
||||
// Unwrap the receiver {value}.
|
||||
if (value->IsJSValue()) {
|
||||
@ -442,7 +442,7 @@ BUILTIN(NumberPrototypeToLocaleString) {
|
||||
// ES6 section 20.1.3.5 Number.prototype.toPrecision ( precision )
|
||||
BUILTIN(NumberPrototypeToPrecision) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
Handle<Object> precision = args.atOrUndefined(isolate, 1);
|
||||
|
||||
// Unwrap the receiver {value}.
|
||||
@ -486,7 +486,7 @@ BUILTIN(NumberPrototypeToPrecision) {
|
||||
// ES6 section 20.1.3.6 Number.prototype.toString ( [ radix ] )
|
||||
BUILTIN(NumberPrototypeToString) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
Handle<Object> radix = args.atOrUndefined(isolate, 1);
|
||||
|
||||
// Unwrap the receiver {value}.
|
||||
|
@ -162,7 +162,7 @@ BUILTIN(ObjectAssign) {
|
||||
// second argument.
|
||||
// 4. For each element nextSource of sources, in ascending index order,
|
||||
for (int i = 2; i < args.length(); ++i) {
|
||||
Handle<Object> next_source = args.at<Object>(i);
|
||||
Handle<Object> next_source = args.at(i);
|
||||
Maybe<bool> fast_assign = FastAssign(to, next_source);
|
||||
if (fast_assign.IsNothing()) return isolate->heap()->exception();
|
||||
if (fast_assign.FromJust()) continue;
|
||||
@ -558,8 +558,8 @@ void Builtins::Generate_ObjectCreate(compiler::CodeAssemblerState* state) {
|
||||
BUILTIN(ObjectDefineProperties) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> properties = args.at<Object>(2);
|
||||
Handle<Object> target = args.at(1);
|
||||
Handle<Object> properties = args.at(2);
|
||||
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, JSReceiver::DefineProperties(isolate, target, properties));
|
||||
@ -569,9 +569,9 @@ BUILTIN(ObjectDefineProperties) {
|
||||
BUILTIN(ObjectDefineProperty) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(4, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> key = args.at<Object>(2);
|
||||
Handle<Object> attributes = args.at<Object>(3);
|
||||
Handle<Object> target = args.at(1);
|
||||
Handle<Object> key = args.at(2);
|
||||
Handle<Object> attributes = args.at(3);
|
||||
|
||||
return JSReceiver::DefineProperty(isolate, target, key, attributes);
|
||||
}
|
||||
@ -671,9 +671,9 @@ Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
|
||||
// https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
|
||||
BUILTIN(ObjectDefineGetter) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> object = args.at<Object>(0); // Receiver.
|
||||
Handle<Object> name = args.at<Object>(1);
|
||||
Handle<Object> getter = args.at<Object>(2);
|
||||
Handle<Object> object = args.at(0); // Receiver.
|
||||
Handle<Object> name = args.at(1);
|
||||
Handle<Object> getter = args.at(2);
|
||||
return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
|
||||
}
|
||||
|
||||
@ -681,9 +681,9 @@ BUILTIN(ObjectDefineGetter) {
|
||||
// https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
|
||||
BUILTIN(ObjectDefineSetter) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> object = args.at<Object>(0); // Receiver.
|
||||
Handle<Object> name = args.at<Object>(1);
|
||||
Handle<Object> setter = args.at<Object>(2);
|
||||
Handle<Object> object = args.at(0); // Receiver.
|
||||
Handle<Object> name = args.at(1);
|
||||
Handle<Object> setter = args.at(2);
|
||||
return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
|
||||
}
|
||||
|
||||
@ -691,8 +691,8 @@ BUILTIN(ObjectDefineSetter) {
|
||||
// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
|
||||
BUILTIN(ObjectLookupGetter) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> name = args.at<Object>(1);
|
||||
Handle<Object> object = args.at(0);
|
||||
Handle<Object> name = args.at(1);
|
||||
return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
|
||||
}
|
||||
|
||||
@ -700,8 +700,8 @@ BUILTIN(ObjectLookupGetter) {
|
||||
// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
|
||||
BUILTIN(ObjectLookupSetter) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> name = args.at<Object>(1);
|
||||
Handle<Object> object = args.at(0);
|
||||
Handle<Object> name = args.at(1);
|
||||
return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
|
||||
}
|
||||
|
||||
@ -790,7 +790,7 @@ BUILTIN(ObjectPrototypeSetProto) {
|
||||
}
|
||||
|
||||
// 2. If Type(proto) is neither Object nor Null, return undefined.
|
||||
Handle<Object> proto = args.at<Object>(1);
|
||||
Handle<Object> proto = args.at(1);
|
||||
if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
@ -865,8 +865,8 @@ BUILTIN(ObjectGetOwnPropertySymbols) {
|
||||
BUILTIN(ObjectIs) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
Handle<Object> value1 = args.at<Object>(1);
|
||||
Handle<Object> value2 = args.at<Object>(2);
|
||||
Handle<Object> value1 = args.at(1);
|
||||
Handle<Object> value2 = args.at(2);
|
||||
return isolate->heap()->ToBoolean(value1->SameValue(*value2));
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ BUILTIN(CreateResolvingFunctions) {
|
||||
DCHECK_EQ(3, args.length());
|
||||
|
||||
Handle<JSObject> promise = args.at<JSObject>(1);
|
||||
Handle<Object> debug_event = args.at<Object>(2);
|
||||
Handle<Object> debug_event = args.at(2);
|
||||
Handle<JSFunction> resolve, reject;
|
||||
|
||||
PromiseUtils::CreateResolvingFunctions(isolate, promise, debug_event,
|
||||
|
@ -17,9 +17,9 @@ namespace internal {
|
||||
BUILTIN(ReflectDefineProperty) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(4, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> key = args.at<Object>(2);
|
||||
Handle<Object> attributes = args.at<Object>(3);
|
||||
Handle<Object> target = args.at(1);
|
||||
Handle<Object> key = args.at(2);
|
||||
Handle<Object> attributes = args.at(3);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -48,8 +48,8 @@ BUILTIN(ReflectDefineProperty) {
|
||||
BUILTIN(ReflectDeleteProperty) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> key = args.at<Object>(2);
|
||||
Handle<Object> target = args.at(1);
|
||||
Handle<Object> key = args.at(2);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -73,7 +73,7 @@ BUILTIN(ReflectGet) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> target = args.atOrUndefined(isolate, 1);
|
||||
Handle<Object> key = args.atOrUndefined(isolate, 2);
|
||||
Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
|
||||
Handle<Object> receiver = args.length() > 3 ? args.at(3) : target;
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -95,8 +95,8 @@ BUILTIN(ReflectGet) {
|
||||
BUILTIN(ReflectGetOwnPropertyDescriptor) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> key = args.at<Object>(2);
|
||||
Handle<Object> target = args.at(1);
|
||||
Handle<Object> key = args.at(2);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -121,7 +121,7 @@ BUILTIN(ReflectGetOwnPropertyDescriptor) {
|
||||
BUILTIN(ReflectGetPrototypeOf) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> target = args.at(1);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -138,8 +138,8 @@ BUILTIN(ReflectGetPrototypeOf) {
|
||||
BUILTIN(ReflectHas) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> key = args.at<Object>(2);
|
||||
Handle<Object> target = args.at(1);
|
||||
Handle<Object> key = args.at(2);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -162,7 +162,7 @@ BUILTIN(ReflectHas) {
|
||||
BUILTIN(ReflectIsExtensible) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> target = args.at(1);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -181,7 +181,7 @@ BUILTIN(ReflectIsExtensible) {
|
||||
BUILTIN(ReflectOwnKeys) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> target = args.at(1);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -203,7 +203,7 @@ BUILTIN(ReflectOwnKeys) {
|
||||
BUILTIN(ReflectPreventExtensions) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> target = args.at(1);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -224,7 +224,7 @@ BUILTIN(ReflectSet) {
|
||||
Handle<Object> target = args.atOrUndefined(isolate, 1);
|
||||
Handle<Object> key = args.atOrUndefined(isolate, 2);
|
||||
Handle<Object> value = args.atOrUndefined(isolate, 3);
|
||||
Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
|
||||
Handle<Object> receiver = args.length() > 4 ? args.at(4) : target;
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
@ -249,8 +249,8 @@ BUILTIN(ReflectSet) {
|
||||
BUILTIN(ReflectSetPrototypeOf) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
Handle<Object> target = args.at<Object>(1);
|
||||
Handle<Object> proto = args.at<Object>(2);
|
||||
Handle<Object> target = args.at(1);
|
||||
Handle<Object> proto = args.at(2);
|
||||
|
||||
if (!target->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
|
@ -14,6 +14,46 @@ namespace internal {
|
||||
typedef CodeStubAssembler::ResultMode ResultMode;
|
||||
typedef CodeStubAssembler::RelationalComparisonMode RelationalComparisonMode;
|
||||
|
||||
class StringBuiltinsAssembler : public CodeStubAssembler {
|
||||
public:
|
||||
explicit StringBuiltinsAssembler(compiler::CodeAssemblerState* state)
|
||||
: CodeStubAssembler(state) {}
|
||||
|
||||
protected:
|
||||
Node* LoadOneByteChar(Node* string, Node* index) {
|
||||
return Load(MachineType::Uint8(), string, OneByteCharOffset(index));
|
||||
}
|
||||
|
||||
Node* OneByteCharAddress(Node* string, Node* index) {
|
||||
Node* offset = OneByteCharOffset(index);
|
||||
return IntPtrAdd(BitcastTaggedToWord(string), offset);
|
||||
}
|
||||
|
||||
Node* OneByteCharOffset(Node* index) {
|
||||
return CharOffset(String::ONE_BYTE_ENCODING, index);
|
||||
}
|
||||
|
||||
Node* CharOffset(String::Encoding encoding, Node* index) {
|
||||
const int header = SeqOneByteString::kHeaderSize - kHeapObjectTag;
|
||||
Node* offset = index;
|
||||
if (encoding == String::TWO_BYTE_ENCODING) {
|
||||
offset = IntPtrAddFoldConstants(offset, offset);
|
||||
}
|
||||
offset = IntPtrAddFoldConstants(offset, IntPtrConstant(header));
|
||||
return offset;
|
||||
}
|
||||
|
||||
void BranchIfSimpleOneByteStringInstanceType(Node* instance_type,
|
||||
Label* if_true,
|
||||
Label* if_false) {
|
||||
const int kMask = kStringRepresentationMask | kStringEncodingMask;
|
||||
const int kType = kOneByteStringTag | kSeqStringTag;
|
||||
Branch(Word32Equal(Word32And(instance_type, Int32Constant(kMask)),
|
||||
Int32Constant(kType)),
|
||||
if_true, if_false);
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
void GenerateStringEqual(CodeStubAssembler* assembler, ResultMode mode) {
|
||||
@ -567,7 +607,7 @@ bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
|
||||
}
|
||||
|
||||
uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
|
||||
Handle<Object> value = args.at<Object>(1 + index);
|
||||
Handle<Object> value = args.at(1 + index);
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::ToNumber(value), -1);
|
||||
if (!IsValidCodePoint(isolate, value)) {
|
||||
isolate->Throw(*isolate->factory()->NewRangeError(
|
||||
@ -831,13 +871,131 @@ BUILTIN(StringPrototypeIncludes) {
|
||||
return *isolate->factory()->ToBoolean(index_in_str != -1);
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.8 String.prototype.indexOf ( searchString [ , position ] )
|
||||
BUILTIN(StringPrototypeIndexOf) {
|
||||
HandleScope handle_scope(isolate);
|
||||
// ES6 #sec-string.prototype.indexof
|
||||
TF_BUILTIN(StringPrototypeIndexOf, StringBuiltinsAssembler) {
|
||||
Variable search_string(this, MachineRepresentation::kTagged),
|
||||
position(this, MachineRepresentation::kTagged);
|
||||
Label call_runtime(this), call_runtime_unchecked(this), argc_0(this),
|
||||
no_argc_0(this), argc_1(this), no_argc_1(this), argc_2(this),
|
||||
fast_path(this), return_minus_1(this);
|
||||
|
||||
return String::IndexOf(isolate, args.receiver(),
|
||||
args.atOrUndefined(isolate, 1),
|
||||
args.atOrUndefined(isolate, 2));
|
||||
Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
|
||||
Node* context = Parameter(BuiltinDescriptor::kContext);
|
||||
|
||||
CodeStubArguments arguments(this, argc);
|
||||
Node* receiver = arguments.GetReceiver();
|
||||
// From now on use word-size argc value.
|
||||
argc = arguments.GetLength();
|
||||
|
||||
GotoIf(IntPtrEqual(argc, IntPtrConstant(0)), &argc_0);
|
||||
GotoIf(IntPtrEqual(argc, IntPtrConstant(1)), &argc_1);
|
||||
Goto(&argc_2);
|
||||
Bind(&argc_0);
|
||||
{
|
||||
Comment("0 Argument case");
|
||||
Node* undefined = UndefinedConstant();
|
||||
search_string.Bind(undefined);
|
||||
position.Bind(undefined);
|
||||
Goto(&call_runtime);
|
||||
}
|
||||
Bind(&argc_1);
|
||||
{
|
||||
Comment("1 Argument case");
|
||||
search_string.Bind(arguments.AtIndex(0));
|
||||
position.Bind(SmiConstant(0));
|
||||
Goto(&fast_path);
|
||||
}
|
||||
Bind(&argc_2);
|
||||
{
|
||||
Comment("2 Argument case");
|
||||
search_string.Bind(arguments.AtIndex(0));
|
||||
position.Bind(arguments.AtIndex(1));
|
||||
GotoUnless(TaggedIsSmi(position.value()), &call_runtime);
|
||||
Goto(&fast_path);
|
||||
}
|
||||
|
||||
Bind(&fast_path);
|
||||
{
|
||||
Comment("Fast Path");
|
||||
Label zero_length_needle(this);
|
||||
GotoIf(TaggedIsSmi(receiver), &call_runtime);
|
||||
Node* needle = search_string.value();
|
||||
GotoIf(TaggedIsSmi(needle), &call_runtime);
|
||||
Node* instance_type = LoadInstanceType(receiver);
|
||||
GotoUnless(IsStringInstanceType(instance_type), &call_runtime);
|
||||
|
||||
Node* needle_instance_type = LoadInstanceType(needle);
|
||||
GotoUnless(IsStringInstanceType(needle_instance_type), &call_runtime);
|
||||
|
||||
// At this point we know that the receiver and the needle are Strings and
|
||||
// that position is a Smi.
|
||||
|
||||
Node* needle_length = SmiUntag(LoadStringLength(needle));
|
||||
// Use possibly faster runtime fallback for long search strings.
|
||||
GotoIf(IntPtrLessThan(IntPtrConstant(1), needle_length),
|
||||
&call_runtime_unchecked);
|
||||
Node* string_length = SmiUntag(LoadStringLength(receiver));
|
||||
Node* start_position = SmiUntag(position.value());
|
||||
|
||||
GotoIf(IntPtrEqual(IntPtrConstant(0), needle_length), &zero_length_needle);
|
||||
// Check that the needle fits in the start position.
|
||||
GotoUnless(IntPtrLessThanOrEqual(needle_length,
|
||||
IntPtrSub(string_length, start_position)),
|
||||
&return_minus_1);
|
||||
// Only support one-byte strings on the fast path.
|
||||
Label check_needle(this), continue_fast_path(this);
|
||||
BranchIfSimpleOneByteStringInstanceType(instance_type, &check_needle,
|
||||
&call_runtime_unchecked);
|
||||
Bind(&check_needle);
|
||||
BranchIfSimpleOneByteStringInstanceType(
|
||||
needle_instance_type, &continue_fast_path, &call_runtime_unchecked);
|
||||
Bind(&continue_fast_path);
|
||||
{
|
||||
Node* needle_byte =
|
||||
ChangeInt32ToIntPtr(LoadOneByteChar(needle, IntPtrConstant(0)));
|
||||
Node* start_address = OneByteCharAddress(receiver, start_position);
|
||||
Node* search_length = IntPtrSub(string_length, start_position);
|
||||
// Call out to the highly optimized memchr to perform the actual byte
|
||||
// search.
|
||||
Node* memchr =
|
||||
ExternalConstant(ExternalReference::libc_memchr_function(isolate()));
|
||||
Node* result_address =
|
||||
CallCFunction3(MachineType::Pointer(), MachineType::Pointer(),
|
||||
MachineType::IntPtr(), MachineType::UintPtr(), memchr,
|
||||
start_address, needle_byte, search_length);
|
||||
GotoIf(WordEqual(result_address, IntPtrConstant(0)), &return_minus_1);
|
||||
Node* result_index =
|
||||
IntPtrAdd(IntPtrSub(result_address, start_address), start_position);
|
||||
arguments.PopAndReturn(SmiTag(result_index));
|
||||
}
|
||||
Bind(&zero_length_needle);
|
||||
{
|
||||
Comment("0-length needle");
|
||||
arguments.PopAndReturn(SmiTag(IntPtrMin(string_length, start_position)));
|
||||
}
|
||||
}
|
||||
|
||||
Bind(&return_minus_1);
|
||||
{ arguments.PopAndReturn(SmiConstant(-1)); }
|
||||
|
||||
Bind(&call_runtime);
|
||||
{
|
||||
Comment("Call Runtime");
|
||||
Node* result = CallRuntime(Runtime::kStringIndexOf, context, receiver,
|
||||
search_string.value(), position.value());
|
||||
arguments.PopAndReturn(result);
|
||||
}
|
||||
|
||||
Bind(&call_runtime_unchecked);
|
||||
{
|
||||
// Simplified version of the runtime call where the types of the arguments
|
||||
// are already known due to type checks in this stub.
|
||||
Comment("Call Runtime Unchecked");
|
||||
Node* result =
|
||||
CallRuntime(Runtime::kStringIndexOfUnchecked, context, receiver,
|
||||
search_string.value(), position.value());
|
||||
arguments.PopAndReturn(result);
|
||||
}
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.9
|
||||
@ -861,8 +1019,8 @@ BUILTIN(StringPrototypeLocaleCompare) {
|
||||
|
||||
TO_THIS_STRING(str1, "String.prototype.localeCompare");
|
||||
Handle<String> str2;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, str2, Object::ToString(isolate, args.at<Object>(1)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, str2,
|
||||
Object::ToString(isolate, args.at(1)));
|
||||
|
||||
if (str1.is_identical_to(str2)) return Smi::kZero; // Equal.
|
||||
int str1_length = str1->length();
|
||||
|
@ -30,7 +30,7 @@ class BuiltinArguments : public Arguments {
|
||||
return Arguments::operator[](index);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
template <class S = Object>
|
||||
Handle<S> at(int index) {
|
||||
DCHECK_LT(index, length());
|
||||
return Arguments::at<S>(index);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4380,6 +4380,11 @@ Node* CodeStubAssembler::IntPtrMax(Node* left, Node* right) {
|
||||
MachineType::PointerRepresentation());
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::IntPtrMin(Node* left, Node* right) {
|
||||
return SelectConstant(IntPtrLessThanOrEqual(left, right), left, right,
|
||||
MachineType::PointerRepresentation());
|
||||
}
|
||||
|
||||
template <class Dictionary>
|
||||
Node* CodeStubAssembler::GetNumberOfElements(Node* dictionary) {
|
||||
return LoadFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex);
|
||||
|
@ -139,7 +139,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
Node* IntPtrSubFoldConstants(Node* left, Node* right);
|
||||
// Round the 32bits payload of the provided word up to the next power of two.
|
||||
Node* IntPtrRoundUpToPowerOfTwo32(Node* value);
|
||||
// Select the maximum of the two provided IntPtr values.
|
||||
Node* IntPtrMax(Node* left, Node* right);
|
||||
// Select the minimum of the two provided IntPtr values.
|
||||
Node* IntPtrMin(Node* left, Node* right);
|
||||
|
||||
// Float64 operations.
|
||||
Node* Float64Ceil(Node* x);
|
||||
|
@ -546,6 +546,15 @@ Node* CodeAssembler::CallCFunction2(MachineType return_type,
|
||||
function, arg0, arg1);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::CallCFunction3(MachineType return_type,
|
||||
MachineType arg0_type,
|
||||
MachineType arg1_type,
|
||||
MachineType arg2_type, Node* function,
|
||||
Node* arg0, Node* arg1, Node* arg2) {
|
||||
return raw_assembler()->CallCFunction3(return_type, arg0_type, arg1_type,
|
||||
arg2_type, function, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
void CodeAssembler::Goto(Label* label) {
|
||||
label->MergeVariables();
|
||||
raw_assembler()->Goto(label->label_);
|
||||
@ -718,12 +727,13 @@ void CodeAssemblerLabel::Bind() {
|
||||
for (auto var : variable_phis_) {
|
||||
CodeAssemblerVariable::Impl* var_impl = var.first;
|
||||
auto i = variable_merges_.find(var_impl);
|
||||
// If the following assert fires, then a variable that has been marked as
|
||||
// If the following asserts fire, then a variable that has been marked as
|
||||
// being merged at the label--either by explicitly marking it so in the
|
||||
// label constructor or by having seen different bound values at branches
|
||||
// into the label--doesn't have a bound value along all of the paths that
|
||||
// have been merged into the label up to this point.
|
||||
DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
|
||||
DCHECK(i != variable_merges_.end());
|
||||
DCHECK_EQ(i->second.size(), merge_count_);
|
||||
Node* phi = state_->raw_assembler_->Phi(
|
||||
var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
|
||||
variable_phis_[var_impl] = phi;
|
||||
|
@ -163,6 +163,7 @@ typedef ZoneList<CodeAssemblerVariable*> CodeAssemblerVariableList;
|
||||
V(Float64RoundTiesEven) \
|
||||
V(Float64RoundTruncate) \
|
||||
V(Word32Clz) \
|
||||
V(Word32Not) \
|
||||
V(Word32BinaryNot)
|
||||
|
||||
// A "public" interface used by components outside of compiler directory to
|
||||
@ -354,6 +355,11 @@ class V8_EXPORT_PRIVATE CodeAssembler {
|
||||
MachineType arg1_type, Node* function, Node* arg0,
|
||||
Node* arg1);
|
||||
|
||||
// Call to a C function with three arguments.
|
||||
Node* CallCFunction3(MachineType return_type, MachineType arg0_type,
|
||||
MachineType arg1_type, MachineType arg2_type,
|
||||
Node* function, Node* arg0, Node* arg1, Node* arg2);
|
||||
|
||||
// Exception handling support.
|
||||
void GotoIfException(Node* node, Label* if_exception,
|
||||
Variable* exception_var = nullptr);
|
||||
|
@ -254,6 +254,21 @@ Node* RawMachineAssembler::CallCFunction2(MachineType return_type,
|
||||
return AddNode(common()->Call(descriptor), function, arg0, arg1);
|
||||
}
|
||||
|
||||
Node* RawMachineAssembler::CallCFunction3(MachineType return_type,
|
||||
MachineType arg0_type,
|
||||
MachineType arg1_type,
|
||||
MachineType arg2_type, Node* function,
|
||||
Node* arg0, Node* arg1, Node* arg2) {
|
||||
MachineSignature::Builder builder(zone(), 1, 3);
|
||||
builder.AddReturn(return_type);
|
||||
builder.AddParam(arg0_type);
|
||||
builder.AddParam(arg1_type);
|
||||
builder.AddParam(arg2_type);
|
||||
const CallDescriptor* descriptor =
|
||||
Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
|
||||
|
||||
return AddNode(common()->Call(descriptor), function, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
Node* RawMachineAssembler::CallCFunction8(
|
||||
MachineType return_type, MachineType arg0_type, MachineType arg1_type,
|
||||
|
@ -723,6 +723,10 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
|
||||
Node* CallCFunction2(MachineType return_type, MachineType arg0_type,
|
||||
MachineType arg1_type, Node* function, Node* arg0,
|
||||
Node* arg1);
|
||||
// Call to a C function with three arguments.
|
||||
Node* CallCFunction3(MachineType return_type, MachineType arg0_type,
|
||||
MachineType arg1_type, MachineType arg2_type,
|
||||
Node* function, Node* arg0, Node* arg1, Node* arg2);
|
||||
// Call to a C function with eight arguments.
|
||||
Node* CallCFunction8(MachineType return_type, MachineType arg0_type,
|
||||
MachineType arg1_type, MachineType arg2_type,
|
||||
|
@ -3699,9 +3699,9 @@ MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array,
|
||||
JSArray::Initialize(array, JSArray::kPreallocatedArrayElements);
|
||||
return array;
|
||||
|
||||
} else if (args->length() == 1 && args->at<Object>(0)->IsNumber()) {
|
||||
} else if (args->length() == 1 && args->at(0)->IsNumber()) {
|
||||
uint32_t length;
|
||||
if (!args->at<Object>(0)->ToArrayLength(&length)) {
|
||||
if (!args->at(0)->ToArrayLength(&length)) {
|
||||
return ThrowArrayLengthRangeError(array->GetIsolate());
|
||||
}
|
||||
|
||||
|
@ -230,6 +230,8 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) {
|
||||
"f64_mod_wrapper");
|
||||
Add(ExternalReference::wasm_call_trap_callback_for_testing(isolate).address(),
|
||||
"wasm::call_trap_callback_for_testing");
|
||||
Add(ExternalReference::libc_memchr_function(isolate).address(),
|
||||
"libc_memchr");
|
||||
Add(ExternalReference::log_enter_external_function(isolate).address(),
|
||||
"Logger::EnterExternal");
|
||||
Add(ExternalReference::log_leave_external_function(isolate).address(),
|
||||
|
54
src/ic/ic.cc
54
src/ic/ic.cc
@ -2636,7 +2636,7 @@ RUNTIME_FUNCTION(Runtime_CallIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
// Runtime functions don't follow the IC's calling convention.
|
||||
Handle<Object> function = args.at<Object>(0);
|
||||
Handle<Object> function = args.at(0);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
|
||||
@ -2652,7 +2652,7 @@ RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(4, args.length());
|
||||
// Runtime functions don't follow the IC's calling convention.
|
||||
Handle<Object> receiver = args.at<Object>(0);
|
||||
Handle<Object> receiver = args.at(0);
|
||||
Handle<Name> key = args.at<Name>(1);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
@ -2749,8 +2749,8 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(4, args.length());
|
||||
// Runtime functions don't follow the IC's calling convention.
|
||||
Handle<Object> receiver = args.at<Object>(0);
|
||||
Handle<Object> key = args.at<Object>(1);
|
||||
Handle<Object> receiver = args.at(0);
|
||||
Handle<Object> key = args.at(1);
|
||||
Handle<Smi> slot = args.at<Smi>(2);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3);
|
||||
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
|
||||
@ -2765,8 +2765,8 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) {
|
||||
HandleScope scope(isolate);
|
||||
typedef LoadWithVectorDescriptor Descriptor;
|
||||
DCHECK_EQ(Descriptor::kParameterCount, args.length());
|
||||
Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver);
|
||||
Handle<Object> key = args.at<Object>(Descriptor::kName);
|
||||
Handle<Object> receiver = args.at(Descriptor::kReceiver);
|
||||
Handle<Object> key = args.at(Descriptor::kName);
|
||||
Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot);
|
||||
Handle<TypeFeedbackVector> vector =
|
||||
args.at<TypeFeedbackVector>(Descriptor::kVector);
|
||||
@ -2783,10 +2783,10 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(5, args.length());
|
||||
// Runtime functions don't follow the IC's calling convention.
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
Handle<Smi> slot = args.at<Smi>(1);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
|
||||
Handle<Object> receiver = args.at<Object>(3);
|
||||
Handle<Object> receiver = args.at(3);
|
||||
Handle<Name> key = args.at<Name>(4);
|
||||
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
|
||||
if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) {
|
||||
@ -2810,11 +2810,11 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(5, args.length());
|
||||
// Runtime functions don't follow the IC's calling convention.
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
Handle<Smi> slot = args.at<Smi>(1);
|
||||
Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
|
||||
Handle<Object> receiver = args.at<Object>(3);
|
||||
Handle<Object> key = args.at<Object>(4);
|
||||
Handle<Object> receiver = args.at(3);
|
||||
Handle<Object> key = args.at(4);
|
||||
FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value());
|
||||
KeyedStoreICNexus nexus(vector, vector_slot);
|
||||
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
@ -2827,10 +2827,10 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(5, args.length());
|
||||
// Runtime functions don't follow the IC's calling convention.
|
||||
Handle<Object> value = args.at<Object>(0);
|
||||
Handle<Object> value = args.at(0);
|
||||
// slot and vector parameters are not used.
|
||||
Handle<Object> object = args.at<Object>(3);
|
||||
Handle<Object> key = args.at<Object>(4);
|
||||
Handle<Object> object = args.at(3);
|
||||
Handle<Object> key = args.at(4);
|
||||
LanguageMode language_mode;
|
||||
KeyedStoreICNexus nexus(isolate);
|
||||
KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
@ -2844,9 +2844,9 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {
|
||||
RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
// Runtime functions don't follow the IC's calling convention.
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> key = args.at<Object>(1);
|
||||
Handle<Object> value = args.at<Object>(2);
|
||||
Handle<Object> object = args.at(0);
|
||||
Handle<Object> key = args.at(1);
|
||||
Handle<Object> value = args.at(2);
|
||||
Handle<Map> map = args.at<Map>(3);
|
||||
LanguageMode language_mode;
|
||||
KeyedStoreICNexus nexus(isolate);
|
||||
@ -2995,8 +2995,8 @@ RUNTIME_FUNCTION(Runtime_BinaryOpIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
typedef BinaryOpDescriptor Descriptor;
|
||||
Handle<Object> left = args.at<Object>(Descriptor::kLeft);
|
||||
Handle<Object> right = args.at<Object>(Descriptor::kRight);
|
||||
Handle<Object> left = args.at(Descriptor::kLeft);
|
||||
Handle<Object> right = args.at(Descriptor::kRight);
|
||||
BinaryOpIC ic(isolate);
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, ic.Transition(Handle<AllocationSite>::null(), left, right));
|
||||
@ -3009,8 +3009,8 @@ RUNTIME_FUNCTION(Runtime_BinaryOpIC_MissWithAllocationSite) {
|
||||
typedef BinaryOpWithAllocationSiteDescriptor Descriptor;
|
||||
Handle<AllocationSite> allocation_site =
|
||||
args.at<AllocationSite>(Descriptor::kAllocationSite);
|
||||
Handle<Object> left = args.at<Object>(Descriptor::kLeft);
|
||||
Handle<Object> right = args.at<Object>(Descriptor::kRight);
|
||||
Handle<Object> left = args.at(Descriptor::kLeft);
|
||||
Handle<Object> right = args.at(Descriptor::kRight);
|
||||
BinaryOpIC ic(isolate);
|
||||
RETURN_RESULT_OR_FAILURE(isolate,
|
||||
ic.Transition(allocation_site, left, right));
|
||||
@ -3093,7 +3093,7 @@ RUNTIME_FUNCTION(Runtime_CompareIC_Miss) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
|
||||
return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
|
||||
return ic.UpdateCaches(args.at(0), args.at(1));
|
||||
}
|
||||
|
||||
|
||||
@ -3116,7 +3116,7 @@ Handle<Object> ToBooleanIC::ToBoolean(Handle<Object> object) {
|
||||
RUNTIME_FUNCTION(Runtime_ToBooleanIC_Miss) {
|
||||
DCHECK(args.length() == 1);
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> object = args.at(0);
|
||||
ToBooleanIC ic(isolate);
|
||||
return *ic.ToBoolean(object);
|
||||
}
|
||||
@ -3127,7 +3127,7 @@ RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
|
||||
Handle<JSObject> holder = args.at<JSObject>(1);
|
||||
Handle<HeapObject> callback_or_cell = args.at<HeapObject>(2);
|
||||
Handle<Name> name = args.at<Name>(3);
|
||||
Handle<Object> value = args.at<Object>(4);
|
||||
Handle<Object> value = args.at(4);
|
||||
CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 5);
|
||||
HandleScope scope(isolate);
|
||||
|
||||
@ -3171,7 +3171,7 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly) {
|
||||
Handle<Name> name =
|
||||
args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
|
||||
Handle<Object> receiver =
|
||||
args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
|
||||
args.at(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
|
||||
Handle<JSObject> holder =
|
||||
args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
|
||||
HandleScope scope(isolate);
|
||||
@ -3207,7 +3207,7 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {
|
||||
Handle<Name> name =
|
||||
args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex);
|
||||
Handle<Object> receiver =
|
||||
args.at<Object>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
|
||||
args.at(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex);
|
||||
Handle<JSObject> holder =
|
||||
args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex);
|
||||
|
||||
@ -3263,7 +3263,7 @@ RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {
|
||||
StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus);
|
||||
Handle<JSObject> receiver = args.at<JSObject>(0);
|
||||
Handle<Name> name = args.at<Name>(1);
|
||||
Handle<Object> value = args.at<Object>(2);
|
||||
Handle<Object> value = args.at(2);
|
||||
|
||||
DCHECK(receiver->HasNamedInterceptor());
|
||||
InterceptorInfo* interceptor = receiver->GetNamedInterceptor();
|
||||
|
@ -79,28 +79,16 @@ class MachineType {
|
||||
return semantic() == MachineSemantic::kUint32 ||
|
||||
semantic() == MachineSemantic::kUint64;
|
||||
}
|
||||
|
||||
static MachineRepresentation PointerRepresentation() {
|
||||
return (kPointerSize == 4) ? MachineRepresentation::kWord32
|
||||
: MachineRepresentation::kWord64;
|
||||
}
|
||||
static MachineType Pointer() {
|
||||
return MachineType(PointerRepresentation(), MachineSemantic::kNone);
|
||||
static MachineType UintPtr() {
|
||||
return (kPointerSize == 4) ? Uint32() : Uint64();
|
||||
}
|
||||
static MachineType IntPtr() {
|
||||
return (kPointerSize == 4) ? Int32() : Int64();
|
||||
}
|
||||
static MachineType Float32() {
|
||||
return MachineType(MachineRepresentation::kFloat32,
|
||||
MachineSemantic::kNumber);
|
||||
}
|
||||
static MachineType Float64() {
|
||||
return MachineType(MachineRepresentation::kFloat64,
|
||||
MachineSemantic::kNumber);
|
||||
}
|
||||
static MachineType Simd128() {
|
||||
return MachineType(MachineRepresentation::kSimd128, MachineSemantic::kNone);
|
||||
}
|
||||
static MachineType Int8() {
|
||||
return MachineType(MachineRepresentation::kWord8, MachineSemantic::kInt32);
|
||||
}
|
||||
@ -128,6 +116,20 @@ class MachineType {
|
||||
return MachineType(MachineRepresentation::kWord64,
|
||||
MachineSemantic::kUint64);
|
||||
}
|
||||
static MachineType Float32() {
|
||||
return MachineType(MachineRepresentation::kFloat32,
|
||||
MachineSemantic::kNumber);
|
||||
}
|
||||
static MachineType Float64() {
|
||||
return MachineType(MachineRepresentation::kFloat64,
|
||||
MachineSemantic::kNumber);
|
||||
}
|
||||
static MachineType Simd128() {
|
||||
return MachineType(MachineRepresentation::kSimd128, MachineSemantic::kNone);
|
||||
}
|
||||
static MachineType Pointer() {
|
||||
return MachineType(PointerRepresentation(), MachineSemantic::kNone);
|
||||
}
|
||||
static MachineType TaggedPointer() {
|
||||
return MachineType(MachineRepresentation::kTaggedPointer,
|
||||
MachineSemantic::kAny);
|
||||
|
@ -9919,6 +9919,7 @@ class String: public Name {
|
||||
// returned structure will report so, and can't provide a vector of either
|
||||
// kind.
|
||||
FlatContent GetFlatContent();
|
||||
FlatContent GetFlattenedContent();
|
||||
|
||||
// Returns the parent of a sliced string or first part of a flat cons string.
|
||||
// Requires: StringShape(this).IsIndirect() && this->IsFlat()
|
||||
|
@ -537,7 +537,7 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, from_index, 2);
|
||||
|
||||
// Let O be ? ToObject(this value).
|
||||
Handle<Object> receiver_obj = args.at<Object>(0);
|
||||
Handle<Object> receiver_obj = args.at(0);
|
||||
if (receiver_obj->IsNull(isolate) || receiver_obj->IsUndefined(isolate)) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
|
||||
@ -545,8 +545,8 @@ RUNTIME_FUNCTION(Runtime_ArrayIndexOf) {
|
||||
"Array.prototype.indexOf")));
|
||||
}
|
||||
Handle<JSReceiver> object;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, object, Object::ToObject(isolate, args.at<Object>(0)));
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
|
||||
Object::ToObject(isolate, args.at(0)));
|
||||
|
||||
// Let len be ? ToLength(? Get(O, "length")).
|
||||
int64_t len;
|
||||
|
@ -454,7 +454,7 @@ RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 6);
|
||||
|
||||
Handle<Object> callee = args.at<Object>(0);
|
||||
Handle<Object> callee = args.at(0);
|
||||
|
||||
// If "eval" didn't refer to the original GlobalEval, it's not a
|
||||
// direct call to eval.
|
||||
|
@ -278,7 +278,7 @@ RUNTIME_FUNCTION(Runtime_Call) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
|
||||
ScopedVector<Handle<Object>> argv(argc);
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
argv[i] = args.at<Object>(2 + i);
|
||||
argv[i] = args.at(2 + i);
|
||||
}
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, Execution::Call(isolate, target, receiver, argc, argv.start()));
|
||||
|
@ -106,9 +106,9 @@ RUNTIME_FUNCTION(Runtime_ThrowTypeError) {
|
||||
CONVERT_SMI_ARG_CHECKED(message_id_smi, 0);
|
||||
|
||||
Handle<Object> undefined = isolate->factory()->undefined_value();
|
||||
Handle<Object> arg0 = (args.length() > 1) ? args.at<Object>(1) : undefined;
|
||||
Handle<Object> arg1 = (args.length() > 2) ? args.at<Object>(2) : undefined;
|
||||
Handle<Object> arg2 = (args.length() > 3) ? args.at<Object>(3) : undefined;
|
||||
Handle<Object> arg0 = (args.length() > 1) ? args.at(1) : undefined;
|
||||
Handle<Object> arg1 = (args.length() > 2) ? args.at(2) : undefined;
|
||||
Handle<Object> arg2 = (args.length() > 3) ? args.at(3) : undefined;
|
||||
|
||||
MessageTemplate::Template message_id =
|
||||
static_cast<MessageTemplate::Template>(message_id_smi);
|
||||
|
@ -133,7 +133,7 @@ Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate,
|
||||
// ES6 19.1.3.2
|
||||
RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> property = args.at<Object>(1);
|
||||
Handle<Object> property = args.at(1);
|
||||
|
||||
Handle<Name> key;
|
||||
uint32_t index;
|
||||
@ -145,7 +145,7 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
|
||||
key_is_array_index = key->AsArrayIndex(&index);
|
||||
}
|
||||
|
||||
Handle<Object> object = args.at<Object>(0);
|
||||
Handle<Object> object = args.at(0);
|
||||
|
||||
if (object->IsJSObject()) {
|
||||
Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
|
||||
@ -212,7 +212,7 @@ RUNTIME_FUNCTION(Runtime_ObjectHasOwnProperty) {
|
||||
// an Object.create stub.
|
||||
RUNTIME_FUNCTION(Runtime_ObjectCreate) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> prototype = args.at<Object>(0);
|
||||
Handle<Object> prototype = args.at(0);
|
||||
if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
|
||||
@ -262,7 +262,7 @@ RUNTIME_FUNCTION(Runtime_ObjectCreate) {
|
||||
}
|
||||
|
||||
// Define the properties if properties was specified and is not undefined.
|
||||
Handle<Object> properties = args.at<Object>(1);
|
||||
Handle<Object> properties = args.at(1);
|
||||
if (!properties->IsUndefined(isolate)) {
|
||||
RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, JSReceiver::DefineProperties(isolate, object, properties));
|
||||
|
@ -44,7 +44,7 @@ RUNTIME_FUNCTION(Runtime_JSProxyCall) {
|
||||
// 6.a. Return Call(target, thisArgument, argumentsList).
|
||||
ScopedVector<Handle<Object>> argv(arguments_length);
|
||||
for (int i = 0; i < arguments_length; ++i) {
|
||||
argv[i] = args.at<Object>(i + 1);
|
||||
argv[i] = args.at(i + 1);
|
||||
}
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, Execution::Call(isolate, target, receiver, arguments_length,
|
||||
@ -100,7 +100,7 @@ RUNTIME_FUNCTION(Runtime_JSProxyConstruct) {
|
||||
// 6.b. Return Construct(target, argumentsList, newTarget).
|
||||
ScopedVector<Handle<Object>> argv(arguments_length);
|
||||
for (int i = 0; i < arguments_length; ++i) {
|
||||
argv[i] = args.at<Object>(i + 1);
|
||||
argv[i] = args.at(i + 1);
|
||||
}
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, Execution::New(isolate, target, new_target, arguments_length,
|
||||
|
@ -1495,7 +1495,7 @@ RUNTIME_FUNCTION(Runtime_RegExpReplace) {
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, recv, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, string, 1);
|
||||
Handle<Object> replace_obj = args.at<Object>(2);
|
||||
Handle<Object> replace_obj = args.at(2);
|
||||
|
||||
Factory* factory = isolate->factory();
|
||||
|
||||
|
@ -171,7 +171,7 @@ RUNTIME_FUNCTION(Runtime_IsSimdValue) {
|
||||
|
||||
// TODO(gdeepti): Fix to use ToNumber conversion once polyfill is updated.
|
||||
#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \
|
||||
Handle<Object> name_object = args.at<Object>(index); \
|
||||
Handle<Object> name_object = args.at(index); \
|
||||
if (!name_object->IsNumber()) { \
|
||||
THROW_NEW_ERROR_RETURN_FAILURE( \
|
||||
isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex)); \
|
||||
@ -228,10 +228,10 @@ RUNTIME_FUNCTION(Runtime_IsSimdValue) {
|
||||
|
||||
// Common functions.
|
||||
|
||||
#define GET_NUMERIC_ARG(lane_type, name, index) \
|
||||
Handle<Object> a; \
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
|
||||
isolate, a, Object::ToNumber(args.at<Object>(index))); \
|
||||
#define GET_NUMERIC_ARG(lane_type, name, index) \
|
||||
Handle<Object> a; \
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, a, \
|
||||
Object::ToNumber(args.at(index))); \
|
||||
name = ConvertNumber<lane_type>(a->Number());
|
||||
|
||||
#define GET_BOOLEAN_ARG(lane_type, name, index) \
|
||||
@ -409,7 +409,7 @@ SIMD_MAXNUM_FUNCTION(Float32x4, float, 4)
|
||||
FUNCTION(Uint8x16, uint8_t, 8, 16)
|
||||
|
||||
#define CONVERT_SHIFT_ARG_CHECKED(name, index) \
|
||||
Handle<Object> name_object = args.at<Object>(index); \
|
||||
Handle<Object> name_object = args.at(index); \
|
||||
if (!name_object->IsNumber()) { \
|
||||
THROW_NEW_ERROR_RETURN_FAILURE( \
|
||||
isolate, NewTypeError(MessageTemplate::kInvalidSimdOperation)); \
|
||||
@ -880,16 +880,16 @@ SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION)
|
||||
FUNCTION(Int32x4, int32_t, 4) \
|
||||
FUNCTION(Uint32x4, uint32_t, 4)
|
||||
|
||||
#define SIMD_COERCE_INDEX(name, i) \
|
||||
Handle<Object> length_object, number_object; \
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
|
||||
isolate, length_object, Object::ToLength(isolate, args.at<Object>(i))); \
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_object, \
|
||||
Object::ToNumber(args.at<Object>(i))); \
|
||||
if (number_object->Number() != length_object->Number()) { \
|
||||
THROW_NEW_ERROR_RETURN_FAILURE( \
|
||||
isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex)); \
|
||||
} \
|
||||
#define SIMD_COERCE_INDEX(name, i) \
|
||||
Handle<Object> length_object, number_object; \
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, length_object, \
|
||||
Object::ToLength(isolate, args.at(i))); \
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_object, \
|
||||
Object::ToNumber(args.at(i))); \
|
||||
if (number_object->Number() != length_object->Number()) { \
|
||||
THROW_NEW_ERROR_RETURN_FAILURE( \
|
||||
isolate, NewTypeError(MessageTemplate::kInvalidSimdIndex)); \
|
||||
} \
|
||||
int32_t name = number_object->Number();
|
||||
|
||||
// Common Load and Store Functions
|
||||
|
@ -86,17 +86,32 @@ RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) {
|
||||
return isolate->StackOverflow();
|
||||
}
|
||||
|
||||
|
||||
// ES6 #sec-string.prototype.indexof
|
||||
// String.prototype.indexOf(searchString [, position])
|
||||
RUNTIME_FUNCTION(Runtime_StringIndexOf) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
return String::IndexOf(isolate, args.at<Object>(0), args.at<Object>(1),
|
||||
args.at<Object>(2));
|
||||
return String::IndexOf(isolate, args.at(0), args.at(1), args.at(2));
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.indexof
|
||||
// String.prototype.indexOf(searchString, position)
|
||||
// Fast version that assumes that does not perform conversions of the incoming
|
||||
// arguments.
|
||||
RUNTIME_FUNCTION(Runtime_StringIndexOfUnchecked) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK(args.length() == 3);
|
||||
Handle<String> receiver_string = args.at<String>(0);
|
||||
Handle<String> search_string = args.at<String>(1);
|
||||
int index = std::min(std::max(args.smi_at(2), 0), receiver_string->length());
|
||||
|
||||
return Smi::FromInt(String::IndexOf(isolate, receiver_string, search_string,
|
||||
static_cast<uint32_t>(index)));
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_StringLastIndexOf) {
|
||||
HandleScope handle_scope(isolate);
|
||||
return String::LastIndexOf(isolate, args.at<Object>(0), args.at<Object>(1),
|
||||
return String::LastIndexOf(isolate, args.at(0), args.at(1),
|
||||
isolate->factory()->undefined_value());
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace internal {
|
||||
|
||||
#define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index) \
|
||||
CHECK(args[index]->IsNumber()); \
|
||||
Handle<Object> name = args.at<Object>(index);
|
||||
Handle<Object> name = args.at(index);
|
||||
|
||||
// Cast the given object to a boolean and store it in a variable with
|
||||
// the given name. If the object is not a boolean we crash safely.
|
||||
@ -47,10 +47,10 @@ namespace internal {
|
||||
|
||||
// Cast the given argument to a size_t and store its value in a variable with
|
||||
// the given name. If the argument is not a size_t we crash safely.
|
||||
#define CONVERT_SIZE_ARG_CHECKED(name, index) \
|
||||
CHECK(args[index]->IsNumber()); \
|
||||
Handle<Object> name##_object = args.at<Object>(index); \
|
||||
size_t name = 0; \
|
||||
#define CONVERT_SIZE_ARG_CHECKED(name, index) \
|
||||
CHECK(args[index]->IsNumber()); \
|
||||
Handle<Object> name##_object = args.at(index); \
|
||||
size_t name = 0; \
|
||||
CHECK(TryNumberToSize(*name##_object, &name));
|
||||
|
||||
// Call the specified converter on the object *comand store the result in
|
||||
|
@ -817,6 +817,7 @@ namespace internal {
|
||||
#define FOR_EACH_INTRINSIC_STRINGS(F) \
|
||||
F(StringReplaceOneCharWithString, 3, 1) \
|
||||
F(StringIndexOf, 3, 1) \
|
||||
F(StringIndexOfUnchecked, 3, 1) \
|
||||
F(StringLastIndexOf, 2, 1) \
|
||||
F(SubString, 3, 1) \
|
||||
F(StringAdd, 2, 1) \
|
||||
|
@ -583,7 +583,6 @@ class InitializedHandleScope {
|
||||
std::unique_ptr<InitializedHandleScopeImpl> initialized_handle_scope_impl_;
|
||||
};
|
||||
|
||||
|
||||
class HandleAndZoneScope : public InitializedHandleScope {
|
||||
public:
|
||||
HandleAndZoneScope();
|
||||
@ -597,4 +596,18 @@ class HandleAndZoneScope : public InitializedHandleScope {
|
||||
std::unique_ptr<i::Zone> main_zone_;
|
||||
};
|
||||
|
||||
class StaticOneByteResource : public v8::String::ExternalOneByteStringResource {
|
||||
public:
|
||||
explicit StaticOneByteResource(const char* data) : data_(data) {}
|
||||
|
||||
~StaticOneByteResource() {}
|
||||
|
||||
const char* data() const { return data_; }
|
||||
|
||||
size_t length() const { return strlen(data_); }
|
||||
|
||||
private:
|
||||
const char* data_;
|
||||
};
|
||||
|
||||
#endif // ifndef CCTEST_H_
|
||||
|
@ -1608,3 +1608,38 @@ TEST(Regress609831) {
|
||||
CHECK(v8::Utils::OpenHandle(*result)->IsSeqTwoByteString());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ExternalStringIndexOf) {
|
||||
CcTest::InitializeVM();
|
||||
LocalContext context;
|
||||
v8::HandleScope scope(CcTest::isolate());
|
||||
|
||||
const char* raw_string = "abcdefghijklmnopqrstuvwxyz";
|
||||
v8::Local<v8::String> string =
|
||||
v8::String::NewExternalOneByte(CcTest::isolate(),
|
||||
new StaticOneByteResource(raw_string))
|
||||
.ToLocalChecked();
|
||||
v8::Local<v8::Object> global = context->Global();
|
||||
global->Set(context.local(), v8_str("external"), string).FromJust();
|
||||
|
||||
char source[] = "external.indexOf('%')";
|
||||
for (size_t i = 0; i < strlen(raw_string); i++) {
|
||||
source[18] = raw_string[i];
|
||||
int result_position = static_cast<int>(i);
|
||||
CHECK_EQ(result_position,
|
||||
CompileRun(source)->Int32Value(context.local()).FromJust());
|
||||
}
|
||||
CHECK_EQ(-1,
|
||||
CompileRun("external.indexOf('abcdefghijklmnopqrstuvwxyz%%%%%%')")
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(1, CompileRun("external.indexOf('', 1)")
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(-1, CompileRun("external.indexOf('a', 1)")
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
CHECK_EQ(-1, CompileRun("external.indexOf('$')")
|
||||
->Int32Value(context.local())
|
||||
.FromJust());
|
||||
}
|
||||
|
@ -137,3 +137,60 @@ for (var lengthIndex = 0; lengthIndex < lengths.length; lengthIndex++) {
|
||||
assertEquals(index, allCharsString.indexOf(pattern));
|
||||
}
|
||||
}
|
||||
|
||||
(function nonStringReceivers() {
|
||||
let indexOf = String.prototype.indexOf;
|
||||
assertThrows(() => indexOf.call(null), TypeError);
|
||||
assertThrows(() => indexOf.call(undefined), TypeError);
|
||||
|
||||
assertEquals(-1, indexOf.call(1));
|
||||
assertEquals(0, indexOf.call(1, "1"));
|
||||
|
||||
assertEquals(-1, indexOf.call(1.2));
|
||||
assertEquals(0, indexOf.call(1.2, "1"));
|
||||
assertEquals(1, indexOf.call(1.2, "."));
|
||||
assertEquals(2, indexOf.call(1.2, "2"));
|
||||
assertEquals(-1, indexOf.call(1.2, "1", 2));
|
||||
|
||||
assertEquals(-1, indexOf.call({}));
|
||||
assertEquals(0, indexOf.call({}, "[object Object]"));
|
||||
assertEquals(-1, indexOf.call({}, "[object", 1));
|
||||
|
||||
assertEquals(-1, indexOf.call([]));
|
||||
assertEquals(0, indexOf.call([1,2], "1,2"));
|
||||
|
||||
assertEquals(-1, indexOf.call(this));
|
||||
})();
|
||||
|
||||
(function nonStringSearchString() {
|
||||
|
||||
assertEquals(-1, "".indexOf(1));
|
||||
assertEquals(2, "_0123".indexOf(1));
|
||||
|
||||
assertEquals(-1, "".indexOf(1.2));
|
||||
assertEquals(1, "01.2".indexOf(1.2));
|
||||
assertEquals(1, "01.2".indexOf(1.2, 1));
|
||||
assertEquals(-1, "01.2".indexOf(1.2, 2));
|
||||
|
||||
assertEquals(-1, "".indexOf(null));
|
||||
assertEquals(0, "null".indexOf(null));
|
||||
|
||||
assertEquals(-1, "".indexOf(undefined));
|
||||
assertEquals(1, "_undefined_".indexOf(undefined));
|
||||
|
||||
assertEquals(0, "".indexOf([]));
|
||||
assertEquals(0, "123".indexOf([]));
|
||||
assertEquals(2, "1,2,3".indexOf([2,3]));
|
||||
|
||||
assertEquals(-1, "".indexOf({}));
|
||||
assertEquals(-1, "".indexOf(this));
|
||||
})();
|
||||
|
||||
(function nonStringPosition() {
|
||||
assertEquals(0, "aba".indexOf("a", false));
|
||||
assertEquals(2, "aba".indexOf("a", true));
|
||||
assertEquals(2, "aba".indexOf("a", "1"));
|
||||
assertEquals(2, "aba".indexOf("a", "1.00000"));
|
||||
assertEquals(2, "aba".indexOf("a", "2.00000"));
|
||||
assertEquals(-1, "aba".indexOf("a", "3.00000"));
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user