Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/builtins.cc b/src/builtins.cc
index 75f6150..24abb72 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -7,6 +7,7 @@
#include "src/api-arguments.h"
#include "src/api-natives.h"
#include "src/api.h"
+#include "src/base/ieee754.h"
#include "src/base/once.h"
#include "src/bootstrapper.h"
#include "src/code-factory.h"
@@ -18,8 +19,9 @@
#include "src/ic/handler-compiler.h"
#include "src/ic/ic.h"
#include "src/isolate-inl.h"
+#include "src/json-parser.h"
+#include "src/json-stringifier.h"
#include "src/messages.h"
-#include "src/profiler/cpu-profiler.h"
#include "src/property-descriptor.h"
#include "src/prototype.h"
#include "src/string-builder.h"
@@ -32,7 +34,6 @@
namespace {
// Arguments object passed to C++ builtins.
-template <BuiltinExtraArguments extra_args>
class BuiltinArguments : public Arguments {
public:
BuiltinArguments(int length, Object** arguments)
@@ -63,70 +64,19 @@
}
template <class S>
- Handle<S> target();
- Handle<HeapObject> new_target();
+ Handle<S> target() {
+ return Arguments::at<S>(Arguments::length() - 2);
+ }
+ Handle<HeapObject> new_target() {
+ return Arguments::at<HeapObject>(Arguments::length() - 1);
+ }
// Gets the total number of arguments including the receiver (but
// excluding extra arguments).
- int length() const;
+ int length() const { return Arguments::length() - 2; }
};
-// Specialize BuiltinArguments for the extra arguments.
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
- return Arguments::length();
-}
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
- return Arguments::length() - 1;
-}
-
-template <>
-template <class S>
-Handle<S> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
- return Arguments::at<S>(Arguments::length() - 1);
-}
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
- return Arguments::length() - 1;
-}
-
-template <>
-Handle<HeapObject>
-BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
- return Arguments::at<HeapObject>(Arguments::length() - 1);
-}
-
-template <>
-int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
- const {
- return Arguments::length() - 2;
-}
-
-template <>
-template <class S>
-Handle<S>
-BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
- return Arguments::at<S>(Arguments::length() - 2);
-}
-
-template <>
-Handle<HeapObject>
-BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
- return Arguments::at<HeapObject>(Arguments::length() - 1);
-}
-
-
-#define DEF_ARG_TYPE(name, spec) \
- typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
-BUILTIN_LIST_C(DEF_ARG_TYPE)
-#undef DEF_ARG_TYPE
-
-
// ----------------------------------------------------------------------------
// Support macro for defining builtins in C++.
// ----------------------------------------------------------------------------
@@ -141,29 +91,29 @@
// through the BuiltinArguments object args.
// TODO(cbruni): add global flag to check whether any tracing events have been
// enabled.
-#define BUILTIN(name) \
- MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
- Isolate* isolate); \
- \
- V8_NOINLINE static Object* Builtin_Impl_Stats_##name( \
- int args_length, Object** args_object, Isolate* isolate) { \
- name##ArgumentsType args(args_length, args_object); \
- RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Builtin_##name); \
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
- "V8.Builtin_" #name); \
- return Builtin_Impl_##name(args, isolate); \
- } \
- \
- MUST_USE_RESULT static Object* Builtin_##name( \
- int args_length, Object** args_object, Isolate* isolate) { \
- if (FLAG_runtime_call_stats) { \
- return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \
- } \
- name##ArgumentsType args(args_length, args_object); \
- return Builtin_Impl_##name(args, isolate); \
- } \
- \
- MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
+#define BUILTIN(name) \
+ MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args, \
+ Isolate* isolate); \
+ \
+ V8_NOINLINE static Object* Builtin_Impl_Stats_##name( \
+ int args_length, Object** args_object, Isolate* isolate) { \
+ BuiltinArguments args(args_length, args_object); \
+ RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Builtin_##name); \
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
+ "V8.Builtin_" #name); \
+ return Builtin_Impl_##name(args, isolate); \
+ } \
+ \
+ MUST_USE_RESULT static Object* Builtin_##name( \
+ int args_length, Object** args_object, Isolate* isolate) { \
+ if (FLAG_runtime_call_stats) { \
+ return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \
+ } \
+ BuiltinArguments args(args_length, args_object); \
+ return Builtin_Impl_##name(args, isolate); \
+ } \
+ \
+ MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args, \
Isolate* isolate)
// ----------------------------------------------------------------------------
@@ -178,8 +128,22 @@
} \
Handle<Type> name = Handle<Type>::cast(args.receiver())
+// Throws a TypeError for {method} if the receiver is not coercible to Object,
+// or converts the receiver to a String otherwise and assigns it to a new var
+// with the given {name}.
+#define TO_THIS_STRING(name, method) \
+ if (args.receiver()->IsNull(isolate) || \
+ args.receiver()->IsUndefined(isolate)) { \
+ THROW_NEW_ERROR_RETURN_FAILURE( \
+ isolate, \
+ NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, \
+ isolate->factory()->NewStringFromAsciiChecked(method))); \
+ } \
+ Handle<String> name; \
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
+ isolate, name, Object::ToString(isolate, args.receiver()))
-inline bool ClampedToInteger(Object* object, int* out) {
+inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) {
// This is an extended version of ECMA-262 7.1.11 handling signed values
// Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
if (object->IsSmi()) {
@@ -197,11 +161,11 @@
*out = static_cast<int>(value);
}
return true;
- } else if (object->IsUndefined() || object->IsNull()) {
+ } else if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
*out = 0;
return true;
} else if (object->IsBoolean()) {
- *out = object->IsTrue();
+ *out = object->IsTrue(isolate);
return true;
}
return false;
@@ -257,8 +221,7 @@
inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
DisallowHeapAllocation no_gc;
- PrototypeIterator iter(isolate, receiver,
- PrototypeIterator::START_AT_RECEIVER);
+ PrototypeIterator iter(isolate, receiver, kStartAtReceiver);
for (; !iter.IsAtEnd(); iter.Advance()) {
if (iter.GetCurrent()->IsJSProxy()) return false;
JSObject* current = iter.GetCurrent<JSObject>();
@@ -271,7 +234,7 @@
MUST_USE_RESULT
inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
Handle<Object> receiver,
- Arguments* args,
+ BuiltinArguments* args,
int first_added_arg) {
if (!receiver->IsJSArray()) return false;
Handle<JSArray> array = Handle<JSArray>::cast(receiver);
@@ -318,25 +281,18 @@
return true;
}
-
-MUST_USE_RESULT static Object* CallJsIntrinsic(
- Isolate* isolate, Handle<JSFunction> function,
- BuiltinArguments<BuiltinExtraArguments::kNone> args) {
+MUST_USE_RESULT static Object* CallJsIntrinsic(Isolate* isolate,
+ Handle<JSFunction> function,
+ BuiltinArguments args) {
HandleScope handleScope(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);
}
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- Execution::Call(isolate,
- function,
- args.receiver(),
- argc,
- argv.start()));
- return *result;
+ RETURN_RESULT_OR_FAILURE(
+ isolate,
+ Execution::Call(isolate, function, args.receiver(), argc, argv.start()));
}
@@ -412,7 +368,7 @@
&call_runtime);
assembler->Bind(&if_iskeyunique);
- assembler->TryLookupProperty(object, map, instance_type, key, &return_true,
+ assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
&return_false, &call_runtime);
assembler->Bind(&keyisindex);
@@ -432,8 +388,7 @@
namespace {
-Object* DoArrayPush(Isolate* isolate,
- BuiltinArguments<BuiltinExtraArguments::kNone> args) {
+Object* DoArrayPush(Isolate* isolate, BuiltinArguments args) {
HandleScope scope(isolate);
Handle<Object> receiver = args.receiver();
if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
@@ -467,8 +422,8 @@
DCHECK_EQ(2, args.length());
Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
// Rewrap the arguments as builtins arguments.
- BuiltinArguments<BuiltinExtraArguments::kNone> caller_args(
- incoming->length() + 1, incoming->arguments() + 1);
+ BuiltinArguments caller_args(incoming->length() + 3,
+ incoming->arguments() + 1);
return DoArrayPush(isolate, caller_args);
}
@@ -588,16 +543,16 @@
relative_end = len;
if (argument_count > 0) {
DisallowHeapAllocation no_gc;
- if (!ClampedToInteger(args[1], &relative_start)) {
+ if (!ClampedToInteger(isolate, args[1], &relative_start)) {
AllowHeapAllocation allow_allocation;
return CallJsIntrinsic(isolate, isolate->array_slice(), args);
}
if (argument_count > 1) {
Object* end_arg = args[2];
// slice handles the end_arg specially
- if (end_arg->IsUndefined()) {
+ if (end_arg->IsUndefined(isolate)) {
relative_end = len;
- } else if (!ClampedToInteger(end_arg, &relative_end)) {
+ } else if (!ClampedToInteger(isolate, end_arg, &relative_end)) {
AllowHeapAllocation allow_allocation;
return CallJsIntrinsic(isolate, isolate->array_slice(), args);
}
@@ -635,7 +590,7 @@
int relative_start = 0;
if (argument_count > 0) {
DisallowHeapAllocation no_gc;
- if (!ClampedToInteger(args[1], &relative_start)) {
+ if (!ClampedToInteger(isolate, args[1], &relative_start)) {
AllowHeapAllocation allow_allocation;
return CallJsIntrinsic(isolate, isolate->array_splice(), args);
}
@@ -657,7 +612,7 @@
int delete_count = 0;
DisallowHeapAllocation no_gc;
if (argument_count > 1) {
- if (!ClampedToInteger(args[2], &delete_count)) {
+ if (!ClampedToInteger(isolate, args[2], &delete_count)) {
AllowHeapAllocation allow_allocation;
return CallJsIntrinsic(isolate, isolate->array_splice(), args);
}
@@ -810,7 +765,7 @@
FOR_WITH_HANDLE_SCOPE(
isolate_, uint32_t, i = 0, i, i < current_length, i++, {
Handle<Object> element(current_storage->get(i), isolate_);
- if (!element->IsTheHole()) {
+ if (!element->IsTheHole(isolate_)) {
// The object holding this backing store has just been allocated, so
// it cannot yet be used as a prototype.
Handle<SeededNumberDictionary> new_storage =
@@ -856,6 +811,7 @@
uint32_t EstimateElementCount(Handle<JSArray> array) {
+ DisallowHeapAllocation no_gc;
uint32_t length = static_cast<uint32_t>(array->length()->Number());
int element_count = 0;
switch (array->GetElementsKind()) {
@@ -867,9 +823,10 @@
// a 32-bit signed integer.
DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
int fast_length = static_cast<int>(length);
- Handle<FixedArray> elements(FixedArray::cast(array->elements()));
+ Isolate* isolate = array->GetIsolate();
+ FixedArray* elements = FixedArray::cast(array->elements());
for (int i = 0; i < fast_length; i++) {
- if (!elements->get(i)->IsTheHole()) element_count++;
+ if (!elements->get(i)->IsTheHole(isolate)) element_count++;
}
break;
}
@@ -883,20 +840,20 @@
DCHECK(FixedArray::cast(array->elements())->length() == 0);
break;
}
- Handle<FixedDoubleArray> elements(
- FixedDoubleArray::cast(array->elements()));
+ FixedDoubleArray* elements = FixedDoubleArray::cast(array->elements());
for (int i = 0; i < fast_length; i++) {
if (!elements->is_the_hole(i)) element_count++;
}
break;
}
case DICTIONARY_ELEMENTS: {
- Handle<SeededNumberDictionary> dictionary(
- SeededNumberDictionary::cast(array->elements()));
+ SeededNumberDictionary* dictionary =
+ SeededNumberDictionary::cast(array->elements());
+ Isolate* isolate = dictionary->GetIsolate();
int capacity = dictionary->Capacity();
for (int i = 0; i < capacity; i++) {
- Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
- if (dictionary->IsKey(*key)) {
+ Object* key = dictionary->KeyAt(i);
+ if (dictionary->IsKey(isolate, key)) {
element_count++;
}
}
@@ -945,7 +902,7 @@
uint32_t length = static_cast<uint32_t>(elements->length());
if (range < length) length = range;
for (uint32_t i = 0; i < length; i++) {
- if (!elements->get(i)->IsTheHole()) {
+ if (!elements->get(i)->IsTheHole(isolate)) {
indices->Add(i);
}
}
@@ -973,13 +930,9 @@
SeededNumberDictionary* dict =
SeededNumberDictionary::cast(object->elements());
uint32_t capacity = dict->Capacity();
- Heap* heap = isolate->heap();
- Object* undefined = heap->undefined_value();
- Object* the_hole = heap->the_hole_value();
FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
Object* k = dict->KeyAt(j);
- if (k == undefined) continue;
- if (k == the_hole) continue;
+ if (!dict->IsKey(isolate, k)) continue;
DCHECK(k->IsNumber());
uint32_t index = static_cast<uint32_t>(k->Number());
if (index < range) {
@@ -1088,12 +1041,8 @@
length = static_cast<uint32_t>(array->length()->Number());
} else {
Handle<Object> val;
- Handle<Object> key = isolate->factory()->length_string();
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);
+ isolate, val, Object::GetLengthFromArrayLike(isolate, receiver), false);
// TODO(caitp): Support larger element indexes (up to 2^53-1).
if (!val->ToUint32(&length)) {
length = 0;
@@ -1119,7 +1068,7 @@
DCHECK(fast_length <= elements->length());
FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
Handle<Object> element_value(elements->get(j), isolate);
- if (!element_value->IsTheHole()) {
+ if (!element_value->IsTheHole(isolate)) {
if (!visitor->visit(j, element_value)) return false;
} else {
Maybe<bool> maybe = JSReceiver::HasElement(array, j);
@@ -1233,13 +1182,12 @@
MaybeHandle<Object> maybeValue =
i::Runtime::GetObjectProperty(isolate, obj, key);
if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
- if (!value->IsUndefined()) return Just(value->BooleanValue());
+ if (!value->IsUndefined(isolate)) return Just(value->BooleanValue());
}
return Object::IsArray(obj);
}
-
-Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
+Object* Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species,
Isolate* isolate) {
int argument_count = args->length();
@@ -1436,7 +1384,8 @@
return false;
}
-MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
+MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate,
+ BuiltinArguments* args) {
if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
return MaybeHandle<JSArray>();
}
@@ -1471,7 +1420,8 @@
result_len += Smi::cast(array->length())->value();
DCHECK(result_len >= 0);
// Throw an Error if we overflow the FixedArray limits
- if (FixedArray::kMaxLength < result_len) {
+ if (FixedDoubleArray::kMaxLength < result_len ||
+ FixedArray::kMaxLength < result_len) {
AllowHeapAllocation gc;
THROW_NEW_ERROR(isolate,
NewRangeError(MessageTemplate::kInvalidArrayLength),
@@ -1491,7 +1441,7 @@
Handle<Object> receiver = args.receiver();
// TODO(bmeurer): Do we really care about the exact exception message here?
- if (receiver->IsNull() || receiver->IsUndefined()) {
+ if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
isolate->factory()->NewStringFromAsciiChecked(
@@ -1636,8 +1586,9 @@
// 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
Handle<FixedArray> keys;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, keys,
- JSReceiver::GetKeys(from, OWN_ONLY, ALL_PROPERTIES, KEEP_NUMBERS));
+ isolate, keys, KeyAccumulator::GetKeys(
+ from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
+ GetKeysConversion::kKeepNumbers));
// 4c. Repeat for each element nextKey of keys in List order,
for (int j = 0; j < keys->length(); ++j) {
Handle<Object> next_key(keys->get(j), isolate);
@@ -1667,10 +1618,12 @@
// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
+// TODO(verwaest): Support the common cases with precached map directly in
+// an Object.create stub.
BUILTIN(ObjectCreate) {
HandleScope scope(isolate);
Handle<Object> prototype = args.atOrUndefined(isolate, 1);
- if (!prototype->IsNull() && !prototype->IsJSReceiver()) {
+ if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
}
@@ -1682,7 +1635,26 @@
Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
isolate);
if (map->prototype() != *prototype) {
- map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
+ if (prototype->IsNull(isolate)) {
+ map = isolate->object_with_null_prototype_map();
+ } else if (prototype->IsJSObject()) {
+ Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
+ if (!js_prototype->map()->is_prototype_map()) {
+ JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
+ }
+ Handle<PrototypeInfo> info =
+ Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
+ // TODO(verwaest): Use inobject slack tracking for this map.
+ if (info->HasObjectCreateMap()) {
+ map = handle(info->ObjectCreateMap(), isolate);
+ } else {
+ map = Map::CopyInitialMap(map);
+ Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
+ PrototypeInfo::SetObjectCreateMap(info, map);
+ }
+ } else {
+ map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
+ }
}
// Actually allocate the object.
@@ -1690,7 +1662,7 @@
// Define the properties if properties was specified and is not undefined.
Handle<Object> properties = args.atOrUndefined(isolate, 2);
- if (!properties->IsUndefined()) {
+ if (!properties->IsUndefined(isolate)) {
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSReceiver::DefineProperties(isolate, object, properties));
}
@@ -1705,11 +1677,8 @@
Handle<Object> target = args.at<Object>(1);
Handle<Object> properties = args.at<Object>(2);
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- JSReceiver::DefineProperties(isolate, target, properties));
- return *result;
+ RETURN_RESULT_OR_FAILURE(
+ isolate, JSReceiver::DefineProperties(isolate, target, properties));
}
// ES6 section 19.1.2.4 Object.defineProperty
@@ -1760,6 +1729,9 @@
Maybe<bool> success = JSReceiver::DefineOwnProperty(
isolate, receiver, name, &desc, Object::DONT_THROW);
MAYBE_RETURN(success, isolate->heap()->exception());
+ if (!success.FromJust()) {
+ isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
+ }
// 6. Return undefined.
return isolate->heap()->undefined_value();
}
@@ -1871,11 +1843,8 @@
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, receiver, Object::ToObject(isolate, object));
- Handle<Object> prototype;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, prototype, JSReceiver::GetPrototype(isolate, receiver));
-
- return *prototype;
+ RETURN_RESULT_OR_FAILURE(isolate,
+ JSReceiver::GetPrototype(isolate, receiver));
}
@@ -1905,8 +1874,7 @@
namespace {
-Object* GetOwnPropertyKeys(Isolate* isolate,
- BuiltinArguments<BuiltinExtraArguments::kNone> args,
+Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
PropertyFilter filter) {
HandleScope scope(isolate);
Handle<Object> object = args.atOrUndefined(isolate, 1);
@@ -1916,7 +1884,8 @@
Handle<FixedArray> keys;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, keys,
- JSReceiver::GetKeys(receiver, OWN_ONLY, filter, CONVERT_TO_STRING));
+ KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
+ GetKeysConversion::kConvertToString));
return *isolate->factory()->NewJSArrayWithElements(keys);
}
@@ -2012,8 +1981,9 @@
} else {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, keys,
- JSReceiver::GetKeys(receiver, OWN_ONLY, ENUMERABLE_STRINGS,
- CONVERT_TO_STRING));
+ KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
+ ENUMERABLE_STRINGS,
+ GetKeysConversion::kConvertToString));
}
return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
}
@@ -2055,8 +2025,9 @@
Handle<FixedArray> keys;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, keys, JSReceiver::GetKeys(receiver, OWN_ONLY, ALL_PROPERTIES,
- CONVERT_TO_STRING));
+ isolate, keys, KeyAccumulator::GetKeys(
+ receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
+ GetKeysConversion::kConvertToString));
Handle<JSObject> descriptors =
isolate->factory()->NewJSObject(isolate->object_function());
@@ -2107,6 +2078,29 @@
return *object;
}
+// ES6 section 18.2.6.2 decodeURI (encodedURI)
+BUILTIN(GlobalDecodeURI) {
+ HandleScope scope(isolate);
+ Handle<String> encoded_uri;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, encoded_uri,
+ Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+ RETURN_RESULT_OR_FAILURE(isolate, Uri::DecodeUri(isolate, encoded_uri));
+}
+
+// ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent)
+BUILTIN(GlobalDecodeURIComponent) {
+ HandleScope scope(isolate);
+ Handle<String> encoded_uri_component;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, encoded_uri_component,
+ Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+ RETURN_RESULT_OR_FAILURE(
+ isolate, Uri::DecodeUriComponent(isolate, encoded_uri_component));
+}
+
// ES6 section 18.2.6.4 encodeURI (uri)
BUILTIN(GlobalEncodeURI) {
HandleScope scope(isolate);
@@ -2114,25 +2108,48 @@
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
- return Uri::EncodeUri(isolate, uri);
+ RETURN_RESULT_OR_FAILURE(isolate, Uri::EncodeUri(isolate, uri));
}
// ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
BUILTIN(GlobalEncodeURIComponent) {
HandleScope scope(isolate);
- Handle<String> uriComponent;
+ Handle<String> uri_component;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, uriComponent,
+ isolate, uri_component,
Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
- return Uri::EncodeUriComponent(isolate, uriComponent);
+ RETURN_RESULT_OR_FAILURE(isolate,
+ Uri::EncodeUriComponent(isolate, uri_component));
+}
+
+// ES6 section B.2.1.1 escape (string)
+BUILTIN(GlobalEscape) {
+ HandleScope scope(isolate);
+ Handle<String> string;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, string,
+ Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+ RETURN_RESULT_OR_FAILURE(isolate, Uri::Escape(isolate, string));
+}
+
+// ES6 section B.2.1.2 unescape (string)
+BUILTIN(GlobalUnescape) {
+ HandleScope scope(isolate);
+ Handle<String> string;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, string,
+ Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
+
+ RETURN_RESULT_OR_FAILURE(isolate, Uri::Unescape(isolate, string));
}
namespace {
bool CodeGenerationFromStringsAllowed(Isolate* isolate,
Handle<Context> context) {
- DCHECK(context->allow_code_gen_from_strings()->IsFalse());
+ DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
// Check with callback if set.
AllowCodeGenerationFromStringsCallback callback =
isolate->allow_code_gen_callback();
@@ -2155,7 +2172,7 @@
// Check if native context allows code generation from
// strings. Throw an exception if it doesn't.
- if (native_context->allow_code_gen_from_strings()->IsFalse() &&
+ if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
!CodeGenerationFromStringsAllowed(isolate, native_context)) {
Handle<Object> error_message =
native_context->ErrorMessageForCodeGenerationFromStrings();
@@ -2188,13 +2205,36 @@
isolate, function,
CompileString(handle(target->native_context(), isolate),
Handle<String>::cast(x), NO_PARSE_RESTRICTION));
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
+ RETURN_RESULT_OR_FAILURE(
+ isolate,
Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
- return *result;
}
+// ES6 section 24.3.1 JSON.parse.
+BUILTIN(JsonParse) {
+ HandleScope scope(isolate);
+ Handle<Object> source = args.atOrUndefined(isolate, 1);
+ Handle<Object> reviver = args.atOrUndefined(isolate, 2);
+ Handle<String> string;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
+ Object::ToString(isolate, source));
+ string = String::Flatten(string);
+ RETURN_RESULT_OR_FAILURE(
+ isolate, string->IsSeqOneByteString()
+ ? JsonParser<true>::Parse(isolate, string, reviver)
+ : JsonParser<false>::Parse(isolate, string, reviver));
+}
+
+// ES6 section 24.3.2 JSON.stringify.
+BUILTIN(JsonStringify) {
+ HandleScope scope(isolate);
+ JsonStringifier stringifier(isolate);
+ Handle<Object> object = args.atOrUndefined(isolate, 1);
+ Handle<Object> replacer = args.atOrUndefined(isolate, 2);
+ Handle<Object> indent = args.atOrUndefined(isolate, 3);
+ RETURN_RESULT_OR_FAILURE(isolate,
+ stringifier.Stringify(object, replacer, indent));
+}
// -----------------------------------------------------------------------------
// ES6 section 20.2.2 Function Properties of the Math Object
@@ -2219,14 +2259,42 @@
return *isolate->factory()->NewHeapNumber(std::asin(x->Number()));
}
-
// ES6 section 20.2.2.6 Math.atan ( x )
-BUILTIN(MathAtan) {
- HandleScope scope(isolate);
- DCHECK_EQ(2, args.length());
- Handle<Object> x = args.at<Object>(1);
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
- return *isolate->factory()->NewHeapNumber(std::atan(x->Number()));
+void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Atan(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
+// ES6 section 20.2.2.8 Math.atan2 ( y, x )
+void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* y = assembler->Parameter(1);
+ Node* x = assembler->Parameter(2);
+ Node* context = assembler->Parameter(5);
+ Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Atan2(y_value, x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
+// ES6 section 20.2.2.7 Math.atanh ( x )
+void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Atanh(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
}
namespace {
@@ -2297,6 +2365,18 @@
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
}
+// ES6 section 20.2.2.9 Math.cbrt ( x )
+void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Cbrt(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
// ES6 section 20.2.2.11 Math.clz32 ( x )
void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label;
@@ -2365,6 +2445,30 @@
}
}
+// ES6 section 20.2.2.12 Math.cos ( x )
+void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Cos(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
+// ES6 section 20.2.2.14 Math.exp ( x )
+void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Exp(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
// ES6 section 20.2.2.16 Math.floor ( x )
void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
@@ -2392,11 +2496,83 @@
return *isolate->factory()->NewNumberFromInt(product);
}
+// ES6 section 20.2.2.20 Math.log ( x )
+void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Log(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
+// ES6 section 20.2.2.21 Math.log1p ( x )
+void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Log1p(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
+// ES6 section 20.2.2.23 Math.log2 ( x )
+void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Log2(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
+// ES6 section 20.2.2.22 Math.log10 ( x )
+void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Log10(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
+// ES6 section 20.2.2.15 Math.expm1 ( x )
+void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Expm1(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
// ES6 section 20.2.2.28 Math.round ( x )
void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
}
+// ES6 section 20.2.2.30 Math.sin ( x )
+void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Sin(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
// ES6 section 20.2.2.32 Math.sqrt ( x )
void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
using compiler::Node;
@@ -2409,6 +2585,18 @@
assembler->Return(result);
}
+// ES6 section 20.2.2.33 Math.tan ( x )
+void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
+ using compiler::Node;
+
+ Node* x = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+ Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
+ Node* value = assembler->Float64Tan(x_value);
+ Node* result = assembler->ChangeFloat64ToTagged(value);
+ assembler->Return(result);
+}
+
// ES6 section 20.2.2.35 Math.trunc ( x )
void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
@@ -2612,12 +2800,9 @@
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
Object::ToName(isolate, key));
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Object::GetPropertyOrElement(
- receiver, name, Handle<JSReceiver>::cast(target)));
-
- return *result;
+ RETURN_RESULT_OR_FAILURE(
+ isolate, Object::GetPropertyOrElement(receiver, name,
+ Handle<JSReceiver>::cast(target)));
}
@@ -2660,11 +2845,9 @@
isolate->factory()->NewStringFromAsciiChecked(
"Reflect.getPrototypeOf")));
}
- Handle<Object> prototype;
Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, prototype, JSReceiver::GetPrototype(isolate, receiver));
- return *prototype;
+ RETURN_RESULT_OR_FAILURE(isolate,
+ JSReceiver::GetPrototype(isolate, receiver));
}
@@ -2729,8 +2912,9 @@
Handle<FixedArray> keys;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, keys,
- JSReceiver::GetKeys(Handle<JSReceiver>::cast(target), OWN_ONLY,
- ALL_PROPERTIES, CONVERT_TO_STRING));
+ KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target),
+ KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
+ GetKeysConversion::kConvertToString));
return *isolate->factory()->NewJSArrayWithElements(keys);
}
@@ -2797,7 +2981,7 @@
"Reflect.setPrototypeOf")));
}
- if (!proto->IsJSReceiver() && !proto->IsNull()) {
+ if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
}
@@ -2905,7 +3089,7 @@
// 4. Let numberOffset be ? ToNumber(byteOffset).
Handle<Object> number_offset;
- if (byte_offset->IsUndefined()) {
+ if (byte_offset->IsUndefined(isolate)) {
// We intentionally violate the specification at this point to allow
// for new DataView(buffer) invocations to be equivalent to the full
// new DataView(buffer, 0) invocation.
@@ -2940,7 +3124,7 @@
}
Handle<Object> view_byte_length;
- if (byte_length->IsUndefined()) {
+ if (byte_length->IsUndefined(isolate)) {
// 10. If byteLength is undefined, then
// a. Let viewByteLength be bufferByteLength - offset.
view_byte_length =
@@ -2982,6 +3166,119 @@
return *result;
}
+// ES6 section 24.2.4.1 get DataView.prototype.buffer
+BUILTIN(DataViewPrototypeGetBuffer) {
+ HandleScope scope(isolate);
+ CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.buffer");
+ return data_view->buffer();
+}
+
+// ES6 section 24.2.4.2 get DataView.prototype.byteLength
+BUILTIN(DataViewPrototypeGetByteLength) {
+ HandleScope scope(isolate);
+ CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteLength");
+ // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
+ // here if the JSArrayBuffer of the {data_view} was neutered.
+ return data_view->byte_length();
+}
+
+// ES6 section 24.2.4.3 get DataView.prototype.byteOffset
+BUILTIN(DataViewPrototypeGetByteOffset) {
+ HandleScope scope(isolate);
+ CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteOffset");
+ // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
+ // here if the JSArrayBuffer of the {data_view} was neutered.
+ return data_view->byte_offset();
+}
+
+// -----------------------------------------------------------------------------
+// ES6 section 22.2 TypedArray Objects
+
+// ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
+BUILTIN(TypedArrayPrototypeBuffer) {
+ HandleScope scope(isolate);
+ CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer");
+ return *typed_array->GetBuffer();
+}
+
+namespace {
+
+void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
+ const char* method_name,
+ int object_offset) {
+ typedef CodeStubAssembler::Label Label;
+ typedef compiler::Node Node;
+
+ Node* receiver = assembler->Parameter(0);
+ Node* context = assembler->Parameter(3);
+
+ // Check if the {receiver} is actually a JSTypedArray.
+ Label if_receiverisincompatible(assembler, Label::kDeferred);
+ assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
+ Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
+ assembler->GotoUnless(
+ assembler->Word32Equal(receiver_instance_type,
+ assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
+ &if_receiverisincompatible);
+
+ // Check if the {receiver}'s JSArrayBuffer was neutered.
+ Node* receiver_buffer =
+ assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
+ Node* receiver_buffer_bit_field = assembler->LoadObjectField(
+ receiver_buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
+ Label if_receiverisneutered(assembler, Label::kDeferred);
+ assembler->GotoUnless(
+ assembler->Word32Equal(
+ assembler->Word32And(
+ receiver_buffer_bit_field,
+ assembler->Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
+ assembler->Int32Constant(0)),
+ &if_receiverisneutered);
+ assembler->Return(assembler->LoadObjectField(receiver, object_offset));
+
+ assembler->Bind(&if_receiverisneutered);
+ {
+ // The {receiver}s buffer was neutered, default to zero.
+ assembler->Return(assembler->SmiConstant(0));
+ }
+
+ assembler->Bind(&if_receiverisincompatible);
+ {
+ // The {receiver} is not a valid JSGeneratorObject.
+ Node* result = assembler->CallRuntime(
+ Runtime::kThrowIncompatibleMethodReceiver, context,
+ assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
+ method_name, TENURED)),
+ receiver);
+ assembler->Return(result); // Never reached.
+ }
+}
+
+} // namespace
+
+// ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
+void Builtins::Generate_TypedArrayPrototypeByteLength(
+ CodeStubAssembler* assembler) {
+ Generate_TypedArrayProtoypeGetter(assembler,
+ "get TypedArray.prototype.byteLength",
+ JSTypedArray::kByteLengthOffset);
+}
+
+// ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
+void Builtins::Generate_TypedArrayPrototypeByteOffset(
+ CodeStubAssembler* assembler) {
+ Generate_TypedArrayProtoypeGetter(assembler,
+ "get TypedArray.prototype.byteOffset",
+ JSTypedArray::kByteOffsetOffset);
+}
+
+// ES6 section 22.2.3.18 get %TypedArray%.prototype.length
+void Builtins::Generate_TypedArrayPrototypeLength(
+ CodeStubAssembler* assembler) {
+ Generate_TypedArrayProtoypeGetter(assembler,
+ "get TypedArray.prototype.length",
+ JSTypedArray::kLengthOffset);
+}
// -----------------------------------------------------------------------------
// ES6 section 20.3 Date Objects
@@ -3100,11 +3397,9 @@
String::FlatContent str_content = str->GetFlatContent();
bool result;
if (str_content.IsOneByte()) {
- result = DateParser::Parse(str_content.ToOneByteVector(), *tmp,
- isolate->unicode_cache());
+ result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp);
} else {
- result = DateParser::Parse(str_content.ToUC16Vector(), *tmp,
- isolate->unicode_cache());
+ result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp);
}
if (!result) return std::numeric_limits<double>::quiet_NaN();
double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
@@ -3112,7 +3407,7 @@
double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
tmp->get(5)->Number(), tmp->get(6)->Number());
double date = MakeDate(day, time);
- if (tmp->get(7)->IsNull()) {
+ if (tmp->get(7)->IsNull(isolate)) {
if (!std::isnan(date)) {
date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
}
@@ -3183,11 +3478,8 @@
double const time_val = JSDate::CurrentTimeValue(isolate);
char buffer[128];
ToDateString(time_val, ArrayVector(buffer), isolate->date_cache());
- Handle<String> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
- return *result;
+ RETURN_RESULT_OR_FAILURE(
+ isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
}
@@ -3269,10 +3561,7 @@
time_val = std::numeric_limits<double>::quiet_NaN();
}
}
- Handle<JSDate> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
- JSDate::New(target, new_target, time_val));
- return *result;
+ RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val));
}
@@ -3767,11 +4056,8 @@
char buffer[128];
ToDateString(date->value()->Number(), ArrayVector(buffer),
isolate->date_cache(), kDateOnly);
- Handle<String> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
- return *result;
+ RETURN_RESULT_OR_FAILURE(
+ isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
}
@@ -3810,11 +4096,8 @@
char buffer[128];
ToDateString(date->value()->Number(), ArrayVector(buffer),
isolate->date_cache());
- Handle<String> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
- return *result;
+ RETURN_RESULT_OR_FAILURE(
+ isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
}
@@ -3825,11 +4108,8 @@
char buffer[128];
ToDateString(date->value()->Number(), ArrayVector(buffer),
isolate->date_cache(), kTimeOnly);
- Handle<String> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
- return *result;
+ RETURN_RESULT_OR_FAILURE(
+ isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
}
@@ -3867,10 +4147,7 @@
DCHECK_EQ(2, args.length());
CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
Handle<Object> hint = args.at<Object>(1);
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
- JSDate::ToPrimitive(receiver, hint));
- return *result;
+ RETURN_RESULT_OR_FAILURE(isolate, JSDate::ToPrimitive(receiver, hint));
}
@@ -3914,6 +4191,33 @@
return SetLocalDateValue(date, time_val);
}
+// ES6 section 20.3.4.37 Date.prototype.toJSON ( key )
+BUILTIN(DatePrototypeToJson) {
+ HandleScope scope(isolate);
+ Handle<Object> receiver = args.atOrUndefined(isolate, 0);
+ Handle<JSReceiver> receiver_obj;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj,
+ Object::ToObject(isolate, receiver));
+ Handle<Object> primitive;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, primitive,
+ Object::ToPrimitive(receiver_obj, ToPrimitiveHint::kNumber));
+ if (primitive->IsNumber() && !std::isfinite(primitive->Number())) {
+ return isolate->heap()->null_value();
+ } else {
+ Handle<String> name =
+ isolate->factory()->NewStringFromAsciiChecked("toISOString");
+ Handle<Object> function;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function,
+ Object::GetProperty(receiver_obj, name));
+ if (!function->IsCallable()) {
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name));
+ }
+ RETURN_RESULT_OR_FAILURE(
+ isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL));
+ }
+}
// static
void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
@@ -4026,10 +4330,9 @@
namespace {
// ES6 section 19.2.1.1.1 CreateDynamicFunction
-MaybeHandle<JSFunction> CreateDynamicFunction(
- Isolate* isolate,
- BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,
- const char* token) {
+MaybeHandle<JSFunction> CreateDynamicFunction(Isolate* isolate,
+ BuiltinArguments args,
+ const char* token) {
// Compute number of arguments, ignoring the receiver.
DCHECK_LE(1, args.length());
int const argc = args.length() - 1;
@@ -4115,7 +4418,7 @@
// function has wrong initial map. To fix that we create a new
// function object with correct initial map.
Handle<Object> unchecked_new_target = args.new_target();
- if (!unchecked_new_target->IsUndefined() &&
+ if (!unchecked_new_target->IsUndefined(isolate) &&
!unchecked_new_target.is_identical_to(target)) {
Handle<JSReceiver> new_target =
Handle<JSReceiver>::cast(unchecked_new_target);
@@ -4147,9 +4450,9 @@
return *result;
}
+namespace {
-// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
-BUILTIN(FunctionPrototypeBind) {
+Object* DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
HandleScope scope(isolate);
DCHECK_LE(1, args.length());
if (!args.receiver()->IsCallable()) {
@@ -4233,6 +4536,22 @@
return *function;
}
+} // namespace
+
+// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
+BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
+
+// TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
+// can tailcall to the builtin directly.
+RUNTIME_FUNCTION(Runtime_FunctionBind) {
+ DCHECK_EQ(2, args.length());
+ Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
+ // Rewrap the arguments as builtins arguments.
+ BuiltinArguments caller_args(incoming->length() + 3,
+ incoming->arguments() + 1);
+ return DoFunctionBind(isolate, caller_args);
+}
+
// ES6 section 19.2.3.5 Function.prototype.toString ( )
BUILTIN(FunctionPrototypeToString) {
HandleScope scope(isolate);
@@ -4252,18 +4571,23 @@
// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
BUILTIN(GeneratorFunctionConstructor) {
HandleScope scope(isolate);
- Handle<JSFunction> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, CreateDynamicFunction(isolate, args, "function*"));
- return *result;
+ RETURN_RESULT_OR_FAILURE(isolate,
+ CreateDynamicFunction(isolate, args, "function*"));
}
BUILTIN(AsyncFunctionConstructor) {
HandleScope scope(isolate);
- Handle<JSFunction> result;
+ Handle<JSFunction> func;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, CreateDynamicFunction(isolate, args, "async function"));
- return *result;
+ isolate, func, CreateDynamicFunction(isolate, args, "async function"));
+
+ // Do not lazily compute eval position for AsyncFunction, as they may not be
+ // determined after the function is resumed.
+ Handle<Script> script = handle(Script::cast(func->shared()->script()));
+ int position = script->GetEvalPosition();
+ USE(position);
+
+ return *func;
}
// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
@@ -4271,7 +4595,7 @@
HandleScope scope(isolate);
Handle<Symbol> result = isolate->factory()->NewSymbol();
Handle<Object> description = args.atOrUndefined(isolate, 1);
- if (!description->IsUndefined()) {
+ if (!description->IsUndefined(isolate)) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
Object::ToString(isolate, description));
result->set_name(*description);
@@ -4293,75 +4617,290 @@
BUILTIN(ObjectProtoToString) {
HandleScope scope(isolate);
Handle<Object> object = args.at<Object>(0);
- Handle<String> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, Object::ObjectProtoToString(isolate, object));
- return *result;
+ RETURN_RESULT_OR_FAILURE(isolate,
+ Object::ObjectProtoToString(isolate, object));
}
// -----------------------------------------------------------------------------
// ES6 section 21.1 String Objects
-namespace {
+// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
+void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
+ typedef CodeStubAssembler::Label Label;
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Variable Variable;
-bool ToUint16(Handle<Object> value, uint16_t* result) {
- if (value->IsNumber() || Object::ToNumber(value).ToHandle(&value)) {
- *result = DoubleToUint32(value->Number());
- return true;
+ Node* code = assembler->Parameter(1);
+ Node* context = assembler->Parameter(4);
+
+ // Check if we have exactly one argument (plus the implicit receiver), i.e.
+ // if the parent frame is not an arguments adaptor frame.
+ Label if_oneargument(assembler), if_notoneargument(assembler);
+ Node* parent_frame_pointer = assembler->LoadParentFramePointer();
+ Node* parent_frame_type =
+ assembler->Load(MachineType::Pointer(), parent_frame_pointer,
+ assembler->IntPtrConstant(
+ CommonFrameConstants::kContextOrFrameTypeOffset));
+ assembler->Branch(
+ assembler->WordEqual(
+ parent_frame_type,
+ assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
+ &if_notoneargument, &if_oneargument);
+
+ assembler->Bind(&if_oneargument);
+ {
+ // Single argument case, perform fast single character string cache lookup
+ // for one-byte code units, or fall back to creating a single character
+ // string on the fly otherwise.
+ Node* code32 = assembler->TruncateTaggedToWord32(context, code);
+ Node* code16 = assembler->Word32And(
+ code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
+ Node* result = assembler->StringFromCharCode(code16);
+ assembler->Return(result);
}
- return false;
+
+ assembler->Bind(&if_notoneargument);
+ {
+ // Determine the resulting string length.
+ Node* parent_frame_length =
+ assembler->Load(MachineType::Pointer(), parent_frame_pointer,
+ assembler->IntPtrConstant(
+ ArgumentsAdaptorFrameConstants::kLengthOffset));
+ Node* length = assembler->SmiToWord(parent_frame_length);
+
+ // Assume that the resulting string contains only one-byte characters.
+ Node* result = assembler->AllocateSeqOneByteString(context, length);
+
+ // Truncate all input parameters and append them to the resulting string.
+ Variable var_offset(assembler, MachineType::PointerRepresentation());
+ Label loop(assembler, &var_offset), done_loop(assembler);
+ var_offset.Bind(assembler->IntPtrConstant(0));
+ assembler->Goto(&loop);
+ assembler->Bind(&loop);
+ {
+ // Load the current {offset}.
+ Node* offset = var_offset.value();
+
+ // Check if we're done with the string.
+ assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop);
+
+ // Load the next code point and truncate it to a 16-bit value.
+ Node* code = assembler->Load(
+ MachineType::AnyTagged(), parent_frame_pointer,
+ assembler->IntPtrAdd(
+ assembler->WordShl(assembler->IntPtrSub(length, offset),
+ assembler->IntPtrConstant(kPointerSizeLog2)),
+ assembler->IntPtrConstant(
+ CommonFrameConstants::kFixedFrameSizeAboveFp -
+ kPointerSize)));
+ Node* code32 = assembler->TruncateTaggedToWord32(context, code);
+ Node* code16 = assembler->Word32And(
+ code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
+
+ // Check if {code16} fits into a one-byte string.
+ Label if_codeisonebyte(assembler), if_codeistwobyte(assembler);
+ assembler->Branch(
+ assembler->Int32LessThanOrEqual(
+ code16, assembler->Int32Constant(String::kMaxOneByteCharCode)),
+ &if_codeisonebyte, &if_codeistwobyte);
+
+ assembler->Bind(&if_codeisonebyte);
+ {
+ // The {code16} fits into the SeqOneByteString {result}.
+ assembler->StoreNoWriteBarrier(
+ MachineRepresentation::kWord8, result,
+ assembler->IntPtrAdd(
+ assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
+ kHeapObjectTag),
+ offset),
+ code16);
+ var_offset.Bind(
+ assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
+ assembler->Goto(&loop);
+ }
+
+ assembler->Bind(&if_codeistwobyte);
+ {
+ // Allocate a SeqTwoByteString to hold the resulting string.
+ Node* cresult = assembler->AllocateSeqTwoByteString(context, length);
+
+ // Copy all characters that were previously written to the
+ // SeqOneByteString in {result} over to the new {cresult}.
+ Variable var_coffset(assembler, MachineType::PointerRepresentation());
+ Label cloop(assembler, &var_coffset), done_cloop(assembler);
+ var_coffset.Bind(assembler->IntPtrConstant(0));
+ assembler->Goto(&cloop);
+ assembler->Bind(&cloop);
+ {
+ Node* coffset = var_coffset.value();
+ assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop);
+ Node* ccode = assembler->Load(
+ MachineType::Uint8(), result,
+ assembler->IntPtrAdd(
+ assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
+ kHeapObjectTag),
+ coffset));
+ assembler->StoreNoWriteBarrier(
+ MachineRepresentation::kWord16, cresult,
+ assembler->IntPtrAdd(
+ assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+ kHeapObjectTag),
+ assembler->WordShl(coffset, 1)),
+ ccode);
+ var_coffset.Bind(
+ assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1)));
+ assembler->Goto(&cloop);
+ }
+
+ // Write the pending {code16} to {offset}.
+ assembler->Bind(&done_cloop);
+ assembler->StoreNoWriteBarrier(
+ MachineRepresentation::kWord16, cresult,
+ assembler->IntPtrAdd(
+ assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+ kHeapObjectTag),
+ assembler->WordShl(offset, 1)),
+ code16);
+
+ // Copy the remaining parameters to the SeqTwoByteString {cresult}.
+ Label floop(assembler, &var_offset), done_floop(assembler);
+ assembler->Goto(&floop);
+ assembler->Bind(&floop);
+ {
+ // Compute the next {offset}.
+ Node* offset = assembler->IntPtrAdd(var_offset.value(),
+ assembler->IntPtrConstant(1));
+
+ // Check if we're done with the string.
+ assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop);
+
+ // Load the next code point and truncate it to a 16-bit value.
+ Node* code = assembler->Load(
+ MachineType::AnyTagged(), parent_frame_pointer,
+ assembler->IntPtrAdd(
+ assembler->WordShl(
+ assembler->IntPtrSub(length, offset),
+ assembler->IntPtrConstant(kPointerSizeLog2)),
+ assembler->IntPtrConstant(
+ CommonFrameConstants::kFixedFrameSizeAboveFp -
+ kPointerSize)));
+ Node* code32 = assembler->TruncateTaggedToWord32(context, code);
+ Node* code16 = assembler->Word32And(
+ code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
+
+ // Store the truncated {code} point at the next offset.
+ assembler->StoreNoWriteBarrier(
+ MachineRepresentation::kWord16, cresult,
+ assembler->IntPtrAdd(
+ assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
+ kHeapObjectTag),
+ assembler->WordShl(offset, 1)),
+ code16);
+ var_offset.Bind(offset);
+ assembler->Goto(&floop);
+ }
+
+ // Return the SeqTwoByteString.
+ assembler->Bind(&done_floop);
+ assembler->Return(cresult);
+ }
+ }
+
+ assembler->Bind(&done_loop);
+ assembler->Return(result);
+ }
+}
+
+namespace { // for String.fromCodePoint
+
+bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
+ if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) {
+ return false;
+ }
+
+ if (Object::ToInteger(isolate, value).ToHandleChecked()->Number() !=
+ value->Number()) {
+ return false;
+ }
+
+ if (value->Number() < 0 || value->Number() > 0x10FFFF) {
+ return false;
+ }
+
+ return true;
+}
+
+uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
+ Handle<Object> value = args.at<Object>(1 + index);
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::ToNumber(value), -1);
+ if (!IsValidCodePoint(isolate, value)) {
+ isolate->Throw(*isolate->factory()->NewRangeError(
+ MessageTemplate::kInvalidCodePoint, value));
+ return -1;
+ }
+ return DoubleToUint32(value->Number());
}
} // namespace
-// ES6 21.1.2.1 String.fromCharCode ( ...codeUnits )
-BUILTIN(StringFromCharCode) {
+// ES6 section 21.1.2.2 String.fromCodePoint ( ...codePoints )
+BUILTIN(StringFromCodePoint) {
HandleScope scope(isolate);
- // Check resulting string length.
- int index = 0;
- Handle<String> result;
int const length = args.length() - 1;
if (length == 0) return isolate->heap()->empty_string();
DCHECK_LT(0, length);
- // Load the first character code.
- uint16_t code;
- if (!ToUint16(args.at<Object>(1), &code)) return isolate->heap()->exception();
- // Assume that the resulting String contains only one byte characters.
- if (code <= String::kMaxOneByteCharCodeU) {
- // Check for single one-byte character fast case.
- if (length == 1) {
- return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
+
+ // Optimistically assume that the resulting String contains only one byte
+ // characters.
+ List<uint8_t> one_byte_buffer(length);
+ uc32 code = 0;
+ int index;
+ for (index = 0; index < length; index++) {
+ code = NextCodePoint(isolate, args, index);
+ if (code < 0) {
+ return isolate->heap()->exception();
}
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, isolate->factory()->NewRawOneByteString(length));
- do {
- Handle<SeqOneByteString>::cast(result)->Set(index, code);
- if (++index == length) break;
- if (!ToUint16(args.at<Object>(1 + index), &code)) {
- return isolate->heap()->exception();
- }
- } while (code <= String::kMaxOneByteCharCodeU);
+ if (code > String::kMaxOneByteCharCode) {
+ break;
+ }
+ one_byte_buffer.Add(code);
}
- // Check if all characters fit into the one byte range.
- if (index < length) {
- // Fallback to two byte string.
- Handle<String> new_result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, new_result, isolate->factory()->NewRawTwoByteString(length));
- for (int new_index = 0; new_index < index; ++new_index) {
- uint16_t new_code =
- Handle<SeqOneByteString>::cast(result)->Get(new_index);
- Handle<SeqTwoByteString>::cast(new_result)->Set(new_index, new_code);
- }
- while (true) {
- Handle<SeqTwoByteString>::cast(new_result)->Set(index, code);
- if (++index == length) break;
- if (!ToUint16(args.at<Object>(1 + index), &code)) {
- return isolate->heap()->exception();
- }
- }
- result = new_result;
+
+ if (index == length) {
+ RETURN_RESULT_OR_FAILURE(isolate, isolate->factory()->NewStringFromOneByte(
+ one_byte_buffer.ToConstVector()));
}
+
+ List<uc16> two_byte_buffer(length - index);
+
+ while (true) {
+ if (code <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
+ two_byte_buffer.Add(code);
+ } else {
+ two_byte_buffer.Add(unibrow::Utf16::LeadSurrogate(code));
+ two_byte_buffer.Add(unibrow::Utf16::TrailSurrogate(code));
+ }
+
+ if (++index == length) {
+ break;
+ }
+ code = NextCodePoint(isolate, args, index);
+ if (code < 0) {
+ return isolate->heap()->exception();
+ }
+ }
+
+ Handle<SeqTwoByteString> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ isolate->factory()->NewRawTwoByteString(one_byte_buffer.length() +
+ two_byte_buffer.length()));
+
+ CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(),
+ one_byte_buffer.length());
+ CopyChars(result->GetChars() + one_byte_buffer.length(),
+ two_byte_buffer.ToConstVector().start(), two_byte_buffer.length());
+
return *result;
}
@@ -4552,6 +5091,27 @@
assembler->Return(result);
}
+// ES6 section 21.1.3.25 String.prototype.trim ()
+BUILTIN(StringPrototypeTrim) {
+ HandleScope scope(isolate);
+ TO_THIS_STRING(string, "String.prototype.trim");
+ return *String::Trim(string, String::kTrim);
+}
+
+// Non-standard WebKit extension
+BUILTIN(StringPrototypeTrimLeft) {
+ HandleScope scope(isolate);
+ TO_THIS_STRING(string, "String.prototype.trimLeft");
+ return *String::Trim(string, String::kTrimLeft);
+}
+
+// Non-standard WebKit extension
+BUILTIN(StringPrototypeTrimRight) {
+ HandleScope scope(isolate);
+ TO_THIS_STRING(string, "String.prototype.trimRight");
+ return *String::Trim(string, String::kTrimRight);
+}
+
// -----------------------------------------------------------------------------
// ES6 section 21.1 ArrayBuffer Objects
@@ -4629,10 +5189,7 @@
DCHECK(isolate->proxy_function()->IsConstructor());
Handle<Object> target = args.atOrUndefined(isolate, 1);
Handle<Object> handler = args.atOrUndefined(isolate, 2);
- Handle<JSProxy> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
- JSProxy::New(isolate, target, handler));
- return *result;
+ RETURN_RESULT_OR_FAILURE(isolate, JSProxy::New(isolate, target, handler));
}
@@ -4661,25 +5218,38 @@
namespace {
+// Returns the holder JSObject if the function can legally be called with this
+// receiver. Returns nullptr if the call is illegal.
+// TODO(dcarney): CallOptimization duplicates this logic, merge.
+JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
+ JSObject* receiver) {
+ Object* recv_type = info->signature();
+ // No signature, return holder.
+ if (!recv_type->IsFunctionTemplateInfo()) return receiver;
+ FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
+
+ // Check the receiver. Fast path for receivers with no hidden prototypes.
+ if (signature->IsTemplateFor(receiver)) return receiver;
+ if (!receiver->map()->has_hidden_prototype()) return nullptr;
+ for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype,
+ PrototypeIterator::END_AT_NON_HIDDEN);
+ !iter.IsAtEnd(); iter.Advance()) {
+ JSObject* current = iter.GetCurrent<JSObject>();
+ if (signature->IsTemplateFor(current)) return current;
+ }
+ return nullptr;
+}
+
+template <bool is_construct>
MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
- Isolate* isolate,
- BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args) {
- HandleScope scope(isolate);
- Handle<HeapObject> function = args.target<HeapObject>();
- Handle<HeapObject> new_target = args.new_target();
- bool is_construct = !new_target->IsUndefined();
- Handle<JSReceiver> receiver;
-
- DCHECK(function->IsFunctionTemplateInfo() ||
- Handle<JSFunction>::cast(function)->shared()->IsApiFunction());
-
- Handle<FunctionTemplateInfo> fun_data =
- function->IsFunctionTemplateInfo()
- ? Handle<FunctionTemplateInfo>::cast(function)
- : handle(JSFunction::cast(*function)->shared()->get_api_func_data());
+ Isolate* isolate, Handle<HeapObject> function,
+ Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
+ Handle<Object> receiver, BuiltinArguments args) {
+ Handle<JSObject> js_receiver;
+ JSObject* raw_holder;
if (is_construct) {
- DCHECK(args.receiver()->IsTheHole());
- if (fun_data->instance_template()->IsUndefined()) {
+ DCHECK(args.receiver()->IsTheHole(isolate));
+ if (fun_data->instance_template()->IsUndefined(isolate)) {
v8::Local<ObjectTemplate> templ =
ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
ToApiHandle<v8::FunctionTemplate>(fun_data));
@@ -4688,37 +5258,43 @@
Handle<ObjectTemplateInfo> instance_template(
ObjectTemplateInfo::cast(fun_data->instance_template()), isolate);
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, receiver,
+ isolate, js_receiver,
ApiNatives::InstantiateObject(instance_template,
Handle<JSReceiver>::cast(new_target)),
Object);
- args[0] = *receiver;
- DCHECK_EQ(*receiver, *args.receiver());
- } else {
- DCHECK(args.receiver()->IsJSReceiver());
- receiver = args.at<JSReceiver>(0);
- }
+ args[0] = *js_receiver;
+ DCHECK_EQ(*js_receiver, *args.receiver());
- if (!is_construct && !fun_data->accept_any_receiver()) {
- if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
- Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
- if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
- isolate->ReportFailedAccessCheck(js_receiver);
- RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
- }
+ raw_holder = *js_receiver;
+ } else {
+ DCHECK(receiver->IsJSReceiver());
+
+ if (!receiver->IsJSObject()) {
+ // This function cannot be called with the given receiver. Abort!
+ THROW_NEW_ERROR(
+ isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
+ }
+
+ js_receiver = Handle<JSObject>::cast(receiver);
+
+ if (!fun_data->accept_any_receiver() &&
+ js_receiver->IsAccessCheckNeeded() &&
+ !isolate->MayAccess(handle(isolate->context()), js_receiver)) {
+ isolate->ReportFailedAccessCheck(js_receiver);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ }
+
+ raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver);
+
+ if (raw_holder == nullptr) {
+ // This function cannot be called with the given receiver. Abort!
+ THROW_NEW_ERROR(
+ isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
}
}
- Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, *receiver);
-
- if (raw_holder->IsNull()) {
- // This function cannot be called with the given receiver. Abort!
- THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
- Object);
- }
-
Object* raw_call_data = fun_data->call_code();
- if (!raw_call_data->IsUndefined()) {
+ if (!raw_call_data->IsUndefined(isolate)) {
DCHECK(raw_call_data->IsCallHandlerInfo());
CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
Object* callback_obj = call_data->callback();
@@ -4726,23 +5302,25 @@
v8::ToCData<v8::FunctionCallback>(callback_obj);
Object* data_obj = call_data->data();
- LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
- DCHECK(raw_holder->IsJSObject());
+ LOG(isolate, ApiObjectAccess("call", JSObject::cast(*js_receiver)));
FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder,
*new_target, &args[0] - 1,
args.length() - 1);
Handle<Object> result = custom.Call(callback);
- if (result.is_null()) result = isolate->factory()->undefined_value();
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
- if (!is_construct || result->IsJSObject()) {
- return scope.CloseAndEscape(result);
+ if (result.is_null()) {
+ if (is_construct) return js_receiver;
+ return isolate->factory()->undefined_value();
}
+ // Rebox the result.
+ result->VerifyApiCallResultType();
+ if (!is_construct || result->IsJSObject()) return handle(*result, isolate);
}
- return scope.CloseAndEscape(receiver);
+ return js_receiver;
}
} // namespace
@@ -4750,10 +5328,20 @@
BUILTIN(HandleApiCall) {
HandleScope scope(isolate);
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
- HandleApiCallHelper(isolate, args));
- return *result;
+ Handle<JSFunction> function = args.target<JSFunction>();
+ Handle<Object> receiver = args.receiver();
+ Handle<HeapObject> new_target = args.new_target();
+ Handle<FunctionTemplateInfo> fun_data(function->shared()->get_api_func_data(),
+ isolate);
+ if (new_target->IsJSReceiver()) {
+ RETURN_RESULT_OR_FAILURE(
+ isolate, HandleApiCallHelper<true>(isolate, function, new_target,
+ fun_data, receiver, args));
+ } else {
+ RETURN_RESULT_OR_FAILURE(
+ isolate, HandleApiCallHelper<false>(isolate, function, new_target,
+ fun_data, receiver, args));
+ }
}
@@ -4837,14 +5425,10 @@
namespace {
-class RelocatableArguments
- : public BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>,
- public Relocatable {
+class RelocatableArguments : public BuiltinArguments, public Relocatable {
public:
RelocatableArguments(Isolate* isolate, int length, Object** arguments)
- : BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>(length,
- arguments),
- Relocatable(isolate) {}
+ : BuiltinArguments(length, arguments), Relocatable(isolate) {}
virtual inline void IterateInstance(ObjectVisitor* v) {
if (length() == 0) return;
@@ -4857,14 +5441,17 @@
} // namespace
-MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
+MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
+ Handle<HeapObject> function,
Handle<Object> receiver,
int argc,
Handle<Object> args[]) {
- Isolate* isolate = function->GetIsolate();
+ DCHECK(function->IsFunctionTemplateInfo() ||
+ (function->IsJSFunction() &&
+ JSFunction::cast(*function)->shared()->IsApiFunction()));
+
// Do proper receiver conversion for non-strict mode api functions.
if (!receiver->IsJSReceiver()) {
- DCHECK(function->IsFunctionTemplateInfo() || function->IsJSFunction());
if (function->IsFunctionTemplateInfo() ||
is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
@@ -4872,6 +5459,13 @@
Object);
}
}
+
+ Handle<FunctionTemplateInfo> fun_data =
+ function->IsFunctionTemplateInfo()
+ ? Handle<FunctionTemplateInfo>::cast(function)
+ : handle(JSFunction::cast(*function)->shared()->get_api_func_data(),
+ isolate);
+ Handle<HeapObject> new_target = isolate->factory()->undefined_value();
// Construct BuiltinArguments object:
// new target, function, arguments reversed, receiver.
const int kBufferSize = 32;
@@ -4887,15 +5481,14 @@
argv[argc - i + 1] = *args[i];
}
argv[1] = *function;
- argv[0] = isolate->heap()->undefined_value(); // new target
+ argv[0] = *new_target;
MaybeHandle<Object> result;
{
RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2);
- result = HandleApiCallHelper(isolate, arguments);
+ result = HandleApiCallHelper<false>(isolate, function, new_target, fun_data,
+ receiver, arguments);
}
- if (argv != small_argv) {
- delete[] argv;
- }
+ if (argv != small_argv) delete[] argv;
return result;
}
@@ -4904,8 +5497,7 @@
// API. The object can be called as either a constructor (using new) or just as
// a function (without new).
MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
- Isolate* isolate, bool is_construct_call,
- BuiltinArguments<BuiltinExtraArguments::kNone> args) {
+ Isolate* isolate, bool is_construct_call, BuiltinArguments args) {
Handle<Object> receiver = args.receiver();
// Get the object called.
@@ -4931,7 +5523,7 @@
CHECK(constructor->shared()->IsApiFunction());
Object* handler =
constructor->shared()->get_api_func_data()->instance_call_handler();
- DCHECK(!handler->IsUndefined());
+ DCHECK(!handler->IsUndefined(isolate));
// TODO(ishell): remove this debugging code.
CHECK(handler->IsCallHandlerInfo());
CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
@@ -4974,106 +5566,122 @@
return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
}
+namespace {
-static void Generate_LoadIC_Miss(MacroAssembler* masm) {
- LoadIC::GenerateMiss(masm);
+void Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
+ typedef compiler::Node Node;
+
+ Node* receiver = assembler->Parameter(0);
+ Node* name = assembler->Parameter(1);
+ Node* slot = assembler->Parameter(2);
+ Node* vector = assembler->Parameter(3);
+ Node* context = assembler->Parameter(4);
+
+ assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
+ slot, vector);
}
+void Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
+ typedef compiler::Node Node;
-static void Generate_LoadIC_Normal(MacroAssembler* masm) {
+ Node* slot = assembler->Parameter(0);
+ Node* vector = assembler->Parameter(1);
+ Node* context = assembler->Parameter(2);
+
+ assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
+ vector);
+}
+
+void Generate_LoadIC_Normal(MacroAssembler* masm) {
LoadIC::GenerateNormal(masm);
}
-
-static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
+void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
}
+void Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
+ typedef compiler::Node Node;
-static void Generate_LoadIC_Slow(MacroAssembler* masm) {
- LoadIC::GenerateRuntimeGetProperty(masm);
+ Node* receiver = assembler->Parameter(0);
+ Node* name = assembler->Parameter(1);
+ // Node* slot = assembler->Parameter(2);
+ // Node* vector = assembler->Parameter(3);
+ Node* context = assembler->Parameter(4);
+
+ assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
}
+void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
+ typedef compiler::Node Node;
-static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
+ Node* slot = assembler->Parameter(0);
+ Node* vector = assembler->Parameter(1);
+ Node* context = assembler->Parameter(2);
+
+ assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot,
+ vector);
+}
+
+void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
KeyedLoadIC::GenerateRuntimeGetProperty(masm);
}
-
-static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
+void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
KeyedLoadIC::GenerateMiss(masm);
}
-
-static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
+void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
KeyedLoadIC::GenerateMegamorphic(masm);
}
-
-static void Generate_StoreIC_Miss(MacroAssembler* masm) {
+void Generate_StoreIC_Miss(MacroAssembler* masm) {
StoreIC::GenerateMiss(masm);
}
-
-static void Generate_StoreIC_Normal(MacroAssembler* masm) {
+void Generate_StoreIC_Normal(MacroAssembler* masm) {
StoreIC::GenerateNormal(masm);
}
-
-static void Generate_StoreIC_Slow(MacroAssembler* masm) {
+void Generate_StoreIC_Slow(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateSlow(masm);
}
-
-static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
ElementHandlerCompiler::GenerateStoreSlow(masm);
}
-
-static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
+void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
-static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
- StoreIC::GenerateMegamorphic(masm);
-}
-
-static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
- StoreIC::GenerateMegamorphic(masm);
-}
-
-
-static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
}
-
-static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
}
-
-static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
+void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
KeyedStoreIC::GenerateMiss(masm);
}
-
-static void Generate_Return_DebugBreak(MacroAssembler* masm) {
+void Generate_Return_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateDebugBreakStub(masm,
DebugCodegen::SAVE_RESULT_REGISTER);
}
-
-static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
+void Generate_Slot_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateDebugBreakStub(masm,
DebugCodegen::IGNORE_RESULT_REGISTER);
}
-
-static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
+void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
DebugCodegen::GenerateFrameDropperLiveEdit(masm);
}
+} // namespace
Builtins::Builtins() : initialized_(false) {
memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
@@ -5084,8 +5692,7 @@
Builtins::~Builtins() {
}
-
-#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
+#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
Address const Builtins::c_functions_[cfunction_count] = {
BUILTIN_LIST_C(DEF_ENUM_C)
};
@@ -5099,7 +5706,6 @@
const char* s_name; // name is only used for generating log information.
int name;
Code::Flags flags;
- BuiltinExtraArguments extra_args;
int argc;
};
@@ -5144,13 +5750,13 @@
MacroAssembler masm(isolate, u.buffer, sizeof(u.buffer),
CodeObjectRequired::kYes);
// Generate the code/adaptor.
- typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
+ typedef void (*Generator)(MacroAssembler*, int);
Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
// We pass all arguments to the generator, but it may not use all of
// them. This works because the first arguments are on top of the
// stack.
DCHECK(!masm.has_frame());
- g(&masm, builtin_desc->name, builtin_desc->extra_args);
+ g(&masm, builtin_desc->name);
// Move the code into the object heap.
CodeDesc desc;
masm.GetCode(&desc);
@@ -5158,8 +5764,9 @@
return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
}
-Handle<Code> CodeStubAssemblerBuilder(Isolate* isolate,
- BuiltinDesc const* builtin_desc) {
+// Builder for builtins implemented in TurboFan with JS linkage.
+Handle<Code> CodeStubAssemblerBuilderJS(Isolate* isolate,
+ BuiltinDesc const* builtin_desc) {
Zone zone(isolate->allocator());
CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
builtin_desc->flags, builtin_desc->s_name);
@@ -5170,6 +5777,25 @@
return assembler.GenerateCode();
}
+// Builder for builtins implemented in TurboFan with CallStub linkage.
+Handle<Code> CodeStubAssemblerBuilderCS(Isolate* isolate,
+ BuiltinDesc const* builtin_desc) {
+ Zone zone(isolate->allocator());
+ // The interface descriptor with given key must be initialized at this point
+ // and this construction just queries the details from the descriptors table.
+ CallInterfaceDescriptor descriptor(
+ isolate, static_cast<CallDescriptors::Key>(builtin_desc->argc));
+ // Ensure descriptor is already initialized.
+ DCHECK_NOT_NULL(descriptor.GetFunctionType());
+ CodeStubAssembler assembler(isolate, &zone, descriptor, builtin_desc->flags,
+ builtin_desc->s_name);
+ // Generate the code/adaptor.
+ typedef void (*Generator)(CodeStubAssembler*);
+ Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
+ g(&assembler);
+ return assembler.GenerateCode();
+}
+
} // namespace
// Define array of pointers to generators and C builtin functions.
@@ -5184,41 +5810,46 @@
functions[builtin_count].s_name = nullptr;
functions[builtin_count].name = builtin_count;
functions[builtin_count].flags = static_cast<Code::Flags>(0);
- functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
functions[builtin_count].argc = 0;
-#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
- functions->builder = &MacroAssemblerBuilder; \
- functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
- functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
- functions->s_name = #aname; \
- functions->name = c_##aname; \
- functions->flags = Code::ComputeFlags(Code::BUILTIN); \
- functions->extra_args = BuiltinExtraArguments::aextra_args; \
- functions->argc = 0; \
+#define DEF_FUNCTION_PTR_C(aname) \
+ functions->builder = &MacroAssemblerBuilder; \
+ functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
+ functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
+ functions->s_name = #aname; \
+ functions->name = c_##aname; \
+ functions->flags = Code::ComputeFlags(Code::BUILTIN); \
+ functions->argc = 0; \
++functions;
-#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
- functions->builder = &MacroAssemblerBuilder; \
- functions->generator = FUNCTION_ADDR(Generate_##aname); \
- functions->c_code = NULL; \
- functions->s_name = #aname; \
- functions->name = k##aname; \
- functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
- functions->extra_args = BuiltinExtraArguments::kNone; \
- functions->argc = 0; \
+#define DEF_FUNCTION_PTR_A(aname, kind, extra) \
+ functions->builder = &MacroAssemblerBuilder; \
+ functions->generator = FUNCTION_ADDR(Generate_##aname); \
+ functions->c_code = NULL; \
+ functions->s_name = #aname; \
+ functions->name = k##aname; \
+ functions->flags = Code::ComputeFlags(Code::kind, extra); \
+ functions->argc = 0; \
++functions;
-#define DEF_FUNCTION_PTR_T(aname, aargc) \
- functions->builder = &CodeStubAssemblerBuilder; \
- functions->generator = FUNCTION_ADDR(Generate_##aname); \
- functions->c_code = NULL; \
- functions->s_name = #aname; \
- functions->name = k##aname; \
- functions->flags = \
- Code::ComputeFlags(Code::BUILTIN, UNINITIALIZED, kNoExtraICState); \
- functions->extra_args = BuiltinExtraArguments::kNone; \
- functions->argc = aargc; \
+#define DEF_FUNCTION_PTR_T(aname, aargc) \
+ functions->builder = &CodeStubAssemblerBuilderJS; \
+ functions->generator = FUNCTION_ADDR(Generate_##aname); \
+ functions->c_code = NULL; \
+ functions->s_name = #aname; \
+ functions->name = k##aname; \
+ functions->flags = Code::ComputeFlags(Code::BUILTIN); \
+ functions->argc = aargc; \
+ ++functions;
+
+#define DEF_FUNCTION_PTR_S(aname, kind, extra, interface_descriptor) \
+ functions->builder = &CodeStubAssemblerBuilderCS; \
+ functions->generator = FUNCTION_ADDR(Generate_##aname); \
+ functions->c_code = NULL; \
+ functions->s_name = #aname; \
+ functions->name = k##aname; \
+ functions->flags = Code::ComputeFlags(Code::kind, extra); \
+ functions->argc = CallDescriptors::interface_descriptor; \
++functions;
#define DEF_FUNCTION_PTR_H(aname, kind) \
@@ -5228,20 +5859,21 @@
functions->s_name = #aname; \
functions->name = k##aname; \
functions->flags = Code::ComputeHandlerFlags(Code::kind); \
- functions->extra_args = BuiltinExtraArguments::kNone; \
functions->argc = 0; \
++functions;
BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
BUILTIN_LIST_T(DEF_FUNCTION_PTR_T)
+ BUILTIN_LIST_S(DEF_FUNCTION_PTR_S)
BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
#undef DEF_FUNCTION_PTR_C
#undef DEF_FUNCTION_PTR_A
-#undef DEF_FUNCTION_PTR_H
#undef DEF_FUNCTION_PTR_T
+#undef DEF_FUNCTION_PTR_S
+#undef DEF_FUNCTION_PTR_H
}
@@ -5251,6 +5883,11 @@
// Create a scope for the handles in the builtins.
HandleScope scope(isolate);
+#define INITIALIZE_CALL_DESCRIPTOR(name, kind, extra, interface_descriptor) \
+ { interface_descriptor##Descriptor descriptor(isolate); }
+ BUILTIN_LIST_S(INITIALIZE_CALL_DESCRIPTOR)
+#undef INITIALIZE_CALL_DESCRIPTOR
+
const BuiltinDesc* functions = builtin_function_table.functions();
// Traverse the list of builtins and generate an adaptor in a
@@ -5260,8 +5897,8 @@
Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
// Log the event and add the code to the builtins array.
PROFILE(isolate,
- CodeCreateEvent(Logger::BUILTIN_TAG, AbstractCode::cast(*code),
- functions[i].s_name));
+ CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
+ AbstractCode::cast(*code), functions[i].s_name));
builtins_[i] = *code;
code->set_builtin_index(i);
#ifdef ENABLE_DISASSEMBLER
@@ -5555,23 +6192,26 @@
a->Return(a->Int32Constant(0));
}
-#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
-Handle<Code> Builtins::name() { \
- Code** code_address = \
- reinterpret_cast<Code**>(builtin_address(k##name)); \
- return Handle<Code>(code_address); \
-}
-#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
-Handle<Code> Builtins::name() { \
- Code** code_address = \
- reinterpret_cast<Code**>(builtin_address(k##name)); \
- return Handle<Code>(code_address); \
-}
+#define DEFINE_BUILTIN_ACCESSOR_C(name) \
+ Handle<Code> Builtins::name() { \
+ Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
+ return Handle<Code>(code_address); \
+ }
+#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, extra) \
+ Handle<Code> Builtins::name() { \
+ Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
+ return Handle<Code>(code_address); \
+ }
#define DEFINE_BUILTIN_ACCESSOR_T(name, argc) \
Handle<Code> Builtins::name() { \
Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
return Handle<Code>(code_address); \
}
+#define DEFINE_BUILTIN_ACCESSOR_S(name, kind, extra, interface_descriptor) \
+ Handle<Code> Builtins::name() { \
+ Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
+ return Handle<Code>(code_address); \
+ }
#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
Handle<Code> Builtins::name() { \
Code** code_address = \
@@ -5581,11 +6221,13 @@
BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
+BUILTIN_LIST_S(DEFINE_BUILTIN_ACCESSOR_S)
BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
#undef DEFINE_BUILTIN_ACCESSOR_C
#undef DEFINE_BUILTIN_ACCESSOR_A
#undef DEFINE_BUILTIN_ACCESSOR_T
+#undef DEFINE_BUILTIN_ACCESSOR_S
#undef DEFINE_BUILTIN_ACCESSOR_H
} // namespace internal