blob: 24abb722c57f050e58ba9748f48bb7995ccb2b3b [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/builtins.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochda12d292016-06-02 14:46:10 +01007#include "src/api-arguments.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/api-natives.h"
Ben Murdochc5610432016-08-08 18:44:38 +01009#include "src/api.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010010#include "src/base/ieee754.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011#include "src/base/once.h"
12#include "src/bootstrapper.h"
Ben Murdochda12d292016-06-02 14:46:10 +010013#include "src/code-factory.h"
Ben Murdochc5610432016-08-08 18:44:38 +010014#include "src/code-stub-assembler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015#include "src/dateparser-inl.h"
16#include "src/elements.h"
17#include "src/frames-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/gdb-jit.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019#include "src/ic/handler-compiler.h"
20#include "src/ic/ic.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021#include "src/isolate-inl.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010022#include "src/json-parser.h"
23#include "src/json-stringifier.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024#include "src/messages.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025#include "src/property-descriptor.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026#include "src/prototype.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027#include "src/string-builder.h"
Ben Murdochc5610432016-08-08 18:44:38 +010028#include "src/uri.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000030
31namespace v8 {
32namespace internal {
33
Leon Clarkee46be812010-01-19 14:06:41 +000034namespace {
35
36// Arguments object passed to C++ builtins.
Leon Clarkee46be812010-01-19 14:06:41 +000037class BuiltinArguments : public Arguments {
38 public:
39 BuiltinArguments(int length, Object** arguments)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 : Arguments(length, arguments) {
41 // Check we have at least the receiver.
42 DCHECK_LE(1, this->length());
43 }
Leon Clarkee46be812010-01-19 14:06:41 +000044
45 Object*& operator[] (int index) {
Ben Murdochc5610432016-08-08 18:44:38 +010046 DCHECK_LT(index, length());
Leon Clarkee46be812010-01-19 14:06:41 +000047 return Arguments::operator[](index);
48 }
49
50 template <class S> Handle<S> at(int index) {
Ben Murdochc5610432016-08-08 18:44:38 +010051 DCHECK_LT(index, length());
Leon Clarkee46be812010-01-19 14:06:41 +000052 return Arguments::at<S>(index);
53 }
54
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 Handle<Object> atOrUndefined(Isolate* isolate, int index) {
56 if (index >= length()) {
57 return isolate->factory()->undefined_value();
58 }
59 return at<Object>(index);
60 }
61
Leon Clarkee46be812010-01-19 14:06:41 +000062 Handle<Object> receiver() {
63 return Arguments::at<Object>(0);
64 }
65
Ben Murdoch097c5b22016-05-18 11:27:45 +010066 template <class S>
Ben Murdoch61f157c2016-09-16 13:49:30 +010067 Handle<S> target() {
68 return Arguments::at<S>(Arguments::length() - 2);
69 }
70 Handle<HeapObject> new_target() {
71 return Arguments::at<HeapObject>(Arguments::length() - 1);
72 }
Leon Clarkee46be812010-01-19 14:06:41 +000073
74 // Gets the total number of arguments including the receiver (but
75 // excluding extra arguments).
Ben Murdoch61f157c2016-09-16 13:49:30 +010076 int length() const { return Arguments::length() - 2; }
Leon Clarkee46be812010-01-19 14:06:41 +000077};
78
79
Steve Blocka7e24c12009-10-30 11:49:00 +000080// ----------------------------------------------------------------------------
Leon Clarkee46be812010-01-19 14:06:41 +000081// Support macro for defining builtins in C++.
Steve Blocka7e24c12009-10-30 11:49:00 +000082// ----------------------------------------------------------------------------
83//
84// A builtin function is defined by writing:
85//
86// BUILTIN(name) {
87// ...
88// }
Steve Blocka7e24c12009-10-30 11:49:00 +000089//
Leon Clarkee46be812010-01-19 14:06:41 +000090// In the body of the builtin function the arguments can be accessed
91// through the BuiltinArguments object args.
Ben Murdochc5610432016-08-08 18:44:38 +010092// TODO(cbruni): add global flag to check whether any tracing events have been
93// enabled.
Ben Murdoch61f157c2016-09-16 13:49:30 +010094#define BUILTIN(name) \
95 MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args, \
96 Isolate* isolate); \
97 \
98 V8_NOINLINE static Object* Builtin_Impl_Stats_##name( \
99 int args_length, Object** args_object, Isolate* isolate) { \
100 BuiltinArguments args(args_length, args_object); \
101 RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Builtin_##name); \
102 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
103 "V8.Builtin_" #name); \
104 return Builtin_Impl_##name(args, isolate); \
105 } \
106 \
107 MUST_USE_RESULT static Object* Builtin_##name( \
108 int args_length, Object** args_object, Isolate* isolate) { \
109 if (FLAG_runtime_call_stats) { \
110 return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \
111 } \
112 BuiltinArguments args(args_length, args_object); \
113 return Builtin_Impl_##name(args, isolate); \
114 } \
115 \
116 MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args, \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100117 Isolate* isolate)
Steve Blocka7e24c12009-10-30 11:49:00 +0000118
119// ----------------------------------------------------------------------------
120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121#define CHECK_RECEIVER(Type, name, method) \
122 if (!args.receiver()->Is##Type()) { \
123 THROW_NEW_ERROR_RETURN_FAILURE( \
124 isolate, \
125 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
126 isolate->factory()->NewStringFromAsciiChecked(method), \
127 args.receiver())); \
128 } \
129 Handle<Type> name = Handle<Type>::cast(args.receiver())
130
Ben Murdoch61f157c2016-09-16 13:49:30 +0100131// Throws a TypeError for {method} if the receiver is not coercible to Object,
132// or converts the receiver to a String otherwise and assigns it to a new var
133// with the given {name}.
134#define TO_THIS_STRING(name, method) \
135 if (args.receiver()->IsNull(isolate) || \
136 args.receiver()->IsUndefined(isolate)) { \
137 THROW_NEW_ERROR_RETURN_FAILURE( \
138 isolate, \
139 NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, \
140 isolate->factory()->NewStringFromAsciiChecked(method))); \
141 } \
142 Handle<String> name; \
143 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
144 isolate, name, Object::ToString(isolate, args.receiver()))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145
Ben Murdoch61f157c2016-09-16 13:49:30 +0100146inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 // This is an extended version of ECMA-262 7.1.11 handling signed values
148 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
149 if (object->IsSmi()) {
150 *out = Smi::cast(object)->value();
151 return true;
152 } else if (object->IsHeapNumber()) {
153 double value = HeapNumber::cast(object)->value();
154 if (std::isnan(value)) {
155 *out = 0;
156 } else if (value > kMaxInt) {
157 *out = kMaxInt;
158 } else if (value < kMinInt) {
159 *out = kMinInt;
160 } else {
161 *out = static_cast<int>(value);
162 }
163 return true;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100164 } else if (object->IsUndefined(isolate) || object->IsNull(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 *out = 0;
166 return true;
167 } else if (object->IsBoolean()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100168 *out = object->IsTrue(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 return true;
170 }
171 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000172}
Steve Blocka7e24c12009-10-30 11:49:00 +0000173
174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
176 int* out) {
Ben Murdochc5610432016-08-08 18:44:38 +0100177 Context* context = *isolate->native_context();
178 Map* map = object->map();
179 if (map != context->sloppy_arguments_map() &&
180 map != context->strict_arguments_map() &&
181 map != context->fast_aliased_arguments_map()) {
182 return false;
183 }
184 DCHECK(object->HasFastElements() || object->HasFastArgumentsElements());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100185 Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 if (!len_obj->IsSmi()) return false;
187 *out = Max(0, Smi::cast(len_obj)->value());
188 return *out <= object->elements()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000189}
Steve Blocka7e24c12009-10-30 11:49:00 +0000190
Ben Murdochda12d292016-06-02 14:46:10 +0100191inline bool PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 DisallowHeapAllocation no_gc;
Ben Murdochda12d292016-06-02 14:46:10 +0100193 HeapObject* prototype = HeapObject::cast(object->map()->prototype());
194 HeapObject* null = isolate->heap()->null_value();
195 HeapObject* empty = isolate->heap()->empty_fixed_array();
196 while (prototype != null) {
197 Map* map = prototype->map();
198 if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false;
199 if (JSObject::cast(prototype)->elements() != empty) return false;
200 prototype = HeapObject::cast(map->prototype());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202 return true;
203}
204
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
206 JSArray* receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100207 return PrototypeHasNoElements(isolate, receiver);
Steve Block6ded16b2010-05-10 14:33:55 +0100208}
209
Ben Murdoch097c5b22016-05-18 11:27:45 +0100210inline bool HasSimpleElements(JSObject* current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100211 return current->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
212 !current->GetElementsAccessor()->HasAccessors(current);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100213}
214
215inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
Ben Murdochda12d292016-06-02 14:46:10 +0100216 JSObject* receiver) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100217 // Check that we have no accessors on the receiver's elements.
Ben Murdochda12d292016-06-02 14:46:10 +0100218 if (!HasSimpleElements(receiver)) return false;
219 return PrototypeHasNoElements(isolate, receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100220}
221
222inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100223 DisallowHeapAllocation no_gc;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100224 PrototypeIterator iter(isolate, receiver, kStartAtReceiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100225 for (; !iter.IsAtEnd(); iter.Advance()) {
226 if (iter.GetCurrent()->IsJSProxy()) return false;
227 JSObject* current = iter.GetCurrent<JSObject>();
228 if (!HasSimpleElements(current)) return false;
229 }
230 return true;
231}
Steve Block6ded16b2010-05-10 14:33:55 +0100232
Ben Murdochda12d292016-06-02 14:46:10 +0100233// Returns |false| if not applicable.
John Reck59135872010-11-02 12:39:01 -0700234MUST_USE_RESULT
Ben Murdochda12d292016-06-02 14:46:10 +0100235inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
236 Handle<Object> receiver,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100237 BuiltinArguments* args,
Ben Murdochda12d292016-06-02 14:46:10 +0100238 int first_added_arg) {
239 if (!receiver->IsJSArray()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Ben Murdochda12d292016-06-02 14:46:10 +0100241 ElementsKind origin_kind = array->GetElementsKind();
242 if (IsDictionaryElementsKind(origin_kind)) return false;
Ben Murdochda12d292016-06-02 14:46:10 +0100243 if (!array->map()->is_extensible()) return false;
244 if (args == nullptr) return true;
245
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 // If there may be elements accessors in the prototype chain, the fast path
247 // cannot be used if there arguments to add to the array.
Ben Murdochda12d292016-06-02 14:46:10 +0100248 if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100249
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 // Adding elements to the array prototype would break code that makes sure
251 // it has no elements. Handle that elsewhere.
Ben Murdochda12d292016-06-02 14:46:10 +0100252 if (isolate->IsAnyInitialArrayPrototype(array)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100254 // Need to ensure that the arguments passed in args can be contained in
255 // the array.
256 int args_length = args->length();
Ben Murdochda12d292016-06-02 14:46:10 +0100257 if (first_added_arg >= args_length) return true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100258
Ben Murdochda12d292016-06-02 14:46:10 +0100259 if (IsFastObjectElementsKind(origin_kind)) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 ElementsKind target_kind = origin_kind;
261 {
262 DisallowHeapAllocation no_gc;
Ben Murdochda12d292016-06-02 14:46:10 +0100263 for (int i = first_added_arg; i < args_length; i++) {
264 Object* arg = (*args)[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265 if (arg->IsHeapObject()) {
266 if (arg->IsHeapNumber()) {
267 target_kind = FAST_DOUBLE_ELEMENTS;
268 } else {
269 target_kind = FAST_ELEMENTS;
270 break;
271 }
272 }
273 }
274 }
275 if (target_kind != origin_kind) {
Ben Murdochda12d292016-06-02 14:46:10 +0100276 // Use a short-lived HandleScope to avoid creating several copies of the
277 // elements handle which would cause issues when left-trimming later-on.
278 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 JSObject::TransitionElementsKind(array, target_kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280 }
Ben Murdochda12d292016-06-02 14:46:10 +0100281 return true;
Steve Block6ded16b2010-05-10 14:33:55 +0100282}
283
Ben Murdoch61f157c2016-09-16 13:49:30 +0100284MUST_USE_RESULT static Object* CallJsIntrinsic(Isolate* isolate,
285 Handle<JSFunction> function,
286 BuiltinArguments args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100287 HandleScope handleScope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100288 int argc = args.length() - 1;
289 ScopedVector<Handle<Object> > argv(argc);
290 for (int i = 0; i < argc; ++i) {
291 argv[i] = args.at<Object>(i + 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100292 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100293 RETURN_RESULT_OR_FAILURE(
294 isolate,
295 Execution::Call(isolate, function, args.receiver(), argc, argv.start()));
Steve Block6ded16b2010-05-10 14:33:55 +0100296}
297
298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299} // namespace
300
301
302BUILTIN(Illegal) {
303 UNREACHABLE();
304 return isolate->heap()->undefined_value(); // Make compiler happy.
305}
306
307
308BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
309
Ben Murdochc5610432016-08-08 18:44:38 +0100310void Builtins::Generate_ArrayIsArray(CodeStubAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100311 typedef compiler::Node Node;
Ben Murdochc5610432016-08-08 18:44:38 +0100312 typedef CodeStubAssembler::Label Label;
313
314 Node* object = assembler->Parameter(1);
315 Node* context = assembler->Parameter(4);
316
317 Label call_runtime(assembler), return_true(assembler),
318 return_false(assembler);
319
320 assembler->GotoIf(assembler->WordIsSmi(object), &return_false);
321 Node* instance_type = assembler->LoadInstanceType(object);
322
323 assembler->GotoIf(assembler->Word32Equal(
324 instance_type, assembler->Int32Constant(JS_ARRAY_TYPE)),
325 &return_true);
326
327 // TODO(verwaest): Handle proxies in-place.
328 assembler->Branch(assembler->Word32Equal(
329 instance_type, assembler->Int32Constant(JS_PROXY_TYPE)),
330 &call_runtime, &return_false);
331
332 assembler->Bind(&return_true);
333 assembler->Return(assembler->BooleanConstant(true));
334
335 assembler->Bind(&return_false);
336 assembler->Return(assembler->BooleanConstant(false));
337
338 assembler->Bind(&call_runtime);
339 assembler->Return(
340 assembler->CallRuntime(Runtime::kArrayIsArray, context, object));
341}
342
343void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
344 typedef compiler::Node Node;
345 typedef CodeStubAssembler::Label Label;
346 typedef CodeStubAssembler::Variable Variable;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347
Ben Murdochda12d292016-06-02 14:46:10 +0100348 Node* object = assembler->Parameter(0);
349 Node* key = assembler->Parameter(1);
350 Node* context = assembler->Parameter(4);
351
352 Label call_runtime(assembler), return_true(assembler),
353 return_false(assembler);
354
355 // Smi receivers do not have own properties.
356 Label if_objectisnotsmi(assembler);
357 assembler->Branch(assembler->WordIsSmi(object), &return_false,
358 &if_objectisnotsmi);
359 assembler->Bind(&if_objectisnotsmi);
360
361 Node* map = assembler->LoadMap(object);
362 Node* instance_type = assembler->LoadMapInstanceType(map);
363
364 Variable var_index(assembler, MachineRepresentation::kWord32);
365
Ben Murdochc5610432016-08-08 18:44:38 +0100366 Label keyisindex(assembler), if_iskeyunique(assembler);
367 assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
368 &call_runtime);
Ben Murdochda12d292016-06-02 14:46:10 +0100369
Ben Murdochda12d292016-06-02 14:46:10 +0100370 assembler->Bind(&if_iskeyunique);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100371 assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
Ben Murdochc5610432016-08-08 18:44:38 +0100372 &return_false, &call_runtime);
Ben Murdochda12d292016-06-02 14:46:10 +0100373
374 assembler->Bind(&keyisindex);
Ben Murdochc5610432016-08-08 18:44:38 +0100375 assembler->TryLookupElement(object, map, instance_type, var_index.value(),
376 &return_true, &return_false, &call_runtime);
Ben Murdochda12d292016-06-02 14:46:10 +0100377
378 assembler->Bind(&return_true);
379 assembler->Return(assembler->BooleanConstant(true));
380
381 assembler->Bind(&return_false);
382 assembler->Return(assembler->BooleanConstant(false));
383
384 assembler->Bind(&call_runtime);
385 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
386 context, object, key));
387}
388
389namespace {
390
Ben Murdoch61f157c2016-09-16 13:49:30 +0100391Object* DoArrayPush(Isolate* isolate, BuiltinArguments args) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392 HandleScope scope(isolate);
393 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100394 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395 return CallJsIntrinsic(isolate, isolate->array_push(), args);
John Reck59135872010-11-02 12:39:01 -0700396 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397 // Fast Elements Path
Ben Murdochda12d292016-06-02 14:46:10 +0100398 int to_add = args.length() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 int len = Smi::cast(array->length())->value();
Ben Murdochda12d292016-06-02 14:46:10 +0100401 if (to_add == 0) return Smi::FromInt(len);
402
403 // Currently fixed arrays cannot grow too big, so we should never hit this.
404 DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
405
406 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 return CallJsIntrinsic(isolate, isolate->array_push(), args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000408 }
Ben Murdochda12d292016-06-02 14:46:10 +0100409
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 ElementsAccessor* accessor = array->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100411 int new_length = accessor->Push(array, &args, to_add);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 return Smi::FromInt(new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000413}
Steve Blocka7e24c12009-10-30 11:49:00 +0000414
Ben Murdochda12d292016-06-02 14:46:10 +0100415} // namespace
416
417BUILTIN(ArrayPush) { return DoArrayPush(isolate, args); }
418
419// TODO(verwaest): This is a temporary helper until the FastArrayPush stub can
420// tailcall to the builtin directly.
421RUNTIME_FUNCTION(Runtime_ArrayPush) {
422 DCHECK_EQ(2, args.length());
423 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
424 // Rewrap the arguments as builtins arguments.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100425 BuiltinArguments caller_args(incoming->length() + 3,
426 incoming->arguments() + 1);
Ben Murdochda12d292016-06-02 14:46:10 +0100427 return DoArrayPush(isolate, caller_args);
428}
Steve Blocka7e24c12009-10-30 11:49:00 +0000429
430BUILTIN(ArrayPop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 HandleScope scope(isolate);
432 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100433 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
John Reck59135872010-11-02 12:39:01 -0700435 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000436
437 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000438
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 if (len == 0) return isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000441
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400442 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000443 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400444 }
445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 Handle<Object> result;
447 if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
448 // Fast Elements Path
Ben Murdochda12d292016-06-02 14:46:10 +0100449 result = array->GetElementsAccessor()->Pop(array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 } else {
451 // Use Slow Lookup otherwise
452 uint32_t new_length = len - 1;
453 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdochda12d292016-06-02 14:46:10 +0100454 isolate, result, JSReceiver::GetElement(isolate, array, new_length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 JSArray::SetLength(array, new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000456 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 return *result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000458}
Steve Blocka7e24c12009-10-30 11:49:00 +0000459
460
Andrei Popescu402d9372010-02-26 13:31:12 +0000461BUILTIN(ArrayShift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100463 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100465 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0) ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
467 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100468 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Andrei Popescu402d9372010-02-26 13:31:12 +0000470
471 int len = Smi::cast(array->length())->value();
Steve Block44f0eee2011-05-26 01:26:41 +0100472 if (len == 0) return heap->undefined_value();
Andrei Popescu402d9372010-02-26 13:31:12 +0000473
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400474 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400476 }
477
Ben Murdochda12d292016-06-02 14:46:10 +0100478 Handle<Object> first = array->GetElementsAccessor()->Shift(array);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000479 return *first;
Andrei Popescu402d9372010-02-26 13:31:12 +0000480}
481
482
483BUILTIN(ArrayUnshift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100486 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100488 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Andrei Popescu402d9372010-02-26 13:31:12 +0000490 int to_add = args.length() - 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100491 if (to_add == 0) return array->length();
Andrei Popescu402d9372010-02-26 13:31:12 +0000492
Ben Murdochda12d292016-06-02 14:46:10 +0100493 // Currently fixed arrays cannot grow too big, so we should never hit this.
494 DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
495
496 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498 }
499
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 ElementsAccessor* accessor = array->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100501 int new_length = accessor->Unshift(array, &args, to_add);
Andrei Popescu402d9372010-02-26 13:31:12 +0000502 return Smi::FromInt(new_length);
503}
504
505
Andrei Popescu402d9372010-02-26 13:31:12 +0000506BUILTIN(ArraySlice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 Handle<Object> receiver = args.receiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100509 int len = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 int relative_start = 0;
511 int relative_end = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 if (receiver->IsJSArray()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 JSArray* array = JSArray::cast(*receiver);
Ben Murdochda12d292016-06-02 14:46:10 +0100516 if (V8_UNLIKELY(!array->HasFastElements() ||
517 !IsJSArrayFastElementMovingAllowed(isolate, array) ||
518 !isolate->IsArraySpeciesLookupChainIntact() ||
519 // If this is a subclass of Array, then call out to JS
520 !array->HasArrayPrototype(isolate))) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521 AllowHeapAllocation allow_allocation;
522 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Steve Block9fac8402011-05-12 15:51:54 +0100523 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524 len = Smi::cast(array->length())->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 } else if (receiver->IsJSObject() &&
526 GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
527 &len)) {
Ben Murdochc5610432016-08-08 18:44:38 +0100528 // Array.prototype.slice.call(arguments, ...) is quite a common idiom
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 // (notably more than 50% of invocations in Web apps).
530 // Treat it in C++ as well.
Ben Murdochc5610432016-08-08 18:44:38 +0100531 DCHECK(JSObject::cast(*receiver)->HasFastElements() ||
532 JSObject::cast(*receiver)->HasFastArgumentsElements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 } else {
534 AllowHeapAllocation allow_allocation;
535 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
536 }
Ben Murdochda12d292016-06-02 14:46:10 +0100537 DCHECK_LE(0, len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000538 int argument_count = args.length() - 1;
539 // Note carefully chosen defaults---if argument is missing,
540 // it's undefined which gets converted to 0 for relative_start
541 // and to len for relative_end.
542 relative_start = 0;
543 relative_end = len;
544 if (argument_count > 0) {
545 DisallowHeapAllocation no_gc;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100546 if (!ClampedToInteger(isolate, args[1], &relative_start)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000547 AllowHeapAllocation allow_allocation;
548 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
549 }
550 if (argument_count > 1) {
551 Object* end_arg = args[2];
552 // slice handles the end_arg specially
Ben Murdoch61f157c2016-09-16 13:49:30 +0100553 if (end_arg->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 relative_end = len;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100555 } else if (!ClampedToInteger(isolate, end_arg, &relative_end)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000559 }
560 }
561
562 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
564 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000565
566 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 uint32_t actual_end =
568 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000569
Ben Murdochda12d292016-06-02 14:46:10 +0100570 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 ElementsAccessor* accessor = object->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100572 return *accessor->Slice(object, actual_start, actual_end);
Andrei Popescu402d9372010-02-26 13:31:12 +0000573}
574
575
576BUILTIN(ArraySplice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100579 if (V8_UNLIKELY(
580 !EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3) ||
581 // If this is a subclass of Array, then call out to JS.
582 !Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) ||
583 // If anything with @@species has been messed with, call out to JS.
584 !isolate->IsArraySpeciesLookupChainIntact())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100586 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Andrei Popescu402d9372010-02-26 13:31:12 +0000588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589 int argument_count = args.length() - 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100590 int relative_start = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 if (argument_count > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 DisallowHeapAllocation no_gc;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100593 if (!ClampedToInteger(isolate, args[1], &relative_start)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100596 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000597 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000598 int len = Smi::cast(array->length())->value();
599 // clip relative start to [0, len]
Steve Block6ded16b2010-05-10 14:33:55 +0100600 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
601 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000602
Steve Block1e0659c2011-05-24 12:43:12 +0100603 int actual_delete_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 if (argument_count == 1) {
605 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
606 // given as a request to delete all the elements from the start.
607 // And it differs from the case of undefined delete count.
608 // This does not follow ECMA-262, but we do the same for compatibility.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 DCHECK(len - actual_start >= 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100610 actual_delete_count = len - actual_start;
611 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 int delete_count = 0;
613 DisallowHeapAllocation no_gc;
614 if (argument_count > 1) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100615 if (!ClampedToInteger(isolate, args[2], &delete_count)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100618 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000619 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
Andrei Popescu402d9372010-02-26 13:31:12 +0000621 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000622
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623 int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
624 int new_length = len - actual_delete_count + add_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400626 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
627 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400629 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 ElementsAccessor* accessor = array->GetElementsAccessor();
631 Handle<JSArray> result_array = accessor->Splice(
Ben Murdochda12d292016-06-02 14:46:10 +0100632 array, actual_start, actual_delete_count, &args, add_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000634}
635
636
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637// Array Concat -------------------------------------------------------------
Steve Block6ded16b2010-05-10 14:33:55 +0100638
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639namespace {
640
641/**
642 * A simple visitor visits every element of Array's.
643 * The backend storage can be a fixed array for fast elements case,
644 * or a dictionary for sparse array. Since Dictionary is a subtype
645 * of FixedArray, the class can be used by both fast and slow cases.
646 * The second parameter of the constructor, fast_elements, specifies
647 * whether the storage is a FixedArray or Dictionary.
648 *
649 * An index limit is used to deal with the situation that a result array
650 * length overflows 32-bit non-negative integer.
651 */
652class ArrayConcatVisitor {
653 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100654 ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 bool fast_elements)
656 : isolate_(isolate),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100657 storage_(isolate->global_handles()->Create(*storage)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 index_offset_(0u),
659 bit_field_(FastElementsField::encode(fast_elements) |
Ben Murdoch097c5b22016-05-18 11:27:45 +0100660 ExceedsLimitField::encode(false) |
661 IsFixedArrayField::encode(storage->IsFixedArray())) {
662 DCHECK(!(this->fast_elements() && !is_fixed_array()));
663 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664
665 ~ArrayConcatVisitor() { clear_storage(); }
666
Ben Murdochda12d292016-06-02 14:46:10 +0100667 MUST_USE_RESULT bool visit(uint32_t i, Handle<Object> elm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 uint32_t index = index_offset_ + i;
669
Ben Murdoch097c5b22016-05-18 11:27:45 +0100670 if (i >= JSObject::kMaxElementCount - index_offset_) {
671 set_exceeds_array_limit(true);
672 // Exception hasn't been thrown at this point. Return true to
673 // break out, and caller will throw. !visit would imply that
674 // there is already a pending exception.
675 return true;
676 }
677
Ben Murdochda12d292016-06-02 14:46:10 +0100678 if (!is_fixed_array()) {
679 LookupIterator it(isolate_, storage_, index, LookupIterator::OWN);
680 MAYBE_RETURN(
681 JSReceiver::CreateDataProperty(&it, elm, Object::THROW_ON_ERROR),
682 false);
683 return true;
684 }
685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 if (fast_elements()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100687 if (index < static_cast<uint32_t>(storage_fixed_array()->length())) {
688 storage_fixed_array()->set(index, *elm);
689 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000690 }
691 // Our initial estimate of length was foiled, possibly by
692 // getters on the arrays increasing the length of later arrays
693 // during iteration.
694 // This shouldn't happen in anything but pathological cases.
695 SetDictionaryMode();
696 // Fall-through to dictionary mode.
697 }
698 DCHECK(!fast_elements());
699 Handle<SeededNumberDictionary> dict(
700 SeededNumberDictionary::cast(*storage_));
701 // The object holding this backing store has just been allocated, so
702 // it cannot yet be used as a prototype.
703 Handle<SeededNumberDictionary> result =
704 SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
705 if (!result.is_identical_to(dict)) {
706 // Dictionary needed to grow.
707 clear_storage();
708 set_storage(*result);
709 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100710 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 }
712
713 void increase_index_offset(uint32_t delta) {
714 if (JSObject::kMaxElementCount - index_offset_ < delta) {
715 index_offset_ = JSObject::kMaxElementCount;
716 } else {
717 index_offset_ += delta;
718 }
719 // If the initial length estimate was off (see special case in visit()),
720 // but the array blowing the limit didn't contain elements beyond the
721 // provided-for index range, go to dictionary mode now.
722 if (fast_elements() &&
723 index_offset_ >
724 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
725 SetDictionaryMode();
726 }
727 }
728
729 bool exceeds_array_limit() const {
730 return ExceedsLimitField::decode(bit_field_);
731 }
732
733 Handle<JSArray> ToArray() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100734 DCHECK(is_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
736 Handle<Object> length =
737 isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
738 Handle<Map> map = JSObject::GetElementsTransitionMap(
739 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
740 array->set_map(*map);
741 array->set_length(*length);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100742 array->set_elements(*storage_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 return array;
744 }
745
Ben Murdoch097c5b22016-05-18 11:27:45 +0100746 // Storage is either a FixedArray (if is_fixed_array()) or a JSReciever
747 // (otherwise)
748 Handle<FixedArray> storage_fixed_array() {
749 DCHECK(is_fixed_array());
750 return Handle<FixedArray>::cast(storage_);
751 }
752 Handle<JSReceiver> storage_jsreceiver() {
753 DCHECK(!is_fixed_array());
754 return Handle<JSReceiver>::cast(storage_);
755 }
756
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 private:
758 // Convert storage to dictionary mode.
759 void SetDictionaryMode() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100760 DCHECK(fast_elements() && is_fixed_array());
761 Handle<FixedArray> current_storage = storage_fixed_array();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 Handle<SeededNumberDictionary> slow_storage(
763 SeededNumberDictionary::New(isolate_, current_storage->length()));
764 uint32_t current_length = static_cast<uint32_t>(current_storage->length());
Ben Murdochda12d292016-06-02 14:46:10 +0100765 FOR_WITH_HANDLE_SCOPE(
766 isolate_, uint32_t, i = 0, i, i < current_length, i++, {
767 Handle<Object> element(current_storage->get(i), isolate_);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100768 if (!element->IsTheHole(isolate_)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100769 // The object holding this backing store has just been allocated, so
770 // it cannot yet be used as a prototype.
771 Handle<SeededNumberDictionary> new_storage =
772 SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
773 false);
774 if (!new_storage.is_identical_to(slow_storage)) {
775 slow_storage = loop_scope.CloseAndEscape(new_storage);
776 }
777 }
778 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000779 clear_storage();
780 set_storage(*slow_storage);
781 set_fast_elements(false);
782 }
783
Ben Murdochda12d292016-06-02 14:46:10 +0100784 inline void clear_storage() { GlobalHandles::Destroy(storage_.location()); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000785
786 inline void set_storage(FixedArray* storage) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100787 DCHECK(is_fixed_array());
788 storage_ = isolate_->global_handles()->Create(storage);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000789 }
790
791 class FastElementsField : public BitField<bool, 0, 1> {};
792 class ExceedsLimitField : public BitField<bool, 1, 1> {};
Ben Murdoch097c5b22016-05-18 11:27:45 +0100793 class IsFixedArrayField : public BitField<bool, 2, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794
795 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
796 void set_fast_elements(bool fast) {
797 bit_field_ = FastElementsField::update(bit_field_, fast);
798 }
799 void set_exceeds_array_limit(bool exceeds) {
800 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
801 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100802 bool is_fixed_array() const { return IsFixedArrayField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000803
804 Isolate* isolate_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100805 Handle<Object> storage_; // Always a global handle.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 // Index after last seen index. Always less than or equal to
807 // JSObject::kMaxElementCount.
808 uint32_t index_offset_;
809 uint32_t bit_field_;
810};
811
812
813uint32_t EstimateElementCount(Handle<JSArray> array) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100814 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 uint32_t length = static_cast<uint32_t>(array->length()->Number());
816 int element_count = 0;
817 switch (array->GetElementsKind()) {
818 case FAST_SMI_ELEMENTS:
819 case FAST_HOLEY_SMI_ELEMENTS:
820 case FAST_ELEMENTS:
821 case FAST_HOLEY_ELEMENTS: {
822 // Fast elements can't have lengths that are not representable by
823 // a 32-bit signed integer.
824 DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
825 int fast_length = static_cast<int>(length);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100826 Isolate* isolate = array->GetIsolate();
827 FixedArray* elements = FixedArray::cast(array->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000828 for (int i = 0; i < fast_length; i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100829 if (!elements->get(i)->IsTheHole(isolate)) element_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 }
831 break;
832 }
833 case FAST_DOUBLE_ELEMENTS:
834 case FAST_HOLEY_DOUBLE_ELEMENTS: {
835 // Fast elements can't have lengths that are not representable by
836 // a 32-bit signed integer.
837 DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
838 int fast_length = static_cast<int>(length);
839 if (array->elements()->IsFixedArray()) {
840 DCHECK(FixedArray::cast(array->elements())->length() == 0);
841 break;
842 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100843 FixedDoubleArray* elements = FixedDoubleArray::cast(array->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844 for (int i = 0; i < fast_length; i++) {
845 if (!elements->is_the_hole(i)) element_count++;
846 }
847 break;
848 }
849 case DICTIONARY_ELEMENTS: {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100850 SeededNumberDictionary* dictionary =
851 SeededNumberDictionary::cast(array->elements());
852 Isolate* isolate = dictionary->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 int capacity = dictionary->Capacity();
854 for (int i = 0; i < capacity; i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100855 Object* key = dictionary->KeyAt(i);
856 if (dictionary->IsKey(isolate, key)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857 element_count++;
858 }
859 }
860 break;
861 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
863
864 TYPED_ARRAYS(TYPED_ARRAY_CASE)
865#undef TYPED_ARRAY_CASE
866 // External arrays are always dense.
867 return length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100868 case NO_ELEMENTS:
869 return 0;
870 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
871 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
872 case FAST_STRING_WRAPPER_ELEMENTS:
873 case SLOW_STRING_WRAPPER_ELEMENTS:
874 UNREACHABLE();
875 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 }
877 // As an estimate, we assume that the prototype doesn't contain any
878 // inherited elements.
879 return element_count;
880}
881
882
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000883// Used for sorting indices in a List<uint32_t>.
884int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
885 uint32_t a = *ap;
886 uint32_t b = *bp;
887 return (a == b) ? 0 : (a < b) ? -1 : 1;
888}
889
890
891void CollectElementIndices(Handle<JSObject> object, uint32_t range,
892 List<uint32_t>* indices) {
893 Isolate* isolate = object->GetIsolate();
894 ElementsKind kind = object->GetElementsKind();
895 switch (kind) {
896 case FAST_SMI_ELEMENTS:
897 case FAST_ELEMENTS:
898 case FAST_HOLEY_SMI_ELEMENTS:
899 case FAST_HOLEY_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +0100900 DisallowHeapAllocation no_gc;
901 FixedArray* elements = FixedArray::cast(object->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 uint32_t length = static_cast<uint32_t>(elements->length());
903 if (range < length) length = range;
904 for (uint32_t i = 0; i < length; i++) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100905 if (!elements->get(i)->IsTheHole(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 indices->Add(i);
907 }
908 }
909 break;
910 }
911 case FAST_HOLEY_DOUBLE_ELEMENTS:
912 case FAST_DOUBLE_ELEMENTS: {
913 if (object->elements()->IsFixedArray()) {
914 DCHECK(object->elements()->length() == 0);
915 break;
916 }
917 Handle<FixedDoubleArray> elements(
918 FixedDoubleArray::cast(object->elements()));
919 uint32_t length = static_cast<uint32_t>(elements->length());
920 if (range < length) length = range;
921 for (uint32_t i = 0; i < length; i++) {
922 if (!elements->is_the_hole(i)) {
923 indices->Add(i);
924 }
925 }
926 break;
927 }
928 case DICTIONARY_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +0100929 DisallowHeapAllocation no_gc;
930 SeededNumberDictionary* dict =
931 SeededNumberDictionary::cast(object->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 uint32_t capacity = dict->Capacity();
Ben Murdochda12d292016-06-02 14:46:10 +0100933 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
934 Object* k = dict->KeyAt(j);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100935 if (!dict->IsKey(isolate, k)) continue;
Ben Murdochda12d292016-06-02 14:46:10 +0100936 DCHECK(k->IsNumber());
937 uint32_t index = static_cast<uint32_t>(k->Number());
938 if (index < range) {
939 indices->Add(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 }
Ben Murdochda12d292016-06-02 14:46:10 +0100941 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 break;
943 }
944#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
945
946 TYPED_ARRAYS(TYPED_ARRAY_CASE)
947#undef TYPED_ARRAY_CASE
948 {
949 uint32_t length = static_cast<uint32_t>(
950 FixedArrayBase::cast(object->elements())->length());
951 if (range <= length) {
952 length = range;
953 // We will add all indices, so we might as well clear it first
954 // and avoid duplicates.
955 indices->Clear();
956 }
957 for (uint32_t i = 0; i < length; i++) {
958 indices->Add(i);
959 }
960 if (length == range) return; // All indices accounted for already.
961 break;
962 }
963 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
964 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
965 ElementsAccessor* accessor = object->GetElementsAccessor();
966 for (uint32_t i = 0; i < range; i++) {
967 if (accessor->HasElement(object, i)) {
968 indices->Add(i);
969 }
970 }
971 break;
972 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100973 case FAST_STRING_WRAPPER_ELEMENTS:
974 case SLOW_STRING_WRAPPER_ELEMENTS: {
975 DCHECK(object->IsJSValue());
976 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
977 DCHECK(js_value->value()->IsString());
978 Handle<String> string(String::cast(js_value->value()), isolate);
979 uint32_t length = static_cast<uint32_t>(string->length());
980 uint32_t i = 0;
981 uint32_t limit = Min(length, range);
982 for (; i < limit; i++) {
983 indices->Add(i);
984 }
985 ElementsAccessor* accessor = object->GetElementsAccessor();
986 for (; i < range; i++) {
987 if (accessor->HasElement(object, i)) {
988 indices->Add(i);
989 }
990 }
991 break;
992 }
993 case NO_ELEMENTS:
994 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 }
996
997 PrototypeIterator iter(isolate, object);
998 if (!iter.IsAtEnd()) {
999 // The prototype will usually have no inherited element indices,
1000 // but we have to check.
1001 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
1002 indices);
1003 }
1004}
1005
1006
1007bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
1008 uint32_t length, ArrayConcatVisitor* visitor) {
Ben Murdochda12d292016-06-02 14:46:10 +01001009 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, i = 0, i, i < length, ++i, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001010 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
1011 if (!maybe.IsJust()) return false;
1012 if (maybe.FromJust()) {
1013 Handle<Object> element_value;
Ben Murdochda12d292016-06-02 14:46:10 +01001014 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1015 isolate, element_value, JSReceiver::GetElement(isolate, receiver, i),
1016 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001017 if (!visitor->visit(i, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001018 }
Ben Murdochda12d292016-06-02 14:46:10 +01001019 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020 visitor->increase_index_offset(length);
1021 return true;
1022}
1023
1024
1025/**
1026 * A helper function that visits "array" elements of a JSReceiver in numerical
1027 * order.
1028 *
1029 * The visitor argument called for each existing element in the array
1030 * with the element index and the element's value.
1031 * Afterwards it increments the base-index of the visitor by the array
1032 * length.
1033 * Returns false if any access threw an exception, otherwise true.
1034 */
1035bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1036 ArrayConcatVisitor* visitor) {
1037 uint32_t length = 0;
1038
1039 if (receiver->IsJSArray()) {
1040 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
1041 length = static_cast<uint32_t>(array->length()->Number());
1042 } else {
1043 Handle<Object> val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001044 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdoch61f157c2016-09-16 13:49:30 +01001045 isolate, val, Object::GetLengthFromArrayLike(isolate, receiver), false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001046 // TODO(caitp): Support larger element indexes (up to 2^53-1).
1047 if (!val->ToUint32(&length)) {
1048 length = 0;
1049 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001050 // TODO(cbruni): handle other element kind as well
1051 return IterateElementsSlow(isolate, receiver, length, visitor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001052 }
1053
Ben Murdoch097c5b22016-05-18 11:27:45 +01001054 if (!HasOnlySimpleElements(isolate, *receiver)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 return IterateElementsSlow(isolate, receiver, length, visitor);
1056 }
1057 Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1058
1059 switch (array->GetElementsKind()) {
1060 case FAST_SMI_ELEMENTS:
1061 case FAST_ELEMENTS:
1062 case FAST_HOLEY_SMI_ELEMENTS:
1063 case FAST_HOLEY_ELEMENTS: {
1064 // Run through the elements FixedArray and use HasElement and GetElement
1065 // to check the prototype for missing elements.
1066 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1067 int fast_length = static_cast<int>(length);
Ben Murdochda12d292016-06-02 14:46:10 +01001068 DCHECK(fast_length <= elements->length());
1069 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 Handle<Object> element_value(elements->get(j), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001071 if (!element_value->IsTheHole(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001072 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 } else {
1074 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1075 if (!maybe.IsJust()) return false;
1076 if (maybe.FromJust()) {
1077 // Call GetElement on array, not its prototype, or getters won't
1078 // have the correct receiver.
1079 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001080 isolate, element_value,
1081 JSReceiver::GetElement(isolate, array, j), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001082 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083 }
1084 }
Ben Murdochda12d292016-06-02 14:46:10 +01001085 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001086 break;
1087 }
1088 case FAST_HOLEY_DOUBLE_ELEMENTS:
1089 case FAST_DOUBLE_ELEMENTS: {
1090 // Empty array is FixedArray but not FixedDoubleArray.
1091 if (length == 0) break;
1092 // Run through the elements FixedArray and use HasElement and GetElement
1093 // to check the prototype for missing elements.
1094 if (array->elements()->IsFixedArray()) {
1095 DCHECK(array->elements()->length() == 0);
1096 break;
1097 }
1098 Handle<FixedDoubleArray> elements(
1099 FixedDoubleArray::cast(array->elements()));
1100 int fast_length = static_cast<int>(length);
1101 DCHECK(fast_length <= elements->length());
Ben Murdochda12d292016-06-02 14:46:10 +01001102 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 if (!elements->is_the_hole(j)) {
1104 double double_value = elements->get_scalar(j);
1105 Handle<Object> element_value =
1106 isolate->factory()->NewNumber(double_value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001107 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 } else {
1109 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1110 if (!maybe.IsJust()) return false;
1111 if (maybe.FromJust()) {
1112 // Call GetElement on array, not its prototype, or getters won't
1113 // have the correct receiver.
1114 Handle<Object> element_value;
1115 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001116 isolate, element_value,
1117 JSReceiver::GetElement(isolate, array, j), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001118 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 }
1120 }
Ben Murdochda12d292016-06-02 14:46:10 +01001121 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 break;
1123 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001124
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001125 case DICTIONARY_ELEMENTS: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1127 List<uint32_t> indices(dict->Capacity() / 2);
1128 // Collect all indices in the object and the prototypes less
1129 // than length. This might introduce duplicates in the indices list.
1130 CollectElementIndices(array, length, &indices);
1131 indices.Sort(&compareUInt32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001132 int n = indices.length();
Ben Murdochda12d292016-06-02 14:46:10 +01001133 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < n, (void)0, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134 uint32_t index = indices[j];
1135 Handle<Object> element;
1136 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001137 isolate, element, JSReceiver::GetElement(isolate, array, index),
1138 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001139 if (!visitor->visit(index, element)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 // Skip to next different index (i.e., omit duplicates).
1141 do {
1142 j++;
1143 } while (j < n && indices[j] == index);
Ben Murdochda12d292016-06-02 14:46:10 +01001144 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001145 break;
1146 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1148 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001149 FOR_WITH_HANDLE_SCOPE(
1150 isolate, uint32_t, index = 0, index, index < length, index++, {
1151 Handle<Object> element;
1152 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1153 isolate, element, JSReceiver::GetElement(isolate, array, index),
1154 false);
1155 if (!visitor->visit(index, element)) return false;
1156 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157 break;
1158 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001159 case NO_ELEMENTS:
1160 break;
1161#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1162 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1163#undef TYPED_ARRAY_CASE
1164 return IterateElementsSlow(isolate, receiver, length, visitor);
1165 case FAST_STRING_WRAPPER_ELEMENTS:
1166 case SLOW_STRING_WRAPPER_ELEMENTS:
1167 // |array| is guaranteed to be an array or typed array.
1168 UNREACHABLE();
1169 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001170 }
1171 visitor->increase_index_offset(length);
1172 return true;
1173}
1174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1176 HandleScope handle_scope(isolate);
1177 if (!obj->IsJSReceiver()) return Just(false);
Ben Murdochc5610432016-08-08 18:44:38 +01001178 if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1179 // Slow path if @@isConcatSpreadable has been used.
1180 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1181 Handle<Object> value;
1182 MaybeHandle<Object> maybeValue =
1183 i::Runtime::GetObjectProperty(isolate, obj, key);
1184 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001185 if (!value->IsUndefined(isolate)) return Just(value->BooleanValue());
Ben Murdochc5610432016-08-08 18:44:38 +01001186 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 return Object::IsArray(obj);
1188}
1189
Ben Murdoch61f157c2016-09-16 13:49:30 +01001190Object* Slow_ArrayConcat(BuiltinArguments* args, Handle<Object> species,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001191 Isolate* isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 int argument_count = args->length();
1193
Ben Murdoch097c5b22016-05-18 11:27:45 +01001194 bool is_array_species = *species == isolate->context()->array_function();
1195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 // Pass 1: estimate the length and number of elements of the result.
1197 // The actual length can be larger if any of the arguments have getters
1198 // that mutate other arguments (but will otherwise be precise).
1199 // The number of elements is precise if there are no inherited elements.
1200
1201 ElementsKind kind = FAST_SMI_ELEMENTS;
1202
1203 uint32_t estimate_result_length = 0;
1204 uint32_t estimate_nof_elements = 0;
Ben Murdochda12d292016-06-02 14:46:10 +01001205 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < argument_count, i++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 Handle<Object> obj((*args)[i], isolate);
1207 uint32_t length_estimate;
1208 uint32_t element_estimate;
1209 if (obj->IsJSArray()) {
1210 Handle<JSArray> array(Handle<JSArray>::cast(obj));
1211 length_estimate = static_cast<uint32_t>(array->length()->Number());
1212 if (length_estimate != 0) {
1213 ElementsKind array_kind =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001214 GetPackedElementsKind(array->GetElementsKind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 kind = GetMoreGeneralElementsKind(kind, array_kind);
1216 }
1217 element_estimate = EstimateElementCount(array);
1218 } else {
1219 if (obj->IsHeapObject()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001220 kind = GetMoreGeneralElementsKind(
1221 kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001222 }
1223 length_estimate = 1;
1224 element_estimate = 1;
1225 }
1226 // Avoid overflows by capping at kMaxElementCount.
1227 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1228 estimate_result_length = JSObject::kMaxElementCount;
1229 } else {
1230 estimate_result_length += length_estimate;
1231 }
1232 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1233 estimate_nof_elements = JSObject::kMaxElementCount;
1234 } else {
1235 estimate_nof_elements += element_estimate;
1236 }
Ben Murdochda12d292016-06-02 14:46:10 +01001237 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238
1239 // If estimated number of elements is more than half of length, a
1240 // fixed array (fast case) is more time and space-efficient than a
1241 // dictionary.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001242 bool fast_case =
1243 is_array_species && (estimate_nof_elements * 2) >= estimate_result_length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001244
1245 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1246 Handle<FixedArrayBase> storage =
1247 isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1248 int j = 0;
1249 bool failure = false;
1250 if (estimate_result_length > 0) {
1251 Handle<FixedDoubleArray> double_storage =
1252 Handle<FixedDoubleArray>::cast(storage);
1253 for (int i = 0; i < argument_count; i++) {
1254 Handle<Object> obj((*args)[i], isolate);
1255 if (obj->IsSmi()) {
1256 double_storage->set(j, Smi::cast(*obj)->value());
1257 j++;
1258 } else if (obj->IsNumber()) {
1259 double_storage->set(j, obj->Number());
1260 j++;
1261 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001262 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263 JSArray* array = JSArray::cast(*obj);
1264 uint32_t length = static_cast<uint32_t>(array->length()->Number());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001265 switch (array->GetElementsKind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001266 case FAST_HOLEY_DOUBLE_ELEMENTS:
1267 case FAST_DOUBLE_ELEMENTS: {
1268 // Empty array is FixedArray but not FixedDoubleArray.
1269 if (length == 0) break;
1270 FixedDoubleArray* elements =
1271 FixedDoubleArray::cast(array->elements());
1272 for (uint32_t i = 0; i < length; i++) {
1273 if (elements->is_the_hole(i)) {
1274 // TODO(jkummerow/verwaest): We could be a bit more clever
1275 // here: Check if there are no elements/getters on the
1276 // prototype chain, and if so, allow creation of a holey
1277 // result array.
1278 // Same thing below (holey smi case).
1279 failure = true;
1280 break;
1281 }
1282 double double_value = elements->get_scalar(i);
1283 double_storage->set(j, double_value);
1284 j++;
1285 }
1286 break;
1287 }
1288 case FAST_HOLEY_SMI_ELEMENTS:
1289 case FAST_SMI_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001290 Object* the_hole = isolate->heap()->the_hole_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 FixedArray* elements(FixedArray::cast(array->elements()));
1292 for (uint32_t i = 0; i < length; i++) {
1293 Object* element = elements->get(i);
Ben Murdochda12d292016-06-02 14:46:10 +01001294 if (element == the_hole) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001295 failure = true;
1296 break;
1297 }
1298 int32_t int_value = Smi::cast(element)->value();
1299 double_storage->set(j, int_value);
1300 j++;
1301 }
1302 break;
1303 }
1304 case FAST_HOLEY_ELEMENTS:
1305 case FAST_ELEMENTS:
1306 case DICTIONARY_ELEMENTS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001307 case NO_ELEMENTS:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001308 DCHECK_EQ(0u, length);
1309 break;
1310 default:
1311 UNREACHABLE();
1312 }
1313 }
1314 if (failure) break;
1315 }
1316 }
1317 if (!failure) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001318 return *isolate->factory()->NewJSArrayWithElements(storage, kind, j);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319 }
1320 // In case of failure, fall through.
1321 }
1322
Ben Murdoch097c5b22016-05-18 11:27:45 +01001323 Handle<Object> storage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001324 if (fast_case) {
1325 // The backing storage array must have non-existing elements to preserve
1326 // holes across concat operations.
1327 storage =
1328 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001329 } else if (is_array_species) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001330 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1331 uint32_t at_least_space_for =
1332 estimate_nof_elements + (estimate_nof_elements >> 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001333 storage = SeededNumberDictionary::New(isolate, at_least_space_for);
1334 } else {
1335 DCHECK(species->IsConstructor());
1336 Handle<Object> length(Smi::FromInt(0), isolate);
1337 Handle<Object> storage_object;
1338 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1339 isolate, storage_object,
1340 Execution::New(isolate, species, species, 1, &length));
1341 storage = storage_object;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001342 }
1343
1344 ArrayConcatVisitor visitor(isolate, storage, fast_case);
1345
1346 for (int i = 0; i < argument_count; i++) {
1347 Handle<Object> obj((*args)[i], isolate);
1348 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1349 MAYBE_RETURN(spreadable, isolate->heap()->exception());
1350 if (spreadable.FromJust()) {
1351 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1352 if (!IterateElements(isolate, object, &visitor)) {
1353 return isolate->heap()->exception();
1354 }
1355 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001356 if (!visitor.visit(0, obj)) return isolate->heap()->exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001357 visitor.increase_index_offset(1);
1358 }
1359 }
1360
1361 if (visitor.exceeds_array_limit()) {
1362 THROW_NEW_ERROR_RETURN_FAILURE(
1363 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1364 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001365
1366 if (is_array_species) {
1367 return *visitor.ToArray();
1368 } else {
1369 return *visitor.storage_jsreceiver();
1370 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001371}
1372
Ben Murdochc5610432016-08-08 18:44:38 +01001373bool IsSimpleArray(Isolate* isolate, Handle<JSArray> obj) {
1374 DisallowHeapAllocation no_gc;
1375 Map* map = obj->map();
1376 // If there is only the 'length' property we are fine.
1377 if (map->prototype() ==
1378 isolate->native_context()->initial_array_prototype() &&
1379 map->NumberOfOwnDescriptors() == 1) {
1380 return true;
1381 }
1382 // TODO(cbruni): slower lookup for array subclasses and support slow
1383 // @@IsConcatSpreadable lookup.
1384 return false;
1385}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386
Ben Murdoch61f157c2016-09-16 13:49:30 +01001387MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate,
1388 BuiltinArguments* args) {
Ben Murdochc5610432016-08-08 18:44:38 +01001389 if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1390 return MaybeHandle<JSArray>();
1391 }
Ben Murdochda12d292016-06-02 14:46:10 +01001392 // We shouldn't overflow when adding another len.
1393 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1394 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1395 STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt);
1396 USE(kHalfOfMaxInt);
1397
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001398 int n_arguments = args->length();
Steve Block6ded16b2010-05-10 14:33:55 +01001399 int result_len = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400 {
1401 DisallowHeapAllocation no_gc;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001402 // Iterate through all the arguments performing checks
1403 // and calculating total length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001404 for (int i = 0; i < n_arguments; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001405 Object* arg = (*args)[i];
1406 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
Ben Murdochda12d292016-06-02 14:46:10 +01001407 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001408 return MaybeHandle<JSArray>();
1409 }
Ben Murdochc5610432016-08-08 18:44:38 +01001410 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1411 if (!JSObject::cast(arg)->HasFastElements()) {
1412 return MaybeHandle<JSArray>();
1413 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 Handle<JSArray> array(JSArray::cast(arg), isolate);
Ben Murdochc5610432016-08-08 18:44:38 +01001415 if (!IsSimpleArray(isolate, array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 return MaybeHandle<JSArray>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417 }
Ben Murdochda12d292016-06-02 14:46:10 +01001418 // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't
1419 // overflow.
1420 result_len += Smi::cast(array->length())->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 DCHECK(result_len >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 // Throw an Error if we overflow the FixedArray limits
Ben Murdoch61f157c2016-09-16 13:49:30 +01001423 if (FixedDoubleArray::kMaxLength < result_len ||
1424 FixedArray::kMaxLength < result_len) {
Ben Murdochc5610432016-08-08 18:44:38 +01001425 AllowHeapAllocation gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001426 THROW_NEW_ERROR(isolate,
1427 NewRangeError(MessageTemplate::kInvalidArrayLength),
1428 JSArray);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001429 }
Steve Block6ded16b2010-05-10 14:33:55 +01001430 }
Steve Block6ded16b2010-05-10 14:33:55 +01001431 }
Ben Murdochc5610432016-08-08 18:44:38 +01001432 return ElementsAccessor::Concat(isolate, args, n_arguments, result_len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001433}
Steve Block6ded16b2010-05-10 14:33:55 +01001434
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435} // namespace
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001436
Ben Murdoch097c5b22016-05-18 11:27:45 +01001437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438// ES6 22.1.3.1 Array.prototype.concat
1439BUILTIN(ArrayConcat) {
1440 HandleScope scope(isolate);
1441
Ben Murdoch097c5b22016-05-18 11:27:45 +01001442 Handle<Object> receiver = args.receiver();
1443 // TODO(bmeurer): Do we really care about the exact exception message here?
Ben Murdoch61f157c2016-09-16 13:49:30 +01001444 if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001445 THROW_NEW_ERROR_RETURN_FAILURE(
1446 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1447 isolate->factory()->NewStringFromAsciiChecked(
1448 "Array.prototype.concat")));
1449 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001450 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1451 isolate, receiver, Object::ToObject(isolate, args.receiver()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452 args[0] = *receiver;
1453
1454 Handle<JSArray> result_array;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001455
Ben Murdochda12d292016-06-02 14:46:10 +01001456 // Avoid a real species read to avoid extra lookups to the array constructor
1457 if (V8_LIKELY(receiver->IsJSArray() &&
1458 Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) &&
1459 isolate->IsArraySpeciesLookupChainIntact())) {
1460 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1461 return *result_array;
1462 }
1463 if (isolate->has_pending_exception()) return isolate->heap()->exception();
1464 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001465 // Reading @@species happens before anything else with a side effect, so
1466 // we can do it here to determine whether to take the fast path.
1467 Handle<Object> species;
1468 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1469 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
Ben Murdochda12d292016-06-02 14:46:10 +01001470 if (*species == *isolate->array_function()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001471 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1472 return *result_array;
1473 }
1474 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001476 return Slow_ArrayConcat(&args, species, isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477}
1478
1479
Ben Murdoch097c5b22016-05-18 11:27:45 +01001480namespace {
1481
1482MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
1483 Handle<Object> next_source) {
1484 // Non-empty strings are the only non-JSReceivers that need to be handled
1485 // explicitly by Object.assign.
1486 if (!next_source->IsJSReceiver()) {
1487 return Just(!next_source->IsString() ||
1488 String::cast(*next_source)->length() == 0);
1489 }
1490
Ben Murdochc5610432016-08-08 18:44:38 +01001491 // If the target is deprecated, the object will be updated on first store. If
1492 // the source for that store equals the target, this will invalidate the
1493 // cached representation of the source. Preventively upgrade the target.
1494 // Do this on each iteration since any property load could cause deprecation.
1495 if (to->map()->is_deprecated()) {
1496 JSObject::MigrateInstance(Handle<JSObject>::cast(to));
1497 }
1498
Ben Murdoch097c5b22016-05-18 11:27:45 +01001499 Isolate* isolate = to->GetIsolate();
1500 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
1501
1502 if (!map->IsJSObjectMap()) return Just(false);
1503 if (!map->OnlyHasSimpleProperties()) return Just(false);
1504
1505 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
1506 if (from->elements() != isolate->heap()->empty_fixed_array()) {
1507 return Just(false);
1508 }
1509
1510 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
1511 int length = map->NumberOfOwnDescriptors();
1512
1513 bool stable = true;
1514
1515 for (int i = 0; i < length; i++) {
1516 Handle<Name> next_key(descriptors->GetKey(i), isolate);
1517 Handle<Object> prop_value;
1518 // Directly decode from the descriptor array if |from| did not change shape.
1519 if (stable) {
1520 PropertyDetails details = descriptors->GetDetails(i);
1521 if (!details.IsEnumerable()) continue;
1522 if (details.kind() == kData) {
1523 if (details.location() == kDescriptor) {
1524 prop_value = handle(descriptors->GetValue(i), isolate);
1525 } else {
1526 Representation representation = details.representation();
1527 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
1528 prop_value = JSObject::FastPropertyAt(from, representation, index);
1529 }
1530 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001531 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1532 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
1533 Nothing<bool>());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001534 stable = from->map() == *map;
1535 }
1536 } else {
1537 // If the map did change, do a slower lookup. We are still guaranteed that
1538 // the object has a simple shape, and that the key is a name.
Ben Murdochda12d292016-06-02 14:46:10 +01001539 LookupIterator it(from, next_key, from,
1540 LookupIterator::OWN_SKIP_INTERCEPTOR);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001541 if (!it.IsFound()) continue;
1542 DCHECK(it.state() == LookupIterator::DATA ||
1543 it.state() == LookupIterator::ACCESSOR);
1544 if (!it.IsEnumerable()) continue;
1545 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1546 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
1547 }
Ben Murdochda12d292016-06-02 14:46:10 +01001548 LookupIterator it(to, next_key, to);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001549 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
1550 Maybe<bool> result = Object::SetProperty(
1551 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
1552 if (result.IsNothing()) return result;
1553 if (stable && call_to_js) stable = from->map() == *map;
1554 }
1555
1556 return Just(true);
1557}
1558
1559} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560
1561// ES6 19.1.2.1 Object.assign
1562BUILTIN(ObjectAssign) {
1563 HandleScope scope(isolate);
1564 Handle<Object> target = args.atOrUndefined(isolate, 1);
1565
1566 // 1. Let to be ? ToObject(target).
1567 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001568 Object::ToObject(isolate, target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
1570 // 2. If only one argument was passed, return to.
1571 if (args.length() == 2) return *to;
1572 // 3. Let sources be the List of argument values starting with the
1573 // second argument.
1574 // 4. For each element nextSource of sources, in ascending index order,
1575 for (int i = 2; i < args.length(); ++i) {
1576 Handle<Object> next_source = args.at<Object>(i);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001577 Maybe<bool> fast_assign = FastAssign(to, next_source);
1578 if (fast_assign.IsNothing()) return isolate->heap()->exception();
1579 if (fast_assign.FromJust()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580 // 4a. If nextSource is undefined or null, let keys be an empty List.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001581 // 4b. Else,
1582 // 4b i. Let from be ToObject(nextSource).
Ben Murdoch097c5b22016-05-18 11:27:45 +01001583 // Only non-empty strings and JSReceivers have enumerable properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 Handle<JSReceiver> from =
1585 Object::ToObject(isolate, next_source).ToHandleChecked();
1586 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
1587 Handle<FixedArray> keys;
1588 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch61f157c2016-09-16 13:49:30 +01001589 isolate, keys, KeyAccumulator::GetKeys(
1590 from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
1591 GetKeysConversion::kKeepNumbers));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001592 // 4c. Repeat for each element nextKey of keys in List order,
1593 for (int j = 0; j < keys->length(); ++j) {
1594 Handle<Object> next_key(keys->get(j), isolate);
1595 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
1596 PropertyDescriptor desc;
1597 Maybe<bool> found =
1598 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
1599 if (found.IsNothing()) return isolate->heap()->exception();
1600 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
1601 if (found.FromJust() && desc.enumerable()) {
1602 // 4c ii 1. Let propValue be ? Get(from, nextKey).
1603 Handle<Object> prop_value;
1604 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1605 isolate, prop_value,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001606 Runtime::GetObjectProperty(isolate, from, next_key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001607 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
1608 Handle<Object> status;
1609 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1610 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
1611 prop_value, STRICT));
1612 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 }
Steve Block6ded16b2010-05-10 14:33:55 +01001614 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001615 // 5. Return to.
1616 return *to;
1617}
Steve Block6ded16b2010-05-10 14:33:55 +01001618
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001620// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
Ben Murdoch61f157c2016-09-16 13:49:30 +01001621// TODO(verwaest): Support the common cases with precached map directly in
1622// an Object.create stub.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001623BUILTIN(ObjectCreate) {
1624 HandleScope scope(isolate);
1625 Handle<Object> prototype = args.atOrUndefined(isolate, 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001626 if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001627 THROW_NEW_ERROR_RETURN_FAILURE(
1628 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
1629 }
1630
1631 // Generate the map with the specified {prototype} based on the Object
1632 // function's initial map from the current native context.
1633 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1634 // slack tracking for Object.create.
1635 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
1636 isolate);
1637 if (map->prototype() != *prototype) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001638 if (prototype->IsNull(isolate)) {
1639 map = isolate->object_with_null_prototype_map();
1640 } else if (prototype->IsJSObject()) {
1641 Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
1642 if (!js_prototype->map()->is_prototype_map()) {
1643 JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
1644 }
1645 Handle<PrototypeInfo> info =
1646 Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
1647 // TODO(verwaest): Use inobject slack tracking for this map.
1648 if (info->HasObjectCreateMap()) {
1649 map = handle(info->ObjectCreateMap(), isolate);
1650 } else {
1651 map = Map::CopyInitialMap(map);
1652 Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
1653 PrototypeInfo::SetObjectCreateMap(info, map);
1654 }
1655 } else {
1656 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
1657 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001658 }
1659
1660 // Actually allocate the object.
1661 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
1662
1663 // Define the properties if properties was specified and is not undefined.
1664 Handle<Object> properties = args.atOrUndefined(isolate, 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001665 if (!properties->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 RETURN_FAILURE_ON_EXCEPTION(
1667 isolate, JSReceiver::DefineProperties(isolate, object, properties));
1668 }
1669
1670 return *object;
1671}
1672
Ben Murdochc5610432016-08-08 18:44:38 +01001673// ES6 section 19.1.2.3 Object.defineProperties
1674BUILTIN(ObjectDefineProperties) {
1675 HandleScope scope(isolate);
1676 DCHECK_EQ(3, args.length());
1677 Handle<Object> target = args.at<Object>(1);
1678 Handle<Object> properties = args.at<Object>(2);
1679
Ben Murdoch61f157c2016-09-16 13:49:30 +01001680 RETURN_RESULT_OR_FAILURE(
1681 isolate, JSReceiver::DefineProperties(isolate, target, properties));
Ben Murdochc5610432016-08-08 18:44:38 +01001682}
1683
1684// ES6 section 19.1.2.4 Object.defineProperty
1685BUILTIN(ObjectDefineProperty) {
1686 HandleScope scope(isolate);
1687 DCHECK_EQ(4, args.length());
1688 Handle<Object> target = args.at<Object>(1);
1689 Handle<Object> key = args.at<Object>(2);
1690 Handle<Object> attributes = args.at<Object>(3);
1691
1692 return JSReceiver::DefineProperty(isolate, target, key, attributes);
1693}
1694
1695namespace {
1696
1697template <AccessorComponent which_accessor>
1698Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
1699 Handle<Object> name, Handle<Object> accessor) {
1700 // 1. Let O be ? ToObject(this value).
1701 Handle<JSReceiver> receiver;
1702 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1703 Object::ConvertReceiver(isolate, object));
1704 // 2. If IsCallable(getter) is false, throw a TypeError exception.
1705 if (!accessor->IsCallable()) {
1706 MessageTemplate::Template message =
1707 which_accessor == ACCESSOR_GETTER
1708 ? MessageTemplate::kObjectGetterExpectingFunction
1709 : MessageTemplate::kObjectSetterExpectingFunction;
1710 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
1711 }
1712 // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
1713 // [[Configurable]]: true}.
1714 PropertyDescriptor desc;
1715 if (which_accessor == ACCESSOR_GETTER) {
1716 desc.set_get(accessor);
1717 } else {
1718 DCHECK(which_accessor == ACCESSOR_SETTER);
1719 desc.set_set(accessor);
1720 }
1721 desc.set_enumerable(true);
1722 desc.set_configurable(true);
1723 // 4. Let key be ? ToPropertyKey(P).
1724 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1725 Object::ToPropertyKey(isolate, name));
1726 // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
1727 // To preserve legacy behavior, we ignore errors silently rather than
1728 // throwing an exception.
1729 Maybe<bool> success = JSReceiver::DefineOwnProperty(
1730 isolate, receiver, name, &desc, Object::DONT_THROW);
1731 MAYBE_RETURN(success, isolate->heap()->exception());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001732 if (!success.FromJust()) {
1733 isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
1734 }
Ben Murdochc5610432016-08-08 18:44:38 +01001735 // 6. Return undefined.
1736 return isolate->heap()->undefined_value();
1737}
1738
1739Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
1740 Handle<Object> key, AccessorComponent component) {
1741 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
1742 Object::ConvertReceiver(isolate, object));
1743 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1744 Object::ToPropertyKey(isolate, key));
1745 bool success = false;
1746 LookupIterator it = LookupIterator::PropertyOrElement(
1747 isolate, object, key, &success,
1748 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
1749 DCHECK(success);
1750
1751 for (; it.IsFound(); it.Next()) {
1752 switch (it.state()) {
1753 case LookupIterator::INTERCEPTOR:
1754 case LookupIterator::NOT_FOUND:
1755 case LookupIterator::TRANSITION:
1756 UNREACHABLE();
1757
1758 case LookupIterator::ACCESS_CHECK:
1759 if (it.HasAccess()) continue;
1760 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
1761 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1762 return isolate->heap()->undefined_value();
1763
1764 case LookupIterator::JSPROXY:
1765 return isolate->heap()->undefined_value();
1766
1767 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1768 return isolate->heap()->undefined_value();
1769 case LookupIterator::DATA:
1770 continue;
1771 case LookupIterator::ACCESSOR: {
1772 Handle<Object> maybe_pair = it.GetAccessors();
1773 if (maybe_pair->IsAccessorPair()) {
1774 return *AccessorPair::GetComponent(
1775 Handle<AccessorPair>::cast(maybe_pair), component);
1776 }
1777 }
1778 }
1779 }
1780
1781 return isolate->heap()->undefined_value();
1782}
1783
1784} // namespace
1785
1786// ES6 B.2.2.2 a.k.a.
1787// https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
1788BUILTIN(ObjectDefineGetter) {
1789 HandleScope scope(isolate);
1790 Handle<Object> object = args.at<Object>(0); // Receiver.
1791 Handle<Object> name = args.at<Object>(1);
1792 Handle<Object> getter = args.at<Object>(2);
1793 return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
1794}
1795
1796// ES6 B.2.2.3 a.k.a.
1797// https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
1798BUILTIN(ObjectDefineSetter) {
1799 HandleScope scope(isolate);
1800 Handle<Object> object = args.at<Object>(0); // Receiver.
1801 Handle<Object> name = args.at<Object>(1);
1802 Handle<Object> setter = args.at<Object>(2);
1803 return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
1804}
1805
1806// ES6 B.2.2.4 a.k.a.
1807// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
1808BUILTIN(ObjectLookupGetter) {
1809 HandleScope scope(isolate);
1810 Handle<Object> object = args.at<Object>(0);
1811 Handle<Object> name = args.at<Object>(1);
1812 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
1813}
1814
1815// ES6 B.2.2.5 a.k.a.
1816// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
1817BUILTIN(ObjectLookupSetter) {
1818 HandleScope scope(isolate);
1819 Handle<Object> object = args.at<Object>(0);
1820 Handle<Object> name = args.at<Object>(1);
1821 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
1822}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001823
1824// ES6 section 19.1.2.5 Object.freeze ( O )
1825BUILTIN(ObjectFreeze) {
1826 HandleScope scope(isolate);
1827 Handle<Object> object = args.atOrUndefined(isolate, 1);
1828 if (object->IsJSReceiver()) {
1829 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1830 FROZEN, Object::THROW_ON_ERROR),
1831 isolate->heap()->exception());
1832 }
1833 return *object;
1834}
1835
1836
Ben Murdochc5610432016-08-08 18:44:38 +01001837// ES section 19.1.2.9 Object.getPrototypeOf ( O )
1838BUILTIN(ObjectGetPrototypeOf) {
1839 HandleScope scope(isolate);
1840 Handle<Object> object = args.atOrUndefined(isolate, 1);
1841
1842 Handle<JSReceiver> receiver;
1843 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1844 isolate, receiver, Object::ToObject(isolate, object));
1845
Ben Murdoch61f157c2016-09-16 13:49:30 +01001846 RETURN_RESULT_OR_FAILURE(isolate,
1847 JSReceiver::GetPrototype(isolate, receiver));
Ben Murdochc5610432016-08-08 18:44:38 +01001848}
1849
1850
Ben Murdoch097c5b22016-05-18 11:27:45 +01001851// ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
1852BUILTIN(ObjectGetOwnPropertyDescriptor) {
1853 HandleScope scope(isolate);
1854 // 1. Let obj be ? ToObject(O).
1855 Handle<Object> object = args.atOrUndefined(isolate, 1);
1856 Handle<JSReceiver> receiver;
1857 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1858 Object::ToObject(isolate, object));
1859 // 2. Let key be ? ToPropertyKey(P).
1860 Handle<Object> property = args.atOrUndefined(isolate, 2);
1861 Handle<Name> key;
1862 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1863 Object::ToName(isolate, property));
1864 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
1865 PropertyDescriptor desc;
1866 Maybe<bool> found =
1867 JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
1868 MAYBE_RETURN(found, isolate->heap()->exception());
1869 // 4. Return FromPropertyDescriptor(desc).
1870 if (!found.FromJust()) return isolate->heap()->undefined_value();
1871 return *desc.ToObject(isolate);
1872}
1873
1874
1875namespace {
1876
Ben Murdoch61f157c2016-09-16 13:49:30 +01001877Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001878 PropertyFilter filter) {
1879 HandleScope scope(isolate);
1880 Handle<Object> object = args.atOrUndefined(isolate, 1);
1881 Handle<JSReceiver> receiver;
1882 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1883 Object::ToObject(isolate, object));
1884 Handle<FixedArray> keys;
1885 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1886 isolate, keys,
Ben Murdoch61f157c2016-09-16 13:49:30 +01001887 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
1888 GetKeysConversion::kConvertToString));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001889 return *isolate->factory()->NewJSArrayWithElements(keys);
1890}
1891
1892} // namespace
1893
1894
1895// ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
1896BUILTIN(ObjectGetOwnPropertyNames) {
1897 return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
1898}
1899
1900
1901// ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
1902BUILTIN(ObjectGetOwnPropertySymbols) {
1903 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
1904}
1905
1906
1907// ES#sec-object.is Object.is ( value1, value2 )
1908BUILTIN(ObjectIs) {
1909 SealHandleScope shs(isolate);
1910 DCHECK_EQ(3, args.length());
1911 Handle<Object> value1 = args.at<Object>(1);
1912 Handle<Object> value2 = args.at<Object>(2);
1913 return isolate->heap()->ToBoolean(value1->SameValue(*value2));
1914}
1915
1916
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001917// ES6 section 19.1.2.11 Object.isExtensible ( O )
1918BUILTIN(ObjectIsExtensible) {
1919 HandleScope scope(isolate);
1920 Handle<Object> object = args.atOrUndefined(isolate, 1);
1921 Maybe<bool> result =
1922 object->IsJSReceiver()
1923 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
1924 : Just(false);
1925 MAYBE_RETURN(result, isolate->heap()->exception());
1926 return isolate->heap()->ToBoolean(result.FromJust());
1927}
1928
1929
1930// ES6 section 19.1.2.12 Object.isFrozen ( O )
1931BUILTIN(ObjectIsFrozen) {
1932 HandleScope scope(isolate);
1933 Handle<Object> object = args.atOrUndefined(isolate, 1);
1934 Maybe<bool> result = object->IsJSReceiver()
1935 ? JSReceiver::TestIntegrityLevel(
1936 Handle<JSReceiver>::cast(object), FROZEN)
1937 : Just(true);
1938 MAYBE_RETURN(result, isolate->heap()->exception());
1939 return isolate->heap()->ToBoolean(result.FromJust());
1940}
1941
1942
1943// ES6 section 19.1.2.13 Object.isSealed ( O )
1944BUILTIN(ObjectIsSealed) {
1945 HandleScope scope(isolate);
1946 Handle<Object> object = args.atOrUndefined(isolate, 1);
1947 Maybe<bool> result = object->IsJSReceiver()
1948 ? JSReceiver::TestIntegrityLevel(
1949 Handle<JSReceiver>::cast(object), SEALED)
1950 : Just(true);
1951 MAYBE_RETURN(result, isolate->heap()->exception());
1952 return isolate->heap()->ToBoolean(result.FromJust());
1953}
1954
1955
1956// ES6 section 19.1.2.14 Object.keys ( O )
1957BUILTIN(ObjectKeys) {
1958 HandleScope scope(isolate);
1959 Handle<Object> object = args.atOrUndefined(isolate, 1);
1960 Handle<JSReceiver> receiver;
1961 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001962 Object::ToObject(isolate, object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001963
Ben Murdoch097c5b22016-05-18 11:27:45 +01001964 Handle<FixedArray> keys;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001965 int enum_length = receiver->map()->EnumLength();
1966 if (enum_length != kInvalidEnumCacheSentinel &&
1967 JSObject::cast(*receiver)->elements() ==
1968 isolate->heap()->empty_fixed_array()) {
1969 DCHECK(receiver->IsJSObject());
1970 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
1971 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001972 DCHECK(!receiver->map()->has_hidden_prototype());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001973 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
1974 if (enum_length == 0) {
1975 keys = isolate->factory()->empty_fixed_array();
1976 } else {
1977 Handle<FixedArray> cache(
1978 receiver->map()->instance_descriptors()->GetEnumCache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001979 keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001980 }
1981 } else {
1982 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1983 isolate, keys,
Ben Murdoch61f157c2016-09-16 13:49:30 +01001984 KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
1985 ENUMERABLE_STRINGS,
1986 GetKeysConversion::kConvertToString));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001987 }
1988 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
1989}
1990
Ben Murdoch097c5b22016-05-18 11:27:45 +01001991BUILTIN(ObjectValues) {
1992 HandleScope scope(isolate);
1993 Handle<Object> object = args.atOrUndefined(isolate, 1);
1994 Handle<JSReceiver> receiver;
1995 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1996 Object::ToObject(isolate, object));
1997 Handle<FixedArray> values;
1998 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1999 isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
2000 return *isolate->factory()->NewJSArrayWithElements(values);
2001}
2002
2003
2004BUILTIN(ObjectEntries) {
2005 HandleScope scope(isolate);
2006 Handle<Object> object = args.atOrUndefined(isolate, 1);
2007 Handle<JSReceiver> receiver;
2008 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
2009 Object::ToObject(isolate, object));
2010 Handle<FixedArray> entries;
2011 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2012 isolate, entries,
2013 JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
2014 return *isolate->factory()->NewJSArrayWithElements(entries);
2015}
2016
2017BUILTIN(ObjectGetOwnPropertyDescriptors) {
2018 HandleScope scope(isolate);
2019 Handle<Object> object = args.atOrUndefined(isolate, 1);
2020 Handle<Object> undefined = isolate->factory()->undefined_value();
2021
2022 Handle<JSReceiver> receiver;
2023 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
2024 Object::ToObject(isolate, object));
2025
2026 Handle<FixedArray> keys;
2027 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch61f157c2016-09-16 13:49:30 +01002028 isolate, keys, KeyAccumulator::GetKeys(
2029 receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2030 GetKeysConversion::kConvertToString));
Ben Murdoch097c5b22016-05-18 11:27:45 +01002031
Ben Murdochda12d292016-06-02 14:46:10 +01002032 Handle<JSObject> descriptors =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002033 isolate->factory()->NewJSObject(isolate->object_function());
2034
2035 for (int i = 0; i < keys->length(); ++i) {
2036 Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
2037 PropertyDescriptor descriptor;
2038 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
2039 isolate, receiver, key, &descriptor);
2040 MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
2041
2042 Handle<Object> from_descriptor = did_get_descriptor.FromJust()
2043 ? descriptor.ToObject(isolate)
2044 : undefined;
2045
2046 LookupIterator it = LookupIterator::PropertyOrElement(
Ben Murdochda12d292016-06-02 14:46:10 +01002047 isolate, descriptors, key, descriptors, LookupIterator::OWN);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002048 Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
2049 Object::DONT_THROW);
2050 CHECK(success.FromJust());
2051 }
2052
2053 return *descriptors;
2054}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002055
2056// ES6 section 19.1.2.15 Object.preventExtensions ( O )
2057BUILTIN(ObjectPreventExtensions) {
2058 HandleScope scope(isolate);
2059 Handle<Object> object = args.atOrUndefined(isolate, 1);
2060 if (object->IsJSReceiver()) {
2061 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
2062 Object::THROW_ON_ERROR),
2063 isolate->heap()->exception());
2064 }
2065 return *object;
2066}
2067
2068
2069// ES6 section 19.1.2.17 Object.seal ( O )
2070BUILTIN(ObjectSeal) {
2071 HandleScope scope(isolate);
2072 Handle<Object> object = args.atOrUndefined(isolate, 1);
2073 if (object->IsJSReceiver()) {
2074 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
2075 SEALED, Object::THROW_ON_ERROR),
2076 isolate->heap()->exception());
2077 }
2078 return *object;
2079}
2080
Ben Murdoch61f157c2016-09-16 13:49:30 +01002081// ES6 section 18.2.6.2 decodeURI (encodedURI)
2082BUILTIN(GlobalDecodeURI) {
2083 HandleScope scope(isolate);
2084 Handle<String> encoded_uri;
2085 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2086 isolate, encoded_uri,
2087 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2088
2089 RETURN_RESULT_OR_FAILURE(isolate, Uri::DecodeUri(isolate, encoded_uri));
2090}
2091
2092// ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent)
2093BUILTIN(GlobalDecodeURIComponent) {
2094 HandleScope scope(isolate);
2095 Handle<String> encoded_uri_component;
2096 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2097 isolate, encoded_uri_component,
2098 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2099
2100 RETURN_RESULT_OR_FAILURE(
2101 isolate, Uri::DecodeUriComponent(isolate, encoded_uri_component));
2102}
2103
Ben Murdochc5610432016-08-08 18:44:38 +01002104// ES6 section 18.2.6.4 encodeURI (uri)
2105BUILTIN(GlobalEncodeURI) {
2106 HandleScope scope(isolate);
2107 Handle<String> uri;
2108 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2109 isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2110
Ben Murdoch61f157c2016-09-16 13:49:30 +01002111 RETURN_RESULT_OR_FAILURE(isolate, Uri::EncodeUri(isolate, uri));
Ben Murdochc5610432016-08-08 18:44:38 +01002112}
2113
2114// ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
2115BUILTIN(GlobalEncodeURIComponent) {
2116 HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002117 Handle<String> uri_component;
Ben Murdochc5610432016-08-08 18:44:38 +01002118 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch61f157c2016-09-16 13:49:30 +01002119 isolate, uri_component,
Ben Murdochc5610432016-08-08 18:44:38 +01002120 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2121
Ben Murdoch61f157c2016-09-16 13:49:30 +01002122 RETURN_RESULT_OR_FAILURE(isolate,
2123 Uri::EncodeUriComponent(isolate, uri_component));
2124}
2125
2126// ES6 section B.2.1.1 escape (string)
2127BUILTIN(GlobalEscape) {
2128 HandleScope scope(isolate);
2129 Handle<String> string;
2130 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2131 isolate, string,
2132 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2133
2134 RETURN_RESULT_OR_FAILURE(isolate, Uri::Escape(isolate, string));
2135}
2136
2137// ES6 section B.2.1.2 unescape (string)
2138BUILTIN(GlobalUnescape) {
2139 HandleScope scope(isolate);
2140 Handle<String> string;
2141 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2142 isolate, string,
2143 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2144
2145 RETURN_RESULT_OR_FAILURE(isolate, Uri::Unescape(isolate, string));
Ben Murdochc5610432016-08-08 18:44:38 +01002146}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002147
2148namespace {
2149
2150bool CodeGenerationFromStringsAllowed(Isolate* isolate,
2151 Handle<Context> context) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01002152 DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002153 // Check with callback if set.
2154 AllowCodeGenerationFromStringsCallback callback =
2155 isolate->allow_code_gen_callback();
2156 if (callback == NULL) {
2157 // No callback set and code generation disallowed.
2158 return false;
2159 } else {
2160 // Callback set. Let it decide if code generation is allowed.
2161 VMState<EXTERNAL> state(isolate);
2162 return callback(v8::Utils::ToLocal(context));
2163 }
2164}
2165
2166
2167MaybeHandle<JSFunction> CompileString(Handle<Context> context,
2168 Handle<String> source,
2169 ParseRestriction restriction) {
2170 Isolate* const isolate = context->GetIsolate();
2171 Handle<Context> native_context(context->native_context(), isolate);
2172
2173 // Check if native context allows code generation from
2174 // strings. Throw an exception if it doesn't.
Ben Murdoch61f157c2016-09-16 13:49:30 +01002175 if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002176 !CodeGenerationFromStringsAllowed(isolate, native_context)) {
2177 Handle<Object> error_message =
2178 native_context->ErrorMessageForCodeGenerationFromStrings();
2179 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
2180 error_message),
2181 JSFunction);
2182 }
2183
2184 // Compile source string in the native context.
Ben Murdochc5610432016-08-08 18:44:38 +01002185 int eval_scope_position = 0;
2186 int eval_position = RelocInfo::kNoPosition;
2187 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002188 return Compiler::GetFunctionFromEval(source, outer_info, native_context,
Ben Murdochc5610432016-08-08 18:44:38 +01002189 SLOPPY, restriction, eval_scope_position,
2190 eval_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002191}
2192
2193} // namespace
2194
2195
2196// ES6 section 18.2.1 eval (x)
2197BUILTIN(GlobalEval) {
2198 HandleScope scope(isolate);
2199 Handle<Object> x = args.atOrUndefined(isolate, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002200 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002201 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
2202 if (!x->IsString()) return *x;
2203 Handle<JSFunction> function;
2204 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2205 isolate, function,
2206 CompileString(handle(target->native_context(), isolate),
2207 Handle<String>::cast(x), NO_PARSE_RESTRICTION));
Ben Murdoch61f157c2016-09-16 13:49:30 +01002208 RETURN_RESULT_OR_FAILURE(
2209 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002210 Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002211}
2212
Ben Murdoch61f157c2016-09-16 13:49:30 +01002213// ES6 section 24.3.1 JSON.parse.
2214BUILTIN(JsonParse) {
2215 HandleScope scope(isolate);
2216 Handle<Object> source = args.atOrUndefined(isolate, 1);
2217 Handle<Object> reviver = args.atOrUndefined(isolate, 2);
2218 Handle<String> string;
2219 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
2220 Object::ToString(isolate, source));
2221 string = String::Flatten(string);
2222 RETURN_RESULT_OR_FAILURE(
2223 isolate, string->IsSeqOneByteString()
2224 ? JsonParser<true>::Parse(isolate, string, reviver)
2225 : JsonParser<false>::Parse(isolate, string, reviver));
2226}
2227
2228// ES6 section 24.3.2 JSON.stringify.
2229BUILTIN(JsonStringify) {
2230 HandleScope scope(isolate);
2231 JsonStringifier stringifier(isolate);
2232 Handle<Object> object = args.atOrUndefined(isolate, 1);
2233 Handle<Object> replacer = args.atOrUndefined(isolate, 2);
2234 Handle<Object> indent = args.atOrUndefined(isolate, 3);
2235 RETURN_RESULT_OR_FAILURE(isolate,
2236 stringifier.Stringify(object, replacer, indent));
2237}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002238
Ben Murdochda12d292016-06-02 14:46:10 +01002239// -----------------------------------------------------------------------------
2240// ES6 section 20.2.2 Function Properties of the Math Object
2241
2242
2243// ES6 section 20.2.2.2 Math.acos ( x )
2244BUILTIN(MathAcos) {
2245 HandleScope scope(isolate);
2246 DCHECK_EQ(2, args.length());
2247 Handle<Object> x = args.at<Object>(1);
2248 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2249 return *isolate->factory()->NewHeapNumber(std::acos(x->Number()));
2250}
2251
2252
2253// ES6 section 20.2.2.4 Math.asin ( x )
2254BUILTIN(MathAsin) {
2255 HandleScope scope(isolate);
2256 DCHECK_EQ(2, args.length());
2257 Handle<Object> x = args.at<Object>(1);
2258 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2259 return *isolate->factory()->NewHeapNumber(std::asin(x->Number()));
2260}
2261
Ben Murdochda12d292016-06-02 14:46:10 +01002262// ES6 section 20.2.2.6 Math.atan ( x )
Ben Murdoch61f157c2016-09-16 13:49:30 +01002263void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
2264 using compiler::Node;
2265
2266 Node* x = assembler->Parameter(1);
2267 Node* context = assembler->Parameter(4);
2268 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2269 Node* value = assembler->Float64Atan(x_value);
2270 Node* result = assembler->ChangeFloat64ToTagged(value);
2271 assembler->Return(result);
2272}
2273
2274// ES6 section 20.2.2.8 Math.atan2 ( y, x )
2275void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
2276 using compiler::Node;
2277
2278 Node* y = assembler->Parameter(1);
2279 Node* x = assembler->Parameter(2);
2280 Node* context = assembler->Parameter(5);
2281 Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
2282 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2283 Node* value = assembler->Float64Atan2(y_value, x_value);
2284 Node* result = assembler->ChangeFloat64ToTagged(value);
2285 assembler->Return(result);
2286}
2287
2288// ES6 section 20.2.2.7 Math.atanh ( x )
2289void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
2290 using compiler::Node;
2291
2292 Node* x = assembler->Parameter(1);
2293 Node* context = assembler->Parameter(4);
2294 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2295 Node* value = assembler->Float64Atanh(x_value);
2296 Node* result = assembler->ChangeFloat64ToTagged(value);
2297 assembler->Return(result);
Ben Murdochda12d292016-06-02 14:46:10 +01002298}
2299
2300namespace {
2301
2302void Generate_MathRoundingOperation(
Ben Murdochc5610432016-08-08 18:44:38 +01002303 CodeStubAssembler* assembler,
2304 compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
2305 typedef CodeStubAssembler::Label Label;
Ben Murdochda12d292016-06-02 14:46:10 +01002306 typedef compiler::Node Node;
Ben Murdochc5610432016-08-08 18:44:38 +01002307 typedef CodeStubAssembler::Variable Variable;
Ben Murdochda12d292016-06-02 14:46:10 +01002308
2309 Node* context = assembler->Parameter(4);
2310
2311 // We might need to loop once for ToNumber conversion.
2312 Variable var_x(assembler, MachineRepresentation::kTagged);
2313 Label loop(assembler, &var_x);
2314 var_x.Bind(assembler->Parameter(1));
2315 assembler->Goto(&loop);
2316 assembler->Bind(&loop);
2317 {
2318 // Load the current {x} value.
2319 Node* x = var_x.value();
2320
2321 // Check if {x} is a Smi or a HeapObject.
2322 Label if_xissmi(assembler), if_xisnotsmi(assembler);
2323 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2324
2325 assembler->Bind(&if_xissmi);
2326 {
2327 // Nothing to do when {x} is a Smi.
2328 assembler->Return(x);
2329 }
2330
2331 assembler->Bind(&if_xisnotsmi);
2332 {
2333 // Check if {x} is a HeapNumber.
2334 Label if_xisheapnumber(assembler),
2335 if_xisnotheapnumber(assembler, Label::kDeferred);
2336 assembler->Branch(
2337 assembler->WordEqual(assembler->LoadMap(x),
2338 assembler->HeapNumberMapConstant()),
2339 &if_xisheapnumber, &if_xisnotheapnumber);
2340
2341 assembler->Bind(&if_xisheapnumber);
2342 {
2343 Node* x_value = assembler->LoadHeapNumberValue(x);
2344 Node* value = (assembler->*float64op)(x_value);
2345 Node* result = assembler->ChangeFloat64ToTagged(value);
2346 assembler->Return(result);
2347 }
2348
2349 assembler->Bind(&if_xisnotheapnumber);
2350 {
2351 // Need to convert {x} to a Number first.
2352 Callable callable =
2353 CodeFactory::NonNumberToNumber(assembler->isolate());
2354 var_x.Bind(assembler->CallStub(callable, context, x));
2355 assembler->Goto(&loop);
2356 }
2357 }
2358 }
2359}
2360
2361} // namespace
2362
2363// ES6 section 20.2.2.10 Math.ceil ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002364void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
2365 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
Ben Murdochda12d292016-06-02 14:46:10 +01002366}
2367
Ben Murdoch61f157c2016-09-16 13:49:30 +01002368// ES6 section 20.2.2.9 Math.cbrt ( x )
2369void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
2370 using compiler::Node;
2371
2372 Node* x = assembler->Parameter(1);
2373 Node* context = assembler->Parameter(4);
2374 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2375 Node* value = assembler->Float64Cbrt(x_value);
2376 Node* result = assembler->ChangeFloat64ToTagged(value);
2377 assembler->Return(result);
2378}
2379
Ben Murdochda12d292016-06-02 14:46:10 +01002380// ES6 section 20.2.2.11 Math.clz32 ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002381void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
2382 typedef CodeStubAssembler::Label Label;
Ben Murdochda12d292016-06-02 14:46:10 +01002383 typedef compiler::Node Node;
Ben Murdochc5610432016-08-08 18:44:38 +01002384 typedef CodeStubAssembler::Variable Variable;
Ben Murdochda12d292016-06-02 14:46:10 +01002385
2386 Node* context = assembler->Parameter(4);
2387
2388 // Shared entry point for the clz32 operation.
2389 Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
2390 Label do_clz32(assembler);
2391
2392 // We might need to loop once for ToNumber conversion.
2393 Variable var_x(assembler, MachineRepresentation::kTagged);
2394 Label loop(assembler, &var_x);
2395 var_x.Bind(assembler->Parameter(1));
2396 assembler->Goto(&loop);
2397 assembler->Bind(&loop);
2398 {
2399 // Load the current {x} value.
2400 Node* x = var_x.value();
2401
2402 // Check if {x} is a Smi or a HeapObject.
2403 Label if_xissmi(assembler), if_xisnotsmi(assembler);
2404 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2405
2406 assembler->Bind(&if_xissmi);
2407 {
2408 var_clz32_x.Bind(assembler->SmiToWord32(x));
2409 assembler->Goto(&do_clz32);
2410 }
2411
2412 assembler->Bind(&if_xisnotsmi);
2413 {
2414 // Check if {x} is a HeapNumber.
2415 Label if_xisheapnumber(assembler),
2416 if_xisnotheapnumber(assembler, Label::kDeferred);
2417 assembler->Branch(
2418 assembler->WordEqual(assembler->LoadMap(x),
2419 assembler->HeapNumberMapConstant()),
2420 &if_xisheapnumber, &if_xisnotheapnumber);
2421
2422 assembler->Bind(&if_xisheapnumber);
2423 {
2424 var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
2425 assembler->Goto(&do_clz32);
2426 }
2427
2428 assembler->Bind(&if_xisnotheapnumber);
2429 {
2430 // Need to convert {x} to a Number first.
2431 Callable callable =
2432 CodeFactory::NonNumberToNumber(assembler->isolate());
2433 var_x.Bind(assembler->CallStub(callable, context, x));
2434 assembler->Goto(&loop);
2435 }
2436 }
2437 }
2438
2439 assembler->Bind(&do_clz32);
2440 {
2441 Node* x_value = var_clz32_x.value();
2442 Node* value = assembler->Word32Clz(x_value);
2443 Node* result = assembler->ChangeInt32ToTagged(value);
2444 assembler->Return(result);
2445 }
2446}
2447
Ben Murdoch61f157c2016-09-16 13:49:30 +01002448// ES6 section 20.2.2.12 Math.cos ( x )
2449void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
2450 using compiler::Node;
2451
2452 Node* x = assembler->Parameter(1);
2453 Node* context = assembler->Parameter(4);
2454 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2455 Node* value = assembler->Float64Cos(x_value);
2456 Node* result = assembler->ChangeFloat64ToTagged(value);
2457 assembler->Return(result);
2458}
2459
2460// ES6 section 20.2.2.14 Math.exp ( x )
2461void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
2462 using compiler::Node;
2463
2464 Node* x = assembler->Parameter(1);
2465 Node* context = assembler->Parameter(4);
2466 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2467 Node* value = assembler->Float64Exp(x_value);
2468 Node* result = assembler->ChangeFloat64ToTagged(value);
2469 assembler->Return(result);
2470}
2471
Ben Murdochda12d292016-06-02 14:46:10 +01002472// ES6 section 20.2.2.16 Math.floor ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002473void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
2474 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
Ben Murdochda12d292016-06-02 14:46:10 +01002475}
2476
2477// ES6 section 20.2.2.17 Math.fround ( x )
2478BUILTIN(MathFround) {
2479 HandleScope scope(isolate);
2480 DCHECK_EQ(2, args.length());
2481 Handle<Object> x = args.at<Object>(1);
2482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2483 float x32 = DoubleToFloat32(x->Number());
2484 return *isolate->factory()->NewNumber(x32);
2485}
2486
2487// ES6 section 20.2.2.19 Math.imul ( x, y )
2488BUILTIN(MathImul) {
2489 HandleScope scope(isolate);
2490 DCHECK_EQ(3, args.length());
2491 Handle<Object> x = args.at<Object>(1);
2492 Handle<Object> y = args.at<Object>(2);
2493 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2494 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, y, Object::ToNumber(y));
2495 int product = static_cast<int>(NumberToUint32(*x) * NumberToUint32(*y));
2496 return *isolate->factory()->NewNumberFromInt(product);
2497}
2498
Ben Murdoch61f157c2016-09-16 13:49:30 +01002499// ES6 section 20.2.2.20 Math.log ( x )
2500void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
2501 using compiler::Node;
2502
2503 Node* x = assembler->Parameter(1);
2504 Node* context = assembler->Parameter(4);
2505 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2506 Node* value = assembler->Float64Log(x_value);
2507 Node* result = assembler->ChangeFloat64ToTagged(value);
2508 assembler->Return(result);
2509}
2510
2511// ES6 section 20.2.2.21 Math.log1p ( x )
2512void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
2513 using compiler::Node;
2514
2515 Node* x = assembler->Parameter(1);
2516 Node* context = assembler->Parameter(4);
2517 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2518 Node* value = assembler->Float64Log1p(x_value);
2519 Node* result = assembler->ChangeFloat64ToTagged(value);
2520 assembler->Return(result);
2521}
2522
2523// ES6 section 20.2.2.23 Math.log2 ( x )
2524void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
2525 using compiler::Node;
2526
2527 Node* x = assembler->Parameter(1);
2528 Node* context = assembler->Parameter(4);
2529 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2530 Node* value = assembler->Float64Log2(x_value);
2531 Node* result = assembler->ChangeFloat64ToTagged(value);
2532 assembler->Return(result);
2533}
2534
2535// ES6 section 20.2.2.22 Math.log10 ( x )
2536void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
2537 using compiler::Node;
2538
2539 Node* x = assembler->Parameter(1);
2540 Node* context = assembler->Parameter(4);
2541 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2542 Node* value = assembler->Float64Log10(x_value);
2543 Node* result = assembler->ChangeFloat64ToTagged(value);
2544 assembler->Return(result);
2545}
2546
2547// ES6 section 20.2.2.15 Math.expm1 ( x )
2548void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
2549 using compiler::Node;
2550
2551 Node* x = assembler->Parameter(1);
2552 Node* context = assembler->Parameter(4);
2553 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2554 Node* value = assembler->Float64Expm1(x_value);
2555 Node* result = assembler->ChangeFloat64ToTagged(value);
2556 assembler->Return(result);
2557}
2558
Ben Murdochda12d292016-06-02 14:46:10 +01002559// ES6 section 20.2.2.28 Math.round ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002560void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
2561 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
Ben Murdochda12d292016-06-02 14:46:10 +01002562}
2563
Ben Murdoch61f157c2016-09-16 13:49:30 +01002564// ES6 section 20.2.2.30 Math.sin ( x )
2565void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
2566 using compiler::Node;
2567
2568 Node* x = assembler->Parameter(1);
2569 Node* context = assembler->Parameter(4);
2570 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2571 Node* value = assembler->Float64Sin(x_value);
2572 Node* result = assembler->ChangeFloat64ToTagged(value);
2573 assembler->Return(result);
2574}
2575
Ben Murdochda12d292016-06-02 14:46:10 +01002576// ES6 section 20.2.2.32 Math.sqrt ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002577void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01002578 using compiler::Node;
2579
2580 Node* x = assembler->Parameter(1);
2581 Node* context = assembler->Parameter(4);
2582 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2583 Node* value = assembler->Float64Sqrt(x_value);
2584 Node* result = assembler->ChangeFloat64ToTagged(value);
2585 assembler->Return(result);
2586}
2587
Ben Murdoch61f157c2016-09-16 13:49:30 +01002588// ES6 section 20.2.2.33 Math.tan ( x )
2589void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
2590 using compiler::Node;
2591
2592 Node* x = assembler->Parameter(1);
2593 Node* context = assembler->Parameter(4);
2594 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2595 Node* value = assembler->Float64Tan(x_value);
2596 Node* result = assembler->ChangeFloat64ToTagged(value);
2597 assembler->Return(result);
2598}
2599
Ben Murdochda12d292016-06-02 14:46:10 +01002600// ES6 section 20.2.2.35 Math.trunc ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002601void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
2602 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
2603}
2604
2605// -----------------------------------------------------------------------------
2606// ES6 section 19.2 Function Objects
2607
2608// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
2609void Builtins::Generate_FunctionPrototypeHasInstance(
2610 CodeStubAssembler* assembler) {
2611 using compiler::Node;
2612
2613 Node* f = assembler->Parameter(0);
2614 Node* v = assembler->Parameter(1);
2615 Node* context = assembler->Parameter(4);
2616 Node* result = assembler->OrdinaryHasInstance(context, f, v);
2617 assembler->Return(result);
2618}
2619
2620// -----------------------------------------------------------------------------
2621// ES6 section 25.3 Generator Objects
2622
2623namespace {
2624
2625void Generate_GeneratorPrototypeResume(
2626 CodeStubAssembler* assembler, JSGeneratorObject::ResumeMode resume_mode,
2627 char const* const method_name) {
2628 typedef CodeStubAssembler::Label Label;
2629 typedef compiler::Node Node;
2630
2631 Node* receiver = assembler->Parameter(0);
2632 Node* value = assembler->Parameter(1);
2633 Node* context = assembler->Parameter(4);
2634 Node* closed = assembler->SmiConstant(
2635 Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
2636
2637 // Check if the {receiver} is actually a JSGeneratorObject.
2638 Label if_receiverisincompatible(assembler, Label::kDeferred);
2639 assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
2640 Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
2641 assembler->GotoUnless(assembler->Word32Equal(
2642 receiver_instance_type,
2643 assembler->Int32Constant(JS_GENERATOR_OBJECT_TYPE)),
2644 &if_receiverisincompatible);
2645
2646 // Check if the {receiver} is running or already closed.
2647 Node* receiver_continuation = assembler->LoadObjectField(
2648 receiver, JSGeneratorObject::kContinuationOffset);
2649 Label if_receiverisclosed(assembler, Label::kDeferred),
2650 if_receiverisrunning(assembler, Label::kDeferred);
2651 assembler->GotoIf(assembler->SmiEqual(receiver_continuation, closed),
2652 &if_receiverisclosed);
2653 DCHECK_LT(JSGeneratorObject::kGeneratorExecuting,
2654 JSGeneratorObject::kGeneratorClosed);
2655 assembler->GotoIf(assembler->SmiLessThan(receiver_continuation, closed),
2656 &if_receiverisrunning);
2657
2658 // Resume the {receiver} using our trampoline.
2659 Node* result = assembler->CallStub(
2660 CodeFactory::ResumeGenerator(assembler->isolate()), context, value,
2661 receiver, assembler->SmiConstant(Smi::FromInt(resume_mode)));
2662 assembler->Return(result);
2663
2664 assembler->Bind(&if_receiverisincompatible);
2665 {
2666 // The {receiver} is not a valid JSGeneratorObject.
2667 Node* result = assembler->CallRuntime(
2668 Runtime::kThrowIncompatibleMethodReceiver, context,
2669 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
2670 method_name, TENURED)),
2671 receiver);
2672 assembler->Return(result); // Never reached.
2673 }
2674
2675 assembler->Bind(&if_receiverisclosed);
2676 {
2677 // The {receiver} is closed already.
2678 Node* result = nullptr;
2679 switch (resume_mode) {
2680 case JSGeneratorObject::kNext:
2681 result = assembler->CallRuntime(Runtime::kCreateIterResultObject,
2682 context, assembler->UndefinedConstant(),
2683 assembler->BooleanConstant(true));
2684 break;
2685 case JSGeneratorObject::kReturn:
2686 result =
2687 assembler->CallRuntime(Runtime::kCreateIterResultObject, context,
2688 value, assembler->BooleanConstant(true));
2689 break;
2690 case JSGeneratorObject::kThrow:
2691 result = assembler->CallRuntime(Runtime::kThrow, context, value);
2692 break;
2693 }
2694 assembler->Return(result);
2695 }
2696
2697 assembler->Bind(&if_receiverisrunning);
2698 {
2699 Node* result =
2700 assembler->CallRuntime(Runtime::kThrowGeneratorRunning, context);
2701 assembler->Return(result); // Never reached.
2702 }
2703}
2704
2705} // namespace
2706
2707// ES6 section 25.3.1.2 Generator.prototype.next ( value )
2708void Builtins::Generate_GeneratorPrototypeNext(CodeStubAssembler* assembler) {
2709 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kNext,
2710 "[Generator].prototype.next");
2711}
2712
2713// ES6 section 25.3.1.3 Generator.prototype.return ( value )
2714void Builtins::Generate_GeneratorPrototypeReturn(CodeStubAssembler* assembler) {
2715 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kReturn,
2716 "[Generator].prototype.return");
2717}
2718
2719// ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
2720void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) {
2721 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow,
2722 "[Generator].prototype.throw");
Ben Murdochda12d292016-06-02 14:46:10 +01002723}
2724
2725// -----------------------------------------------------------------------------
2726// ES6 section 26.1 The Reflect Object
2727
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002728// ES6 section 26.1.3 Reflect.defineProperty
2729BUILTIN(ReflectDefineProperty) {
2730 HandleScope scope(isolate);
2731 DCHECK_EQ(4, args.length());
2732 Handle<Object> target = args.at<Object>(1);
2733 Handle<Object> key = args.at<Object>(2);
2734 Handle<Object> attributes = args.at<Object>(3);
2735
2736 if (!target->IsJSReceiver()) {
2737 THROW_NEW_ERROR_RETURN_FAILURE(
2738 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2739 isolate->factory()->NewStringFromAsciiChecked(
2740 "Reflect.defineProperty")));
2741 }
2742
2743 Handle<Name> name;
2744 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2745 Object::ToName(isolate, key));
2746
2747 PropertyDescriptor desc;
2748 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
2749 return isolate->heap()->exception();
2750 }
2751
2752 Maybe<bool> result =
2753 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
2754 name, &desc, Object::DONT_THROW);
2755 MAYBE_RETURN(result, isolate->heap()->exception());
2756 return *isolate->factory()->ToBoolean(result.FromJust());
2757}
2758
2759
2760// ES6 section 26.1.4 Reflect.deleteProperty
2761BUILTIN(ReflectDeleteProperty) {
2762 HandleScope scope(isolate);
2763 DCHECK_EQ(3, args.length());
2764 Handle<Object> target = args.at<Object>(1);
2765 Handle<Object> key = args.at<Object>(2);
2766
2767 if (!target->IsJSReceiver()) {
2768 THROW_NEW_ERROR_RETURN_FAILURE(
2769 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2770 isolate->factory()->NewStringFromAsciiChecked(
2771 "Reflect.deleteProperty")));
2772 }
2773
2774 Handle<Name> name;
2775 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2776 Object::ToName(isolate, key));
2777
2778 Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
2779 Handle<JSReceiver>::cast(target), name, SLOPPY);
2780 MAYBE_RETURN(result, isolate->heap()->exception());
2781 return *isolate->factory()->ToBoolean(result.FromJust());
2782}
2783
2784
2785// ES6 section 26.1.6 Reflect.get
2786BUILTIN(ReflectGet) {
2787 HandleScope scope(isolate);
2788 Handle<Object> target = args.atOrUndefined(isolate, 1);
2789 Handle<Object> key = args.atOrUndefined(isolate, 2);
2790 Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
2791
2792 if (!target->IsJSReceiver()) {
2793 THROW_NEW_ERROR_RETURN_FAILURE(
2794 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2795 isolate->factory()->NewStringFromAsciiChecked(
2796 "Reflect.get")));
2797 }
2798
2799 Handle<Name> name;
2800 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2801 Object::ToName(isolate, key));
2802
Ben Murdoch61f157c2016-09-16 13:49:30 +01002803 RETURN_RESULT_OR_FAILURE(
2804 isolate, Object::GetPropertyOrElement(receiver, name,
2805 Handle<JSReceiver>::cast(target)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002806}
2807
2808
2809// ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
2810BUILTIN(ReflectGetOwnPropertyDescriptor) {
2811 HandleScope scope(isolate);
2812 DCHECK_EQ(3, args.length());
2813 Handle<Object> target = args.at<Object>(1);
2814 Handle<Object> key = args.at<Object>(2);
2815
2816 if (!target->IsJSReceiver()) {
2817 THROW_NEW_ERROR_RETURN_FAILURE(
2818 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2819 isolate->factory()->NewStringFromAsciiChecked(
2820 "Reflect.getOwnPropertyDescriptor")));
2821 }
2822
2823 Handle<Name> name;
2824 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2825 Object::ToName(isolate, key));
2826
2827 PropertyDescriptor desc;
2828 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
2829 isolate, Handle<JSReceiver>::cast(target), name, &desc);
2830 MAYBE_RETURN(found, isolate->heap()->exception());
2831 if (!found.FromJust()) return isolate->heap()->undefined_value();
2832 return *desc.ToObject(isolate);
2833}
2834
2835
2836// ES6 section 26.1.8 Reflect.getPrototypeOf
2837BUILTIN(ReflectGetPrototypeOf) {
2838 HandleScope scope(isolate);
2839 DCHECK_EQ(2, args.length());
2840 Handle<Object> target = args.at<Object>(1);
2841
2842 if (!target->IsJSReceiver()) {
2843 THROW_NEW_ERROR_RETURN_FAILURE(
2844 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2845 isolate->factory()->NewStringFromAsciiChecked(
2846 "Reflect.getPrototypeOf")));
2847 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002848 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002849 RETURN_RESULT_OR_FAILURE(isolate,
2850 JSReceiver::GetPrototype(isolate, receiver));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002851}
2852
2853
2854// ES6 section 26.1.9 Reflect.has
2855BUILTIN(ReflectHas) {
2856 HandleScope scope(isolate);
2857 DCHECK_EQ(3, args.length());
2858 Handle<Object> target = args.at<Object>(1);
2859 Handle<Object> key = args.at<Object>(2);
2860
2861 if (!target->IsJSReceiver()) {
2862 THROW_NEW_ERROR_RETURN_FAILURE(
2863 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2864 isolate->factory()->NewStringFromAsciiChecked(
2865 "Reflect.has")));
2866 }
2867
2868 Handle<Name> name;
2869 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2870 Object::ToName(isolate, key));
2871
2872 Maybe<bool> result =
2873 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
2874 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
2875 : isolate->heap()->exception();
2876}
2877
2878
2879// ES6 section 26.1.10 Reflect.isExtensible
2880BUILTIN(ReflectIsExtensible) {
2881 HandleScope scope(isolate);
2882 DCHECK_EQ(2, args.length());
2883 Handle<Object> target = args.at<Object>(1);
2884
2885 if (!target->IsJSReceiver()) {
2886 THROW_NEW_ERROR_RETURN_FAILURE(
2887 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2888 isolate->factory()->NewStringFromAsciiChecked(
2889 "Reflect.isExtensible")));
2890 }
2891
2892 Maybe<bool> result =
2893 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
2894 MAYBE_RETURN(result, isolate->heap()->exception());
2895 return *isolate->factory()->ToBoolean(result.FromJust());
2896}
2897
2898
2899// ES6 section 26.1.11 Reflect.ownKeys
2900BUILTIN(ReflectOwnKeys) {
2901 HandleScope scope(isolate);
2902 DCHECK_EQ(2, args.length());
2903 Handle<Object> target = args.at<Object>(1);
2904
2905 if (!target->IsJSReceiver()) {
2906 THROW_NEW_ERROR_RETURN_FAILURE(
2907 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2908 isolate->factory()->NewStringFromAsciiChecked(
2909 "Reflect.ownKeys")));
2910 }
2911
2912 Handle<FixedArray> keys;
2913 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002914 isolate, keys,
Ben Murdoch61f157c2016-09-16 13:49:30 +01002915 KeyAccumulator::GetKeys(Handle<JSReceiver>::cast(target),
2916 KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
2917 GetKeysConversion::kConvertToString));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002918 return *isolate->factory()->NewJSArrayWithElements(keys);
2919}
2920
2921
2922// ES6 section 26.1.12 Reflect.preventExtensions
2923BUILTIN(ReflectPreventExtensions) {
2924 HandleScope scope(isolate);
2925 DCHECK_EQ(2, args.length());
2926 Handle<Object> target = args.at<Object>(1);
2927
2928 if (!target->IsJSReceiver()) {
2929 THROW_NEW_ERROR_RETURN_FAILURE(
2930 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2931 isolate->factory()->NewStringFromAsciiChecked(
2932 "Reflect.preventExtensions")));
2933 }
2934
2935 Maybe<bool> result = JSReceiver::PreventExtensions(
2936 Handle<JSReceiver>::cast(target), Object::DONT_THROW);
2937 MAYBE_RETURN(result, isolate->heap()->exception());
2938 return *isolate->factory()->ToBoolean(result.FromJust());
2939}
2940
2941
2942// ES6 section 26.1.13 Reflect.set
2943BUILTIN(ReflectSet) {
2944 HandleScope scope(isolate);
2945 Handle<Object> target = args.atOrUndefined(isolate, 1);
2946 Handle<Object> key = args.atOrUndefined(isolate, 2);
2947 Handle<Object> value = args.atOrUndefined(isolate, 3);
2948 Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
2949
2950 if (!target->IsJSReceiver()) {
2951 THROW_NEW_ERROR_RETURN_FAILURE(
2952 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2953 isolate->factory()->NewStringFromAsciiChecked(
2954 "Reflect.set")));
2955 }
2956
2957 Handle<Name> name;
2958 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2959 Object::ToName(isolate, key));
2960
2961 LookupIterator it = LookupIterator::PropertyOrElement(
2962 isolate, receiver, name, Handle<JSReceiver>::cast(target));
2963 Maybe<bool> result = Object::SetSuperProperty(
2964 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
2965 MAYBE_RETURN(result, isolate->heap()->exception());
2966 return *isolate->factory()->ToBoolean(result.FromJust());
2967}
2968
2969
2970// ES6 section 26.1.14 Reflect.setPrototypeOf
2971BUILTIN(ReflectSetPrototypeOf) {
2972 HandleScope scope(isolate);
2973 DCHECK_EQ(3, args.length());
2974 Handle<Object> target = args.at<Object>(1);
2975 Handle<Object> proto = args.at<Object>(2);
2976
2977 if (!target->IsJSReceiver()) {
2978 THROW_NEW_ERROR_RETURN_FAILURE(
2979 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2980 isolate->factory()->NewStringFromAsciiChecked(
2981 "Reflect.setPrototypeOf")));
2982 }
2983
Ben Murdoch61f157c2016-09-16 13:49:30 +01002984 if (!proto->IsJSReceiver() && !proto->IsNull(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002985 THROW_NEW_ERROR_RETURN_FAILURE(
2986 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2987 }
2988
2989 Maybe<bool> result = JSReceiver::SetPrototype(
2990 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2991 MAYBE_RETURN(result, isolate->heap()->exception());
2992 return *isolate->factory()->ToBoolean(result.FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002993}
2994
2995
Steve Blocka7e24c12009-10-30 11:49:00 +00002996// -----------------------------------------------------------------------------
Ben Murdoch097c5b22016-05-18 11:27:45 +01002997// ES6 section 19.3 Boolean Objects
2998
2999
3000// ES6 section 19.3.1.1 Boolean ( value ) for the [[Call]] case.
3001BUILTIN(BooleanConstructor) {
3002 HandleScope scope(isolate);
3003 Handle<Object> value = args.atOrUndefined(isolate, 1);
3004 return isolate->heap()->ToBoolean(value->BooleanValue());
3005}
3006
3007
3008// ES6 section 19.3.1.1 Boolean ( value ) for the [[Construct]] case.
3009BUILTIN(BooleanConstructor_ConstructStub) {
3010 HandleScope scope(isolate);
3011 Handle<Object> value = args.atOrUndefined(isolate, 1);
3012 Handle<JSFunction> target = args.target<JSFunction>();
3013 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3014 DCHECK(*target == target->native_context()->boolean_function());
3015 Handle<JSObject> result;
3016 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3017 JSObject::New(target, new_target));
3018 Handle<JSValue>::cast(result)->set_value(
3019 isolate->heap()->ToBoolean(value->BooleanValue()));
3020 return *result;
3021}
3022
3023
3024// ES6 section 19.3.3.2 Boolean.prototype.toString ( )
3025BUILTIN(BooleanPrototypeToString) {
3026 HandleScope scope(isolate);
3027 Handle<Object> receiver = args.receiver();
3028 if (receiver->IsJSValue()) {
3029 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
3030 }
3031 if (!receiver->IsBoolean()) {
3032 THROW_NEW_ERROR_RETURN_FAILURE(
3033 isolate, NewTypeError(MessageTemplate::kNotGeneric,
3034 isolate->factory()->NewStringFromAsciiChecked(
3035 "Boolean.prototype.toString")));
3036 }
3037 return Handle<Oddball>::cast(receiver)->to_string();
3038}
3039
3040
3041// ES6 section 19.3.3.3 Boolean.prototype.valueOf ( )
3042BUILTIN(BooleanPrototypeValueOf) {
3043 HandleScope scope(isolate);
3044 Handle<Object> receiver = args.receiver();
3045 if (receiver->IsJSValue()) {
3046 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
3047 }
3048 if (!receiver->IsBoolean()) {
3049 THROW_NEW_ERROR_RETURN_FAILURE(
3050 isolate, NewTypeError(MessageTemplate::kNotGeneric,
3051 isolate->factory()->NewStringFromAsciiChecked(
3052 "Boolean.prototype.valueOf")));
3053 }
3054 return *receiver;
3055}
3056
3057
3058// -----------------------------------------------------------------------------
3059// ES6 section 24.2 DataView Objects
3060
3061
3062// ES6 section 24.2.2 The DataView Constructor for the [[Call]] case.
3063BUILTIN(DataViewConstructor) {
3064 HandleScope scope(isolate);
3065 THROW_NEW_ERROR_RETURN_FAILURE(
3066 isolate,
3067 NewTypeError(MessageTemplate::kConstructorNotFunction,
3068 isolate->factory()->NewStringFromAsciiChecked("DataView")));
3069}
3070
3071
3072// ES6 section 24.2.2 The DataView Constructor for the [[Construct]] case.
3073BUILTIN(DataViewConstructor_ConstructStub) {
3074 HandleScope scope(isolate);
3075 Handle<JSFunction> target = args.target<JSFunction>();
3076 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3077 Handle<Object> buffer = args.atOrUndefined(isolate, 1);
3078 Handle<Object> byte_offset = args.atOrUndefined(isolate, 2);
3079 Handle<Object> byte_length = args.atOrUndefined(isolate, 3);
3080
3081 // 2. If Type(buffer) is not Object, throw a TypeError exception.
3082 // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a
3083 // TypeError exception.
3084 if (!buffer->IsJSArrayBuffer()) {
3085 THROW_NEW_ERROR_RETURN_FAILURE(
3086 isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
3087 }
3088 Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
3089
3090 // 4. Let numberOffset be ? ToNumber(byteOffset).
3091 Handle<Object> number_offset;
Ben Murdoch61f157c2016-09-16 13:49:30 +01003092 if (byte_offset->IsUndefined(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003093 // We intentionally violate the specification at this point to allow
3094 // for new DataView(buffer) invocations to be equivalent to the full
3095 // new DataView(buffer, 0) invocation.
3096 number_offset = handle(Smi::FromInt(0), isolate);
3097 } else {
3098 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_offset,
3099 Object::ToNumber(byte_offset));
3100 }
3101
3102 // 5. Let offset be ToInteger(numberOffset).
3103 Handle<Object> offset;
3104 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, offset,
3105 Object::ToInteger(isolate, number_offset));
3106
3107 // 6. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
3108 if (number_offset->Number() != offset->Number() || offset->Number() < 0.0) {
3109 THROW_NEW_ERROR_RETURN_FAILURE(
3110 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
3111 }
3112
3113 // 7. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
3114 // We currently violate the specification at this point.
3115
3116 // 8. Let bufferByteLength be the value of buffer's [[ArrayBufferByteLength]]
3117 // internal slot.
3118 double const buffer_byte_length = array_buffer->byte_length()->Number();
3119
3120 // 9. If offset > bufferByteLength, throw a RangeError exception
3121 if (offset->Number() > buffer_byte_length) {
3122 THROW_NEW_ERROR_RETURN_FAILURE(
3123 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
3124 }
3125
3126 Handle<Object> view_byte_length;
Ben Murdoch61f157c2016-09-16 13:49:30 +01003127 if (byte_length->IsUndefined(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003128 // 10. If byteLength is undefined, then
3129 // a. Let viewByteLength be bufferByteLength - offset.
3130 view_byte_length =
3131 isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
3132 } else {
3133 // 11. Else,
3134 // a. Let viewByteLength be ? ToLength(byteLength).
3135 // b. If offset+viewByteLength > bufferByteLength, throw a RangeError
3136 // exception
3137 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3138 isolate, view_byte_length, Object::ToLength(isolate, byte_length));
3139 if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
3140 THROW_NEW_ERROR_RETURN_FAILURE(
3141 isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
3142 }
3143 }
3144
3145 // 12. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
3146 // "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
3147 // [[ByteLength]], [[ByteOffset]]»).
3148 // 13. Set O's [[DataView]] internal slot to true.
3149 Handle<JSObject> result;
3150 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3151 JSObject::New(target, new_target));
3152 for (int i = 0; i < ArrayBufferView::kInternalFieldCount; ++i) {
3153 Handle<JSDataView>::cast(result)->SetInternalField(i, Smi::FromInt(0));
3154 }
3155
3156 // 14. Set O's [[ViewedArrayBuffer]] internal slot to buffer.
3157 Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
3158
3159 // 15. Set O's [[ByteLength]] internal slot to viewByteLength.
3160 Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
3161
3162 // 16. Set O's [[ByteOffset]] internal slot to offset.
3163 Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
3164
3165 // 17. Return O.
3166 return *result;
3167}
3168
Ben Murdoch61f157c2016-09-16 13:49:30 +01003169// ES6 section 24.2.4.1 get DataView.prototype.buffer
3170BUILTIN(DataViewPrototypeGetBuffer) {
3171 HandleScope scope(isolate);
3172 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.buffer");
3173 return data_view->buffer();
3174}
3175
3176// ES6 section 24.2.4.2 get DataView.prototype.byteLength
3177BUILTIN(DataViewPrototypeGetByteLength) {
3178 HandleScope scope(isolate);
3179 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteLength");
3180 // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
3181 // here if the JSArrayBuffer of the {data_view} was neutered.
3182 return data_view->byte_length();
3183}
3184
3185// ES6 section 24.2.4.3 get DataView.prototype.byteOffset
3186BUILTIN(DataViewPrototypeGetByteOffset) {
3187 HandleScope scope(isolate);
3188 CHECK_RECEIVER(JSDataView, data_view, "get DataView.prototype.byteOffset");
3189 // TODO(bmeurer): According to the ES6 spec, we should throw a TypeError
3190 // here if the JSArrayBuffer of the {data_view} was neutered.
3191 return data_view->byte_offset();
3192}
3193
3194// -----------------------------------------------------------------------------
3195// ES6 section 22.2 TypedArray Objects
3196
3197// ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
3198BUILTIN(TypedArrayPrototypeBuffer) {
3199 HandleScope scope(isolate);
3200 CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer");
3201 return *typed_array->GetBuffer();
3202}
3203
3204namespace {
3205
3206void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
3207 const char* method_name,
3208 int object_offset) {
3209 typedef CodeStubAssembler::Label Label;
3210 typedef compiler::Node Node;
3211
3212 Node* receiver = assembler->Parameter(0);
3213 Node* context = assembler->Parameter(3);
3214
3215 // Check if the {receiver} is actually a JSTypedArray.
3216 Label if_receiverisincompatible(assembler, Label::kDeferred);
3217 assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
3218 Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
3219 assembler->GotoUnless(
3220 assembler->Word32Equal(receiver_instance_type,
3221 assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
3222 &if_receiverisincompatible);
3223
3224 // Check if the {receiver}'s JSArrayBuffer was neutered.
3225 Node* receiver_buffer =
3226 assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
3227 Node* receiver_buffer_bit_field = assembler->LoadObjectField(
3228 receiver_buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
3229 Label if_receiverisneutered(assembler, Label::kDeferred);
3230 assembler->GotoUnless(
3231 assembler->Word32Equal(
3232 assembler->Word32And(
3233 receiver_buffer_bit_field,
3234 assembler->Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
3235 assembler->Int32Constant(0)),
3236 &if_receiverisneutered);
3237 assembler->Return(assembler->LoadObjectField(receiver, object_offset));
3238
3239 assembler->Bind(&if_receiverisneutered);
3240 {
3241 // The {receiver}s buffer was neutered, default to zero.
3242 assembler->Return(assembler->SmiConstant(0));
3243 }
3244
3245 assembler->Bind(&if_receiverisincompatible);
3246 {
3247 // The {receiver} is not a valid JSGeneratorObject.
3248 Node* result = assembler->CallRuntime(
3249 Runtime::kThrowIncompatibleMethodReceiver, context,
3250 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
3251 method_name, TENURED)),
3252 receiver);
3253 assembler->Return(result); // Never reached.
3254 }
3255}
3256
3257} // namespace
3258
3259// ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
3260void Builtins::Generate_TypedArrayPrototypeByteLength(
3261 CodeStubAssembler* assembler) {
3262 Generate_TypedArrayProtoypeGetter(assembler,
3263 "get TypedArray.prototype.byteLength",
3264 JSTypedArray::kByteLengthOffset);
3265}
3266
3267// ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
3268void Builtins::Generate_TypedArrayPrototypeByteOffset(
3269 CodeStubAssembler* assembler) {
3270 Generate_TypedArrayProtoypeGetter(assembler,
3271 "get TypedArray.prototype.byteOffset",
3272 JSTypedArray::kByteOffsetOffset);
3273}
3274
3275// ES6 section 22.2.3.18 get %TypedArray%.prototype.length
3276void Builtins::Generate_TypedArrayPrototypeLength(
3277 CodeStubAssembler* assembler) {
3278 Generate_TypedArrayProtoypeGetter(assembler,
3279 "get TypedArray.prototype.length",
3280 JSTypedArray::kLengthOffset);
3281}
Ben Murdoch097c5b22016-05-18 11:27:45 +01003282
3283// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003284// ES6 section 20.3 Date Objects
Steve Block44f0eee2011-05-26 01:26:41 +01003285
3286
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003287namespace {
3288
3289// ES6 section 20.3.1.1 Time Values and Time Range
3290const double kMinYear = -1000000.0;
3291const double kMaxYear = -kMinYear;
3292const double kMinMonth = -10000000.0;
3293const double kMaxMonth = -kMinMonth;
3294
3295
3296// 20.3.1.2 Day Number and Time within Day
3297const double kMsPerDay = 86400000.0;
3298
3299
3300// ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
3301const double kMsPerSecond = 1000.0;
3302const double kMsPerMinute = 60000.0;
3303const double kMsPerHour = 3600000.0;
3304
3305
3306// ES6 section 20.3.1.14 MakeDate (day, time)
3307double MakeDate(double day, double time) {
3308 if (std::isfinite(day) && std::isfinite(time)) {
3309 return time + day * kMsPerDay;
3310 }
3311 return std::numeric_limits<double>::quiet_NaN();
Steve Block44f0eee2011-05-26 01:26:41 +01003312}
3313
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003315// ES6 section 20.3.1.13 MakeDay (year, month, date)
3316double MakeDay(double year, double month, double date) {
3317 if ((kMinYear <= year && year <= kMaxYear) &&
3318 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
3319 int y = FastD2I(year);
3320 int m = FastD2I(month);
3321 y += m / 12;
3322 m %= 12;
3323 if (m < 0) {
3324 m += 12;
3325 y -= 1;
3326 }
3327 DCHECK_LE(0, m);
3328 DCHECK_LT(m, 12);
3329
3330 // kYearDelta is an arbitrary number such that:
3331 // a) kYearDelta = -1 (mod 400)
3332 // b) year + kYearDelta > 0 for years in the range defined by
3333 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
3334 // Jan 1 1970. This is required so that we don't run into integer
3335 // division of negative numbers.
3336 // c) there shouldn't be an overflow for 32-bit integers in the following
3337 // operations.
3338 static const int kYearDelta = 399999;
3339 static const int kBaseDay =
3340 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
3341 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
3342 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
3343 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
3344 kBaseDay;
3345 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
3346 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151,
3347 181, 212, 243, 273, 304, 334};
3348 day_from_year += kDayFromMonth[m];
3349 } else {
3350 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152,
3351 182, 213, 244, 274, 305, 335};
3352 day_from_year += kDayFromMonth[m];
3353 }
3354 return static_cast<double>(day_from_year - 1) + date;
3355 }
3356 return std::numeric_limits<double>::quiet_NaN();
3357}
3358
3359
3360// ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
3361double MakeTime(double hour, double min, double sec, double ms) {
3362 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
3363 std::isfinite(ms)) {
3364 double const h = DoubleToInteger(hour);
3365 double const m = DoubleToInteger(min);
3366 double const s = DoubleToInteger(sec);
3367 double const milli = DoubleToInteger(ms);
3368 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
3369 }
3370 return std::numeric_limits<double>::quiet_NaN();
3371}
3372
3373
3374// ES6 section 20.3.1.15 TimeClip (time)
3375double TimeClip(double time) {
3376 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
3377 return DoubleToInteger(time) + 0.0;
3378 }
3379 return std::numeric_limits<double>::quiet_NaN();
3380}
3381
3382
3383const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
3384 "Thu", "Fri", "Sat"};
3385const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
3386 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
3387
3388
3389// ES6 section 20.3.1.16 Date Time String Format
3390double ParseDateTimeString(Handle<String> str) {
3391 Isolate* const isolate = str->GetIsolate();
3392 str = String::Flatten(str);
3393 // TODO(bmeurer): Change DateParser to not use the FixedArray.
3394 Handle<FixedArray> tmp =
3395 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
3396 DisallowHeapAllocation no_gc;
3397 String::FlatContent str_content = str->GetFlatContent();
3398 bool result;
3399 if (str_content.IsOneByte()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01003400 result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003401 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01003402 result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003403 }
3404 if (!result) return std::numeric_limits<double>::quiet_NaN();
3405 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
3406 tmp->get(2)->Number());
3407 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
3408 tmp->get(5)->Number(), tmp->get(6)->Number());
3409 double date = MakeDate(day, time);
Ben Murdoch61f157c2016-09-16 13:49:30 +01003410 if (tmp->get(7)->IsNull(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003411 if (!std::isnan(date)) {
3412 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
3413 }
3414 } else {
3415 date -= tmp->get(7)->Number() * 1000.0;
3416 }
3417 return date;
3418}
3419
3420
3421enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
3422
3423
3424// ES6 section 20.3.4.41.1 ToDateString(tv)
3425void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
3426 ToDateStringMode mode = kDateAndTime) {
3427 if (std::isnan(time_val)) {
3428 SNPrintF(str, "Invalid Date");
3429 return;
3430 }
3431 int64_t time_ms = static_cast<int64_t>(time_val);
3432 int64_t local_time_ms = date_cache->ToLocal(time_ms);
3433 int year, month, day, weekday, hour, min, sec, ms;
3434 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
3435 &min, &sec, &ms);
3436 int timezone_offset = -date_cache->TimezoneOffset(time_ms);
3437 int timezone_hour = std::abs(timezone_offset) / 60;
3438 int timezone_min = std::abs(timezone_offset) % 60;
3439 const char* local_timezone = date_cache->LocalTimezone(time_ms);
3440 switch (mode) {
3441 case kDateOnly:
3442 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
3443 kShortMonths[month], day, year);
3444 return;
3445 case kTimeOnly:
3446 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
3447 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
3448 local_timezone);
3449 return;
3450 case kDateAndTime:
3451 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
3452 kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
3453 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
3454 timezone_min, local_timezone);
3455 return;
3456 }
3457 UNREACHABLE();
3458}
3459
3460
3461Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
3462 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
3463 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
3464 Isolate* const isolate = date->GetIsolate();
3465 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
3466 } else {
3467 time_val = std::numeric_limits<double>::quiet_NaN();
3468 }
3469 return *JSDate::SetValue(date, TimeClip(time_val));
3470}
3471
3472} // namespace
3473
3474
3475// ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
3476BUILTIN(DateConstructor) {
3477 HandleScope scope(isolate);
3478 double const time_val = JSDate::CurrentTimeValue(isolate);
3479 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01003480 ToDateString(time_val, ArrayVector(buffer), isolate->date_cache());
Ben Murdoch61f157c2016-09-16 13:49:30 +01003481 RETURN_RESULT_OR_FAILURE(
3482 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003483}
3484
3485
3486// ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
3487BUILTIN(DateConstructor_ConstructStub) {
3488 HandleScope scope(isolate);
3489 int const argc = args.length() - 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003490 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003491 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3492 double time_val;
3493 if (argc == 0) {
3494 time_val = JSDate::CurrentTimeValue(isolate);
3495 } else if (argc == 1) {
3496 Handle<Object> value = args.at<Object>(1);
3497 if (value->IsJSDate()) {
3498 time_val = Handle<JSDate>::cast(value)->value()->Number();
3499 } else {
3500 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
3501 Object::ToPrimitive(value));
3502 if (value->IsString()) {
3503 time_val = ParseDateTimeString(Handle<String>::cast(value));
3504 } else {
3505 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
3506 Object::ToNumber(value));
3507 time_val = value->Number();
3508 }
3509 }
3510 } else {
3511 Handle<Object> year_object;
3512 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3513 Object::ToNumber(args.at<Object>(1)));
3514 Handle<Object> month_object;
3515 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3516 Object::ToNumber(args.at<Object>(2)));
3517 double year = year_object->Number();
3518 double month = month_object->Number();
3519 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3520 if (argc >= 3) {
3521 Handle<Object> date_object;
3522 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
3523 Object::ToNumber(args.at<Object>(3)));
3524 date = date_object->Number();
3525 if (argc >= 4) {
3526 Handle<Object> hours_object;
3527 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3528 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3529 hours = hours_object->Number();
3530 if (argc >= 5) {
3531 Handle<Object> minutes_object;
3532 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3533 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3534 minutes = minutes_object->Number();
3535 if (argc >= 6) {
3536 Handle<Object> seconds_object;
3537 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3538 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
3539 seconds = seconds_object->Number();
3540 if (argc >= 7) {
3541 Handle<Object> ms_object;
3542 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3543 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3544 ms = ms_object->Number();
3545 }
3546 }
3547 }
3548 }
3549 }
3550 if (!std::isnan(year)) {
3551 double const y = DoubleToInteger(year);
3552 if (0.0 <= y && y <= 99) year = 1900 + y;
3553 }
3554 double const day = MakeDay(year, month, date);
3555 double const time = MakeTime(hours, minutes, seconds, ms);
3556 time_val = MakeDate(day, time);
3557 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
3558 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
3559 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
3560 } else {
3561 time_val = std::numeric_limits<double>::quiet_NaN();
3562 }
3563 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01003564 RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003565}
3566
3567
3568// ES6 section 20.3.3.1 Date.now ( )
3569BUILTIN(DateNow) {
3570 HandleScope scope(isolate);
3571 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
3572}
3573
3574
3575// ES6 section 20.3.3.2 Date.parse ( string )
3576BUILTIN(DateParse) {
3577 HandleScope scope(isolate);
3578 Handle<String> string;
3579 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3580 isolate, string,
3581 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
3582 return *isolate->factory()->NewNumber(ParseDateTimeString(string));
3583}
3584
3585
3586// ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
3587BUILTIN(DateUTC) {
3588 HandleScope scope(isolate);
3589 int const argc = args.length() - 1;
3590 double year = std::numeric_limits<double>::quiet_NaN();
3591 double month = std::numeric_limits<double>::quiet_NaN();
3592 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3593 if (argc >= 1) {
3594 Handle<Object> year_object;
3595 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3596 Object::ToNumber(args.at<Object>(1)));
3597 year = year_object->Number();
3598 if (argc >= 2) {
3599 Handle<Object> month_object;
3600 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3601 Object::ToNumber(args.at<Object>(2)));
3602 month = month_object->Number();
3603 if (argc >= 3) {
3604 Handle<Object> date_object;
3605 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3606 isolate, date_object, Object::ToNumber(args.at<Object>(3)));
3607 date = date_object->Number();
3608 if (argc >= 4) {
3609 Handle<Object> hours_object;
3610 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3611 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3612 hours = hours_object->Number();
3613 if (argc >= 5) {
3614 Handle<Object> minutes_object;
3615 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3616 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3617 minutes = minutes_object->Number();
3618 if (argc >= 6) {
3619 Handle<Object> seconds_object;
3620 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3621 isolate, seconds_object,
3622 Object::ToNumber(args.at<Object>(6)));
3623 seconds = seconds_object->Number();
3624 if (argc >= 7) {
3625 Handle<Object> ms_object;
3626 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3627 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3628 ms = ms_object->Number();
3629 }
3630 }
3631 }
3632 }
3633 }
3634 }
3635 }
3636 if (!std::isnan(year)) {
3637 double const y = DoubleToInteger(year);
3638 if (0.0 <= y && y <= 99) year = 1900 + y;
3639 }
3640 double const day = MakeDay(year, month, date);
3641 double const time = MakeTime(hours, minutes, seconds, ms);
3642 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
3643}
3644
3645
3646// ES6 section 20.3.4.20 Date.prototype.setDate ( date )
3647BUILTIN(DatePrototypeSetDate) {
3648 HandleScope scope(isolate);
3649 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
3650 Handle<Object> value = args.atOrUndefined(isolate, 1);
3651 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3652 double time_val = date->value()->Number();
3653 if (!std::isnan(time_val)) {
3654 int64_t const time_ms = static_cast<int64_t>(time_val);
3655 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3656 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3657 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3658 int year, month, day;
3659 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3660 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3661 }
3662 return SetLocalDateValue(date, time_val);
3663}
3664
3665
3666// ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
3667BUILTIN(DatePrototypeSetFullYear) {
3668 HandleScope scope(isolate);
3669 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
3670 int const argc = args.length() - 1;
3671 Handle<Object> year = args.atOrUndefined(isolate, 1);
3672 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3673 double y = year->Number(), m = 0.0, dt = 1.0;
3674 int time_within_day = 0;
3675 if (!std::isnan(date->value()->Number())) {
3676 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3677 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3678 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3679 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3680 int year, month, day;
3681 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3682 m = month;
3683 dt = day;
3684 }
3685 if (argc >= 2) {
3686 Handle<Object> month = args.at<Object>(2);
3687 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3688 m = month->Number();
3689 if (argc >= 3) {
3690 Handle<Object> date = args.at<Object>(3);
3691 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3692 dt = date->Number();
3693 }
3694 }
3695 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3696 return SetLocalDateValue(date, time_val);
3697}
3698
3699
3700// ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
3701BUILTIN(DatePrototypeSetHours) {
3702 HandleScope scope(isolate);
3703 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
3704 int const argc = args.length() - 1;
3705 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3706 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3707 double h = hour->Number();
3708 double time_val = date->value()->Number();
3709 if (!std::isnan(time_val)) {
3710 int64_t const time_ms = static_cast<int64_t>(time_val);
3711 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3712 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3713 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3714 double m = (time_within_day / (60 * 1000)) % 60;
3715 double s = (time_within_day / 1000) % 60;
3716 double milli = time_within_day % 1000;
3717 if (argc >= 2) {
3718 Handle<Object> min = args.at<Object>(2);
3719 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3720 m = min->Number();
3721 if (argc >= 3) {
3722 Handle<Object> sec = args.at<Object>(3);
3723 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3724 s = sec->Number();
3725 if (argc >= 4) {
3726 Handle<Object> ms = args.at<Object>(4);
3727 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3728 milli = ms->Number();
3729 }
3730 }
3731 }
3732 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3733 }
3734 return SetLocalDateValue(date, time_val);
3735}
3736
3737
3738// ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
3739BUILTIN(DatePrototypeSetMilliseconds) {
3740 HandleScope scope(isolate);
3741 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
3742 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3743 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3744 double time_val = date->value()->Number();
3745 if (!std::isnan(time_val)) {
3746 int64_t const time_ms = static_cast<int64_t>(time_val);
3747 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3748 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3749 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3750 int h = time_within_day / (60 * 60 * 1000);
3751 int m = (time_within_day / (60 * 1000)) % 60;
3752 int s = (time_within_day / 1000) % 60;
3753 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3754 }
3755 return SetLocalDateValue(date, time_val);
3756}
3757
3758
3759// ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
3760BUILTIN(DatePrototypeSetMinutes) {
3761 HandleScope scope(isolate);
3762 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
3763 int const argc = args.length() - 1;
3764 Handle<Object> min = args.atOrUndefined(isolate, 1);
3765 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3766 double time_val = date->value()->Number();
3767 if (!std::isnan(time_val)) {
3768 int64_t const time_ms = static_cast<int64_t>(time_val);
3769 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3770 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3771 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3772 int h = time_within_day / (60 * 60 * 1000);
3773 double m = min->Number();
3774 double s = (time_within_day / 1000) % 60;
3775 double milli = time_within_day % 1000;
3776 if (argc >= 2) {
3777 Handle<Object> sec = args.at<Object>(2);
3778 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3779 s = sec->Number();
3780 if (argc >= 3) {
3781 Handle<Object> ms = args.at<Object>(3);
3782 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3783 milli = ms->Number();
3784 }
3785 }
3786 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3787 }
3788 return SetLocalDateValue(date, time_val);
3789}
3790
3791
3792// ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
3793BUILTIN(DatePrototypeSetMonth) {
3794 HandleScope scope(isolate);
3795 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
3796 int const argc = args.length() - 1;
3797 Handle<Object> month = args.atOrUndefined(isolate, 1);
3798 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3799 double time_val = date->value()->Number();
3800 if (!std::isnan(time_val)) {
3801 int64_t const time_ms = static_cast<int64_t>(time_val);
3802 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3803 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3804 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3805 int year, unused, day;
3806 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3807 double m = month->Number();
3808 double dt = day;
3809 if (argc >= 2) {
3810 Handle<Object> date = args.at<Object>(2);
3811 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3812 dt = date->Number();
3813 }
3814 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3815 }
3816 return SetLocalDateValue(date, time_val);
3817}
3818
3819
3820// ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
3821BUILTIN(DatePrototypeSetSeconds) {
3822 HandleScope scope(isolate);
3823 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
3824 int const argc = args.length() - 1;
3825 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3826 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3827 double time_val = date->value()->Number();
3828 if (!std::isnan(time_val)) {
3829 int64_t const time_ms = static_cast<int64_t>(time_val);
3830 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3831 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3832 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3833 int h = time_within_day / (60 * 60 * 1000);
3834 double m = (time_within_day / (60 * 1000)) % 60;
3835 double s = sec->Number();
3836 double milli = time_within_day % 1000;
3837 if (argc >= 2) {
3838 Handle<Object> ms = args.at<Object>(2);
3839 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3840 milli = ms->Number();
3841 }
3842 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3843 }
3844 return SetLocalDateValue(date, time_val);
3845}
3846
3847
3848// ES6 section 20.3.4.27 Date.prototype.setTime ( time )
3849BUILTIN(DatePrototypeSetTime) {
3850 HandleScope scope(isolate);
3851 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
3852 Handle<Object> value = args.atOrUndefined(isolate, 1);
3853 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3854 return *JSDate::SetValue(date, TimeClip(value->Number()));
3855}
3856
3857
3858// ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
3859BUILTIN(DatePrototypeSetUTCDate) {
3860 HandleScope scope(isolate);
3861 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
3862 Handle<Object> value = args.atOrUndefined(isolate, 1);
3863 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3864 if (std::isnan(date->value()->Number())) return date->value();
3865 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3866 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3867 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3868 int year, month, day;
3869 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3870 double const time_val =
3871 MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3872 return *JSDate::SetValue(date, TimeClip(time_val));
3873}
3874
3875
3876// ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
3877BUILTIN(DatePrototypeSetUTCFullYear) {
3878 HandleScope scope(isolate);
3879 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
3880 int const argc = args.length() - 1;
3881 Handle<Object> year = args.atOrUndefined(isolate, 1);
3882 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3883 double y = year->Number(), m = 0.0, dt = 1.0;
3884 int time_within_day = 0;
3885 if (!std::isnan(date->value()->Number())) {
3886 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3887 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3888 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3889 int year, month, day;
3890 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3891 m = month;
3892 dt = day;
3893 }
3894 if (argc >= 2) {
3895 Handle<Object> month = args.at<Object>(2);
3896 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3897 m = month->Number();
3898 if (argc >= 3) {
3899 Handle<Object> date = args.at<Object>(3);
3900 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3901 dt = date->Number();
3902 }
3903 }
3904 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3905 return *JSDate::SetValue(date, TimeClip(time_val));
3906}
3907
3908
3909// ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
3910BUILTIN(DatePrototypeSetUTCHours) {
3911 HandleScope scope(isolate);
3912 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
3913 int const argc = args.length() - 1;
3914 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3915 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3916 double h = hour->Number();
3917 double time_val = date->value()->Number();
3918 if (!std::isnan(time_val)) {
3919 int64_t const time_ms = static_cast<int64_t>(time_val);
3920 int day = isolate->date_cache()->DaysFromTime(time_ms);
3921 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3922 double m = (time_within_day / (60 * 1000)) % 60;
3923 double s = (time_within_day / 1000) % 60;
3924 double milli = time_within_day % 1000;
3925 if (argc >= 2) {
3926 Handle<Object> min = args.at<Object>(2);
3927 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3928 m = min->Number();
3929 if (argc >= 3) {
3930 Handle<Object> sec = args.at<Object>(3);
3931 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3932 s = sec->Number();
3933 if (argc >= 4) {
3934 Handle<Object> ms = args.at<Object>(4);
3935 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3936 milli = ms->Number();
3937 }
3938 }
3939 }
3940 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3941 }
3942 return *JSDate::SetValue(date, TimeClip(time_val));
3943}
3944
3945
3946// ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
3947BUILTIN(DatePrototypeSetUTCMilliseconds) {
3948 HandleScope scope(isolate);
3949 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
3950 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3951 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3952 double time_val = date->value()->Number();
3953 if (!std::isnan(time_val)) {
3954 int64_t const time_ms = static_cast<int64_t>(time_val);
3955 int day = isolate->date_cache()->DaysFromTime(time_ms);
3956 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3957 int h = time_within_day / (60 * 60 * 1000);
3958 int m = (time_within_day / (60 * 1000)) % 60;
3959 int s = (time_within_day / 1000) % 60;
3960 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3961 }
3962 return *JSDate::SetValue(date, TimeClip(time_val));
3963}
3964
3965
3966// ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
3967BUILTIN(DatePrototypeSetUTCMinutes) {
3968 HandleScope scope(isolate);
3969 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
3970 int const argc = args.length() - 1;
3971 Handle<Object> min = args.atOrUndefined(isolate, 1);
3972 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3973 double time_val = date->value()->Number();
3974 if (!std::isnan(time_val)) {
3975 int64_t const time_ms = static_cast<int64_t>(time_val);
3976 int day = isolate->date_cache()->DaysFromTime(time_ms);
3977 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3978 int h = time_within_day / (60 * 60 * 1000);
3979 double m = min->Number();
3980 double s = (time_within_day / 1000) % 60;
3981 double milli = time_within_day % 1000;
3982 if (argc >= 2) {
3983 Handle<Object> sec = args.at<Object>(2);
3984 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3985 s = sec->Number();
3986 if (argc >= 3) {
3987 Handle<Object> ms = args.at<Object>(3);
3988 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3989 milli = ms->Number();
3990 }
3991 }
3992 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3993 }
3994 return *JSDate::SetValue(date, TimeClip(time_val));
3995}
3996
3997
3998// ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
3999BUILTIN(DatePrototypeSetUTCMonth) {
4000 HandleScope scope(isolate);
4001 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
4002 int const argc = args.length() - 1;
4003 Handle<Object> month = args.atOrUndefined(isolate, 1);
4004 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
4005 double time_val = date->value()->Number();
4006 if (!std::isnan(time_val)) {
4007 int64_t const time_ms = static_cast<int64_t>(time_val);
4008 int days = isolate->date_cache()->DaysFromTime(time_ms);
4009 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
4010 int year, unused, day;
4011 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
4012 double m = month->Number();
4013 double dt = day;
4014 if (argc >= 2) {
4015 Handle<Object> date = args.at<Object>(2);
4016 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
4017 dt = date->Number();
4018 }
4019 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
4020 }
4021 return *JSDate::SetValue(date, TimeClip(time_val));
4022}
4023
4024
4025// ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
4026BUILTIN(DatePrototypeSetUTCSeconds) {
4027 HandleScope scope(isolate);
4028 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
4029 int const argc = args.length() - 1;
4030 Handle<Object> sec = args.atOrUndefined(isolate, 1);
4031 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
4032 double time_val = date->value()->Number();
4033 if (!std::isnan(time_val)) {
4034 int64_t const time_ms = static_cast<int64_t>(time_val);
4035 int day = isolate->date_cache()->DaysFromTime(time_ms);
4036 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
4037 int h = time_within_day / (60 * 60 * 1000);
4038 double m = (time_within_day / (60 * 1000)) % 60;
4039 double s = sec->Number();
4040 double milli = time_within_day % 1000;
4041 if (argc >= 2) {
4042 Handle<Object> ms = args.at<Object>(2);
4043 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
4044 milli = ms->Number();
4045 }
4046 time_val = MakeDate(day, MakeTime(h, m, s, milli));
4047 }
4048 return *JSDate::SetValue(date, TimeClip(time_val));
4049}
4050
4051
4052// ES6 section 20.3.4.35 Date.prototype.toDateString ( )
4053BUILTIN(DatePrototypeToDateString) {
4054 HandleScope scope(isolate);
4055 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
4056 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01004057 ToDateString(date->value()->Number(), ArrayVector(buffer),
4058 isolate->date_cache(), kDateOnly);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004059 RETURN_RESULT_OR_FAILURE(
4060 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004061}
4062
4063
4064// ES6 section 20.3.4.36 Date.prototype.toISOString ( )
4065BUILTIN(DatePrototypeToISOString) {
4066 HandleScope scope(isolate);
4067 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
4068 double const time_val = date->value()->Number();
4069 if (std::isnan(time_val)) {
4070 THROW_NEW_ERROR_RETURN_FAILURE(
4071 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
4072 }
4073 int64_t const time_ms = static_cast<int64_t>(time_val);
4074 int year, month, day, weekday, hour, min, sec, ms;
4075 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
4076 &hour, &min, &sec, &ms);
4077 char buffer[128];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004078 if (year >= 0 && year <= 9999) {
Ben Murdochc5610432016-08-08 18:44:38 +01004079 SNPrintF(ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
4080 month + 1, day, hour, min, sec, ms);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004081 } else if (year < 0) {
Ben Murdochc5610432016-08-08 18:44:38 +01004082 SNPrintF(ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year,
4083 month + 1, day, hour, min, sec, ms);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004084 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01004085 SNPrintF(ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
4086 month + 1, day, hour, min, sec, ms);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004087 }
Ben Murdochc5610432016-08-08 18:44:38 +01004088 return *isolate->factory()->NewStringFromAsciiChecked(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004089}
4090
4091
4092// ES6 section 20.3.4.41 Date.prototype.toString ( )
4093BUILTIN(DatePrototypeToString) {
4094 HandleScope scope(isolate);
4095 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
4096 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01004097 ToDateString(date->value()->Number(), ArrayVector(buffer),
4098 isolate->date_cache());
Ben Murdoch61f157c2016-09-16 13:49:30 +01004099 RETURN_RESULT_OR_FAILURE(
4100 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004101}
4102
4103
4104// ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
4105BUILTIN(DatePrototypeToTimeString) {
4106 HandleScope scope(isolate);
4107 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
4108 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01004109 ToDateString(date->value()->Number(), ArrayVector(buffer),
4110 isolate->date_cache(), kTimeOnly);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004111 RETURN_RESULT_OR_FAILURE(
4112 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004113}
4114
4115
4116// ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
4117BUILTIN(DatePrototypeToUTCString) {
4118 HandleScope scope(isolate);
4119 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
4120 double const time_val = date->value()->Number();
4121 if (std::isnan(time_val)) {
4122 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
4123 }
4124 char buffer[128];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004125 int64_t time_ms = static_cast<int64_t>(time_val);
4126 int year, month, day, weekday, hour, min, sec, ms;
4127 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
4128 &hour, &min, &sec, &ms);
Ben Murdochc5610432016-08-08 18:44:38 +01004129 SNPrintF(ArrayVector(buffer), "%s, %02d %s %4d %02d:%02d:%02d GMT",
4130 kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min,
4131 sec);
4132 return *isolate->factory()->NewStringFromAsciiChecked(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004133}
4134
4135
4136// ES6 section 20.3.4.44 Date.prototype.valueOf ( )
4137BUILTIN(DatePrototypeValueOf) {
4138 HandleScope scope(isolate);
4139 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
4140 return date->value();
4141}
4142
4143
4144// ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
4145BUILTIN(DatePrototypeToPrimitive) {
4146 HandleScope scope(isolate);
4147 DCHECK_EQ(2, args.length());
4148 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
4149 Handle<Object> hint = args.at<Object>(1);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004150 RETURN_RESULT_OR_FAILURE(isolate, JSDate::ToPrimitive(receiver, hint));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004151}
4152
4153
4154// ES6 section B.2.4.1 Date.prototype.getYear ( )
4155BUILTIN(DatePrototypeGetYear) {
4156 HandleScope scope(isolate);
4157 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
4158 double time_val = date->value()->Number();
4159 if (std::isnan(time_val)) return date->value();
4160 int64_t time_ms = static_cast<int64_t>(time_val);
4161 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
4162 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
4163 int year, month, day;
4164 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
4165 return Smi::FromInt(year - 1900);
4166}
4167
4168
4169// ES6 section B.2.4.2 Date.prototype.setYear ( year )
4170BUILTIN(DatePrototypeSetYear) {
4171 HandleScope scope(isolate);
4172 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
4173 Handle<Object> year = args.atOrUndefined(isolate, 1);
4174 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
4175 double m = 0.0, dt = 1.0, y = year->Number();
4176 if (0.0 <= y && y <= 99.0) {
4177 y = 1900.0 + DoubleToInteger(y);
4178 }
4179 int time_within_day = 0;
4180 if (!std::isnan(date->value()->Number())) {
4181 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
4182 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
4183 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
4184 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
4185 int year, month, day;
4186 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
4187 m = month;
4188 dt = day;
4189 }
4190 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
4191 return SetLocalDateValue(date, time_val);
4192}
4193
Ben Murdoch61f157c2016-09-16 13:49:30 +01004194// ES6 section 20.3.4.37 Date.prototype.toJSON ( key )
4195BUILTIN(DatePrototypeToJson) {
4196 HandleScope scope(isolate);
4197 Handle<Object> receiver = args.atOrUndefined(isolate, 0);
4198 Handle<JSReceiver> receiver_obj;
4199 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj,
4200 Object::ToObject(isolate, receiver));
4201 Handle<Object> primitive;
4202 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4203 isolate, primitive,
4204 Object::ToPrimitive(receiver_obj, ToPrimitiveHint::kNumber));
4205 if (primitive->IsNumber() && !std::isfinite(primitive->Number())) {
4206 return isolate->heap()->null_value();
4207 } else {
4208 Handle<String> name =
4209 isolate->factory()->NewStringFromAsciiChecked("toISOString");
4210 Handle<Object> function;
4211 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function,
4212 Object::GetProperty(receiver_obj, name));
4213 if (!function->IsCallable()) {
4214 THROW_NEW_ERROR_RETURN_FAILURE(
4215 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name));
4216 }
4217 RETURN_RESULT_OR_FAILURE(
4218 isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL));
4219 }
4220}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004221
4222// static
4223void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
4224 Generate_DatePrototype_GetField(masm, JSDate::kDay);
4225}
4226
4227
4228// static
4229void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
4230 Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
4231}
4232
4233
4234// static
4235void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
4236 Generate_DatePrototype_GetField(masm, JSDate::kYear);
4237}
4238
4239
4240// static
4241void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
4242 Generate_DatePrototype_GetField(masm, JSDate::kHour);
4243}
4244
4245
4246// static
4247void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
4248 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
4249}
4250
4251
4252// static
4253void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
4254 Generate_DatePrototype_GetField(masm, JSDate::kMinute);
4255}
4256
4257
4258// static
4259void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
4260 Generate_DatePrototype_GetField(masm, JSDate::kMonth);
4261}
4262
4263
4264// static
4265void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
4266 Generate_DatePrototype_GetField(masm, JSDate::kSecond);
4267}
4268
4269
4270// static
4271void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
4272 Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
4273}
4274
4275
4276// static
4277void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
4278 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
4279}
4280
4281
4282// static
4283void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
4284 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
4285}
4286
4287
4288// static
4289void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
4290 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
4291}
4292
4293
4294// static
4295void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
4296 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
4297}
4298
4299
4300// static
4301void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
4302 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
4303}
4304
4305
4306// static
4307void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
4308 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
4309}
4310
4311
4312// static
4313void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
4314 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
4315}
4316
4317
4318// static
4319void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
4320 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
4321}
4322
4323
4324// static
4325void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
4326 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
4327}
4328
4329
4330namespace {
4331
4332// ES6 section 19.2.1.1.1 CreateDynamicFunction
Ben Murdoch61f157c2016-09-16 13:49:30 +01004333MaybeHandle<JSFunction> CreateDynamicFunction(Isolate* isolate,
4334 BuiltinArguments args,
4335 const char* token) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004336 // Compute number of arguments, ignoring the receiver.
4337 DCHECK_LE(1, args.length());
4338 int const argc = args.length() - 1;
4339
4340 // Build the source string.
4341 Handle<String> source;
4342 {
4343 IncrementalStringBuilder builder(isolate);
4344 builder.AppendCharacter('(');
4345 builder.AppendCString(token);
4346 builder.AppendCharacter('(');
4347 bool parenthesis_in_arg_string = false;
4348 if (argc > 1) {
4349 for (int i = 1; i < argc; ++i) {
4350 if (i > 1) builder.AppendCharacter(',');
4351 Handle<String> param;
4352 ASSIGN_RETURN_ON_EXCEPTION(
4353 isolate, param, Object::ToString(isolate, args.at<Object>(i)),
4354 JSFunction);
4355 param = String::Flatten(param);
4356 builder.AppendString(param);
4357 // If the formal parameters string include ) - an illegal
4358 // character - it may make the combined function expression
4359 // compile. We avoid this problem by checking for this early on.
4360 DisallowHeapAllocation no_gc; // Ensure vectors stay valid.
4361 String::FlatContent param_content = param->GetFlatContent();
4362 for (int i = 0, length = param->length(); i < length; ++i) {
4363 if (param_content.Get(i) == ')') {
4364 parenthesis_in_arg_string = true;
4365 break;
4366 }
4367 }
4368 }
4369 // If the formal parameters include an unbalanced block comment, the
4370 // function must be rejected. Since JavaScript does not allow nested
4371 // comments we can include a trailing block comment to catch this.
4372 builder.AppendCString("\n/**/");
4373 }
4374 builder.AppendCString(") {\n");
4375 if (argc > 0) {
4376 Handle<String> body;
4377 ASSIGN_RETURN_ON_EXCEPTION(
4378 isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
4379 JSFunction);
4380 builder.AppendString(body);
4381 }
4382 builder.AppendCString("\n})");
4383 ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction);
4384
4385 // The SyntaxError must be thrown after all the (observable) ToString
4386 // conversions are done.
4387 if (parenthesis_in_arg_string) {
4388 THROW_NEW_ERROR(isolate,
4389 NewSyntaxError(MessageTemplate::kParenthesisInArgString),
4390 JSFunction);
4391 }
4392 }
4393
4394 // Compile the string in the constructor and not a helper so that errors to
4395 // come from here.
Ben Murdoch097c5b22016-05-18 11:27:45 +01004396 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004397 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
4398 Handle<JSFunction> function;
4399 {
4400 ASSIGN_RETURN_ON_EXCEPTION(
4401 isolate, function,
4402 CompileString(handle(target->native_context(), isolate), source,
4403 ONLY_SINGLE_FUNCTION_LITERAL),
4404 JSFunction);
4405 Handle<Object> result;
4406 ASSIGN_RETURN_ON_EXCEPTION(
4407 isolate, result,
4408 Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
4409 JSFunction);
4410 function = Handle<JSFunction>::cast(result);
4411 function->shared()->set_name_should_print_as_anonymous(true);
4412 }
4413
4414 // If new.target is equal to target then the function created
4415 // is already correctly setup and nothing else should be done
4416 // here. But if new.target is not equal to target then we are
4417 // have a Function builtin subclassing case and therefore the
4418 // function has wrong initial map. To fix that we create a new
4419 // function object with correct initial map.
4420 Handle<Object> unchecked_new_target = args.new_target();
Ben Murdoch61f157c2016-09-16 13:49:30 +01004421 if (!unchecked_new_target->IsUndefined(isolate) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004422 !unchecked_new_target.is_identical_to(target)) {
4423 Handle<JSReceiver> new_target =
4424 Handle<JSReceiver>::cast(unchecked_new_target);
4425 Handle<Map> initial_map;
4426 ASSIGN_RETURN_ON_EXCEPTION(
4427 isolate, initial_map,
4428 JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction);
4429
4430 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
4431 Handle<Map> map = Map::AsLanguageMode(
4432 initial_map, shared_info->language_mode(), shared_info->kind());
4433
4434 Handle<Context> context(function->context(), isolate);
4435 function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
4436 map, shared_info, context, NOT_TENURED);
4437 }
4438 return function;
4439}
4440
4441} // namespace
4442
4443
4444// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
4445BUILTIN(FunctionConstructor) {
4446 HandleScope scope(isolate);
4447 Handle<JSFunction> result;
4448 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4449 isolate, result, CreateDynamicFunction(isolate, args, "function"));
4450 return *result;
4451}
4452
Ben Murdoch61f157c2016-09-16 13:49:30 +01004453namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004454
Ben Murdoch61f157c2016-09-16 13:49:30 +01004455Object* DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004456 HandleScope scope(isolate);
4457 DCHECK_LE(1, args.length());
4458 if (!args.receiver()->IsCallable()) {
4459 THROW_NEW_ERROR_RETURN_FAILURE(
4460 isolate, NewTypeError(MessageTemplate::kFunctionBind));
4461 }
4462
4463 // Allocate the bound function with the given {this_arg} and {args}.
4464 Handle<JSReceiver> target = args.at<JSReceiver>(0);
4465 Handle<Object> this_arg = isolate->factory()->undefined_value();
4466 ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
4467 if (args.length() > 1) {
4468 this_arg = args.at<Object>(1);
4469 for (int i = 2; i < args.length(); ++i) {
4470 argv[i - 2] = args.at<Object>(i);
4471 }
4472 }
4473 Handle<JSBoundFunction> function;
4474 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4475 isolate, function,
4476 isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
4477
Ben Murdochc5610432016-08-08 18:44:38 +01004478 LookupIterator length_lookup(target, isolate->factory()->length_string(),
4479 target, LookupIterator::OWN);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004480 // Setup the "length" property based on the "length" of the {target}.
Ben Murdochc5610432016-08-08 18:44:38 +01004481 // If the targets length is the default JSFunction accessor, we can keep the
4482 // accessor that's installed by default on the JSBoundFunction. It lazily
4483 // computes the value from the underlying internal length.
4484 if (!target->IsJSFunction() ||
4485 length_lookup.state() != LookupIterator::ACCESSOR ||
4486 !length_lookup.GetAccessors()->IsAccessorInfo()) {
4487 Handle<Object> length(Smi::FromInt(0), isolate);
4488 Maybe<PropertyAttributes> attributes =
4489 JSReceiver::GetPropertyAttributes(&length_lookup);
4490 if (!attributes.IsJust()) return isolate->heap()->exception();
4491 if (attributes.FromJust() != ABSENT) {
4492 Handle<Object> target_length;
4493 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length,
4494 Object::GetProperty(&length_lookup));
4495 if (target_length->IsNumber()) {
4496 length = isolate->factory()->NewNumber(std::max(
4497 0.0, DoubleToInteger(target_length->Number()) - argv.length()));
4498 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004499 }
Ben Murdochc5610432016-08-08 18:44:38 +01004500 LookupIterator it(function, isolate->factory()->length_string(), function);
4501 DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
4502 RETURN_FAILURE_ON_EXCEPTION(isolate,
4503 JSObject::DefineOwnPropertyIgnoreAttributes(
4504 &it, length, it.property_attributes()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004505 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004506
4507 // Setup the "name" property based on the "name" of the {target}.
Ben Murdochc5610432016-08-08 18:44:38 +01004508 // If the targets name is the default JSFunction accessor, we can keep the
4509 // accessor that's installed by default on the JSBoundFunction. It lazily
4510 // computes the value from the underlying internal name.
4511 LookupIterator name_lookup(target, isolate->factory()->name_string(), target,
4512 LookupIterator::OWN);
4513 if (!target->IsJSFunction() ||
4514 name_lookup.state() != LookupIterator::ACCESSOR ||
4515 !name_lookup.GetAccessors()->IsAccessorInfo()) {
4516 Handle<Object> target_name;
4517 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name,
4518 Object::GetProperty(&name_lookup));
4519 Handle<String> name;
4520 if (target_name->IsString()) {
4521 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4522 isolate, name,
4523 Name::ToFunctionName(Handle<String>::cast(target_name)));
4524 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4525 isolate, name, isolate->factory()->NewConsString(
4526 isolate->factory()->bound__string(), name));
4527 } else {
4528 name = isolate->factory()->bound__string();
4529 }
4530 LookupIterator it(function, isolate->factory()->name_string());
4531 DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
4532 RETURN_FAILURE_ON_EXCEPTION(isolate,
4533 JSObject::DefineOwnPropertyIgnoreAttributes(
4534 &it, name, it.property_attributes()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004535 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004536 return *function;
4537}
4538
Ben Murdoch61f157c2016-09-16 13:49:30 +01004539} // namespace
4540
4541// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
4542BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
4543
4544// TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
4545// can tailcall to the builtin directly.
4546RUNTIME_FUNCTION(Runtime_FunctionBind) {
4547 DCHECK_EQ(2, args.length());
4548 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
4549 // Rewrap the arguments as builtins arguments.
4550 BuiltinArguments caller_args(incoming->length() + 3,
4551 incoming->arguments() + 1);
4552 return DoFunctionBind(isolate, caller_args);
4553}
4554
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004555// ES6 section 19.2.3.5 Function.prototype.toString ( )
4556BUILTIN(FunctionPrototypeToString) {
4557 HandleScope scope(isolate);
4558 Handle<Object> receiver = args.receiver();
4559 if (receiver->IsJSBoundFunction()) {
4560 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
4561 } else if (receiver->IsJSFunction()) {
4562 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
4563 }
4564 THROW_NEW_ERROR_RETURN_FAILURE(
4565 isolate, NewTypeError(MessageTemplate::kNotGeneric,
4566 isolate->factory()->NewStringFromAsciiChecked(
4567 "Function.prototype.toString")));
4568}
4569
4570
4571// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
4572BUILTIN(GeneratorFunctionConstructor) {
4573 HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004574 RETURN_RESULT_OR_FAILURE(isolate,
4575 CreateDynamicFunction(isolate, args, "function*"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004576}
4577
Ben Murdochc5610432016-08-08 18:44:38 +01004578BUILTIN(AsyncFunctionConstructor) {
4579 HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004580 Handle<JSFunction> func;
Ben Murdochc5610432016-08-08 18:44:38 +01004581 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch61f157c2016-09-16 13:49:30 +01004582 isolate, func, CreateDynamicFunction(isolate, args, "async function"));
4583
4584 // Do not lazily compute eval position for AsyncFunction, as they may not be
4585 // determined after the function is resumed.
4586 Handle<Script> script = handle(Script::cast(func->shared()->script()));
4587 int position = script->GetEvalPosition();
4588 USE(position);
4589
4590 return *func;
Ben Murdochc5610432016-08-08 18:44:38 +01004591}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004592
4593// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
4594BUILTIN(SymbolConstructor) {
4595 HandleScope scope(isolate);
4596 Handle<Symbol> result = isolate->factory()->NewSymbol();
4597 Handle<Object> description = args.atOrUndefined(isolate, 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004598 if (!description->IsUndefined(isolate)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004599 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
4600 Object::ToString(isolate, description));
4601 result->set_name(*description);
4602 }
4603 return *result;
4604}
4605
4606
4607// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
4608BUILTIN(SymbolConstructor_ConstructStub) {
4609 HandleScope scope(isolate);
4610 THROW_NEW_ERROR_RETURN_FAILURE(
4611 isolate, NewTypeError(MessageTemplate::kNotConstructor,
4612 isolate->factory()->Symbol_string()));
4613}
4614
4615
4616// ES6 19.1.3.6 Object.prototype.toString
4617BUILTIN(ObjectProtoToString) {
4618 HandleScope scope(isolate);
4619 Handle<Object> object = args.at<Object>(0);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004620 RETURN_RESULT_OR_FAILURE(isolate,
4621 Object::ObjectProtoToString(isolate, object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004622}
4623
Ben Murdochda12d292016-06-02 14:46:10 +01004624// -----------------------------------------------------------------------------
4625// ES6 section 21.1 String Objects
4626
Ben Murdoch61f157c2016-09-16 13:49:30 +01004627// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
4628void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
4629 typedef CodeStubAssembler::Label Label;
4630 typedef compiler::Node Node;
4631 typedef CodeStubAssembler::Variable Variable;
Ben Murdochda12d292016-06-02 14:46:10 +01004632
Ben Murdoch61f157c2016-09-16 13:49:30 +01004633 Node* code = assembler->Parameter(1);
4634 Node* context = assembler->Parameter(4);
4635
4636 // Check if we have exactly one argument (plus the implicit receiver), i.e.
4637 // if the parent frame is not an arguments adaptor frame.
4638 Label if_oneargument(assembler), if_notoneargument(assembler);
4639 Node* parent_frame_pointer = assembler->LoadParentFramePointer();
4640 Node* parent_frame_type =
4641 assembler->Load(MachineType::Pointer(), parent_frame_pointer,
4642 assembler->IntPtrConstant(
4643 CommonFrameConstants::kContextOrFrameTypeOffset));
4644 assembler->Branch(
4645 assembler->WordEqual(
4646 parent_frame_type,
4647 assembler->SmiConstant(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))),
4648 &if_notoneargument, &if_oneargument);
4649
4650 assembler->Bind(&if_oneargument);
4651 {
4652 // Single argument case, perform fast single character string cache lookup
4653 // for one-byte code units, or fall back to creating a single character
4654 // string on the fly otherwise.
4655 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4656 Node* code16 = assembler->Word32And(
4657 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4658 Node* result = assembler->StringFromCharCode(code16);
4659 assembler->Return(result);
Ben Murdochda12d292016-06-02 14:46:10 +01004660 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01004661
4662 assembler->Bind(&if_notoneargument);
4663 {
4664 // Determine the resulting string length.
4665 Node* parent_frame_length =
4666 assembler->Load(MachineType::Pointer(), parent_frame_pointer,
4667 assembler->IntPtrConstant(
4668 ArgumentsAdaptorFrameConstants::kLengthOffset));
4669 Node* length = assembler->SmiToWord(parent_frame_length);
4670
4671 // Assume that the resulting string contains only one-byte characters.
4672 Node* result = assembler->AllocateSeqOneByteString(context, length);
4673
4674 // Truncate all input parameters and append them to the resulting string.
4675 Variable var_offset(assembler, MachineType::PointerRepresentation());
4676 Label loop(assembler, &var_offset), done_loop(assembler);
4677 var_offset.Bind(assembler->IntPtrConstant(0));
4678 assembler->Goto(&loop);
4679 assembler->Bind(&loop);
4680 {
4681 // Load the current {offset}.
4682 Node* offset = var_offset.value();
4683
4684 // Check if we're done with the string.
4685 assembler->GotoIf(assembler->WordEqual(offset, length), &done_loop);
4686
4687 // Load the next code point and truncate it to a 16-bit value.
4688 Node* code = assembler->Load(
4689 MachineType::AnyTagged(), parent_frame_pointer,
4690 assembler->IntPtrAdd(
4691 assembler->WordShl(assembler->IntPtrSub(length, offset),
4692 assembler->IntPtrConstant(kPointerSizeLog2)),
4693 assembler->IntPtrConstant(
4694 CommonFrameConstants::kFixedFrameSizeAboveFp -
4695 kPointerSize)));
4696 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4697 Node* code16 = assembler->Word32And(
4698 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4699
4700 // Check if {code16} fits into a one-byte string.
4701 Label if_codeisonebyte(assembler), if_codeistwobyte(assembler);
4702 assembler->Branch(
4703 assembler->Int32LessThanOrEqual(
4704 code16, assembler->Int32Constant(String::kMaxOneByteCharCode)),
4705 &if_codeisonebyte, &if_codeistwobyte);
4706
4707 assembler->Bind(&if_codeisonebyte);
4708 {
4709 // The {code16} fits into the SeqOneByteString {result}.
4710 assembler->StoreNoWriteBarrier(
4711 MachineRepresentation::kWord8, result,
4712 assembler->IntPtrAdd(
4713 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
4714 kHeapObjectTag),
4715 offset),
4716 code16);
4717 var_offset.Bind(
4718 assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
4719 assembler->Goto(&loop);
4720 }
4721
4722 assembler->Bind(&if_codeistwobyte);
4723 {
4724 // Allocate a SeqTwoByteString to hold the resulting string.
4725 Node* cresult = assembler->AllocateSeqTwoByteString(context, length);
4726
4727 // Copy all characters that were previously written to the
4728 // SeqOneByteString in {result} over to the new {cresult}.
4729 Variable var_coffset(assembler, MachineType::PointerRepresentation());
4730 Label cloop(assembler, &var_coffset), done_cloop(assembler);
4731 var_coffset.Bind(assembler->IntPtrConstant(0));
4732 assembler->Goto(&cloop);
4733 assembler->Bind(&cloop);
4734 {
4735 Node* coffset = var_coffset.value();
4736 assembler->GotoIf(assembler->WordEqual(coffset, offset), &done_cloop);
4737 Node* ccode = assembler->Load(
4738 MachineType::Uint8(), result,
4739 assembler->IntPtrAdd(
4740 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
4741 kHeapObjectTag),
4742 coffset));
4743 assembler->StoreNoWriteBarrier(
4744 MachineRepresentation::kWord16, cresult,
4745 assembler->IntPtrAdd(
4746 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4747 kHeapObjectTag),
4748 assembler->WordShl(coffset, 1)),
4749 ccode);
4750 var_coffset.Bind(
4751 assembler->IntPtrAdd(coffset, assembler->IntPtrConstant(1)));
4752 assembler->Goto(&cloop);
4753 }
4754
4755 // Write the pending {code16} to {offset}.
4756 assembler->Bind(&done_cloop);
4757 assembler->StoreNoWriteBarrier(
4758 MachineRepresentation::kWord16, cresult,
4759 assembler->IntPtrAdd(
4760 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4761 kHeapObjectTag),
4762 assembler->WordShl(offset, 1)),
4763 code16);
4764
4765 // Copy the remaining parameters to the SeqTwoByteString {cresult}.
4766 Label floop(assembler, &var_offset), done_floop(assembler);
4767 assembler->Goto(&floop);
4768 assembler->Bind(&floop);
4769 {
4770 // Compute the next {offset}.
4771 Node* offset = assembler->IntPtrAdd(var_offset.value(),
4772 assembler->IntPtrConstant(1));
4773
4774 // Check if we're done with the string.
4775 assembler->GotoIf(assembler->WordEqual(offset, length), &done_floop);
4776
4777 // Load the next code point and truncate it to a 16-bit value.
4778 Node* code = assembler->Load(
4779 MachineType::AnyTagged(), parent_frame_pointer,
4780 assembler->IntPtrAdd(
4781 assembler->WordShl(
4782 assembler->IntPtrSub(length, offset),
4783 assembler->IntPtrConstant(kPointerSizeLog2)),
4784 assembler->IntPtrConstant(
4785 CommonFrameConstants::kFixedFrameSizeAboveFp -
4786 kPointerSize)));
4787 Node* code32 = assembler->TruncateTaggedToWord32(context, code);
4788 Node* code16 = assembler->Word32And(
4789 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
4790
4791 // Store the truncated {code} point at the next offset.
4792 assembler->StoreNoWriteBarrier(
4793 MachineRepresentation::kWord16, cresult,
4794 assembler->IntPtrAdd(
4795 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
4796 kHeapObjectTag),
4797 assembler->WordShl(offset, 1)),
4798 code16);
4799 var_offset.Bind(offset);
4800 assembler->Goto(&floop);
4801 }
4802
4803 // Return the SeqTwoByteString.
4804 assembler->Bind(&done_floop);
4805 assembler->Return(cresult);
4806 }
4807 }
4808
4809 assembler->Bind(&done_loop);
4810 assembler->Return(result);
4811 }
4812}
4813
4814namespace { // for String.fromCodePoint
4815
4816bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
4817 if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) {
4818 return false;
4819 }
4820
4821 if (Object::ToInteger(isolate, value).ToHandleChecked()->Number() !=
4822 value->Number()) {
4823 return false;
4824 }
4825
4826 if (value->Number() < 0 || value->Number() > 0x10FFFF) {
4827 return false;
4828 }
4829
4830 return true;
4831}
4832
4833uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
4834 Handle<Object> value = args.at<Object>(1 + index);
4835 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::ToNumber(value), -1);
4836 if (!IsValidCodePoint(isolate, value)) {
4837 isolate->Throw(*isolate->factory()->NewRangeError(
4838 MessageTemplate::kInvalidCodePoint, value));
4839 return -1;
4840 }
4841 return DoubleToUint32(value->Number());
Ben Murdochda12d292016-06-02 14:46:10 +01004842}
4843
4844} // namespace
4845
Ben Murdoch61f157c2016-09-16 13:49:30 +01004846// ES6 section 21.1.2.2 String.fromCodePoint ( ...codePoints )
4847BUILTIN(StringFromCodePoint) {
Ben Murdochda12d292016-06-02 14:46:10 +01004848 HandleScope scope(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +01004849 int const length = args.length() - 1;
4850 if (length == 0) return isolate->heap()->empty_string();
4851 DCHECK_LT(0, length);
Ben Murdoch61f157c2016-09-16 13:49:30 +01004852
4853 // Optimistically assume that the resulting String contains only one byte
4854 // characters.
4855 List<uint8_t> one_byte_buffer(length);
4856 uc32 code = 0;
4857 int index;
4858 for (index = 0; index < length; index++) {
4859 code = NextCodePoint(isolate, args, index);
4860 if (code < 0) {
4861 return isolate->heap()->exception();
Ben Murdochda12d292016-06-02 14:46:10 +01004862 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01004863 if (code > String::kMaxOneByteCharCode) {
4864 break;
4865 }
4866 one_byte_buffer.Add(code);
Ben Murdochda12d292016-06-02 14:46:10 +01004867 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01004868
4869 if (index == length) {
4870 RETURN_RESULT_OR_FAILURE(isolate, isolate->factory()->NewStringFromOneByte(
4871 one_byte_buffer.ToConstVector()));
Ben Murdochda12d292016-06-02 14:46:10 +01004872 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01004873
4874 List<uc16> two_byte_buffer(length - index);
4875
4876 while (true) {
4877 if (code <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
4878 two_byte_buffer.Add(code);
4879 } else {
4880 two_byte_buffer.Add(unibrow::Utf16::LeadSurrogate(code));
4881 two_byte_buffer.Add(unibrow::Utf16::TrailSurrogate(code));
4882 }
4883
4884 if (++index == length) {
4885 break;
4886 }
4887 code = NextCodePoint(isolate, args, index);
4888 if (code < 0) {
4889 return isolate->heap()->exception();
4890 }
4891 }
4892
4893 Handle<SeqTwoByteString> result;
4894 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4895 isolate, result,
4896 isolate->factory()->NewRawTwoByteString(one_byte_buffer.length() +
4897 two_byte_buffer.length()));
4898
4899 CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(),
4900 one_byte_buffer.length());
4901 CopyChars(result->GetChars() + one_byte_buffer.length(),
4902 two_byte_buffer.ToConstVector().start(), two_byte_buffer.length());
4903
Ben Murdochda12d292016-06-02 14:46:10 +01004904 return *result;
4905}
4906
Ben Murdochc5610432016-08-08 18:44:38 +01004907// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
4908void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
4909 typedef CodeStubAssembler::Label Label;
4910 typedef compiler::Node Node;
4911 typedef CodeStubAssembler::Variable Variable;
4912
4913 Node* receiver = assembler->Parameter(0);
4914 Node* position = assembler->Parameter(1);
4915 Node* context = assembler->Parameter(4);
4916
4917 // Check that {receiver} is coercible to Object and convert it to a String.
4918 receiver =
4919 assembler->ToThisString(context, receiver, "String.prototype.charAt");
4920
4921 // Convert the {position} to a Smi and check that it's in bounds of the
4922 // {receiver}.
4923 // TODO(bmeurer): Find an abstraction for this!
4924 {
4925 // Check if the {position} is already a Smi.
4926 Variable var_position(assembler, MachineRepresentation::kTagged);
4927 var_position.Bind(position);
4928 Label if_positionissmi(assembler),
4929 if_positionisnotsmi(assembler, Label::kDeferred);
4930 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
4931 &if_positionisnotsmi);
4932 assembler->Bind(&if_positionisnotsmi);
4933 {
4934 // Convert the {position} to an Integer via the ToIntegerStub.
4935 Callable callable = CodeFactory::ToInteger(assembler->isolate());
4936 Node* index = assembler->CallStub(callable, context, position);
4937
4938 // Check if the resulting {index} is now a Smi.
4939 Label if_indexissmi(assembler, Label::kDeferred),
4940 if_indexisnotsmi(assembler, Label::kDeferred);
4941 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
4942 &if_indexisnotsmi);
4943
4944 assembler->Bind(&if_indexissmi);
4945 {
4946 var_position.Bind(index);
4947 assembler->Goto(&if_positionissmi);
4948 }
4949
4950 assembler->Bind(&if_indexisnotsmi);
4951 {
4952 // The ToIntegerStub canonicalizes everything in Smi range to Smi
4953 // representation, so any HeapNumber returned is not in Smi range.
4954 // The only exception here is -0.0, which we treat as 0.
4955 Node* index_value = assembler->LoadHeapNumberValue(index);
4956 Label if_indexiszero(assembler, Label::kDeferred),
4957 if_indexisnotzero(assembler, Label::kDeferred);
4958 assembler->Branch(assembler->Float64Equal(
4959 index_value, assembler->Float64Constant(0.0)),
4960 &if_indexiszero, &if_indexisnotzero);
4961
4962 assembler->Bind(&if_indexiszero);
4963 {
4964 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
4965 assembler->Goto(&if_positionissmi);
4966 }
4967
4968 assembler->Bind(&if_indexisnotzero);
4969 {
4970 // The {index} is some other integral Number, that is definitely
4971 // neither -0.0 nor in Smi range.
4972 assembler->Return(assembler->EmptyStringConstant());
4973 }
4974 }
4975 }
4976 assembler->Bind(&if_positionissmi);
4977 position = var_position.value();
4978
4979 // Determine the actual length of the {receiver} String.
4980 Node* receiver_length =
4981 assembler->LoadObjectField(receiver, String::kLengthOffset);
4982
4983 // Return "" if the Smi {position} is outside the bounds of the {receiver}.
4984 Label if_positioninbounds(assembler),
4985 if_positionnotinbounds(assembler, Label::kDeferred);
4986 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
4987 &if_positionnotinbounds, &if_positioninbounds);
4988 assembler->Bind(&if_positionnotinbounds);
4989 assembler->Return(assembler->EmptyStringConstant());
4990 assembler->Bind(&if_positioninbounds);
4991 }
4992
4993 // Load the character code at the {position} from the {receiver}.
4994 Node* code = assembler->StringCharCodeAt(receiver, position);
4995
4996 // And return the single character string with only that {code}.
4997 Node* result = assembler->StringFromCharCode(code);
4998 assembler->Return(result);
4999}
5000
5001// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
5002void Builtins::Generate_StringPrototypeCharCodeAt(
5003 CodeStubAssembler* assembler) {
5004 typedef CodeStubAssembler::Label Label;
5005 typedef compiler::Node Node;
5006 typedef CodeStubAssembler::Variable Variable;
5007
5008 Node* receiver = assembler->Parameter(0);
5009 Node* position = assembler->Parameter(1);
5010 Node* context = assembler->Parameter(4);
5011
5012 // Check that {receiver} is coercible to Object and convert it to a String.
5013 receiver =
5014 assembler->ToThisString(context, receiver, "String.prototype.charCodeAt");
5015
5016 // Convert the {position} to a Smi and check that it's in bounds of the
5017 // {receiver}.
5018 // TODO(bmeurer): Find an abstraction for this!
5019 {
5020 // Check if the {position} is already a Smi.
5021 Variable var_position(assembler, MachineRepresentation::kTagged);
5022 var_position.Bind(position);
5023 Label if_positionissmi(assembler),
5024 if_positionisnotsmi(assembler, Label::kDeferred);
5025 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
5026 &if_positionisnotsmi);
5027 assembler->Bind(&if_positionisnotsmi);
5028 {
5029 // Convert the {position} to an Integer via the ToIntegerStub.
5030 Callable callable = CodeFactory::ToInteger(assembler->isolate());
5031 Node* index = assembler->CallStub(callable, context, position);
5032
5033 // Check if the resulting {index} is now a Smi.
5034 Label if_indexissmi(assembler, Label::kDeferred),
5035 if_indexisnotsmi(assembler, Label::kDeferred);
5036 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
5037 &if_indexisnotsmi);
5038
5039 assembler->Bind(&if_indexissmi);
5040 {
5041 var_position.Bind(index);
5042 assembler->Goto(&if_positionissmi);
5043 }
5044
5045 assembler->Bind(&if_indexisnotsmi);
5046 {
5047 // The ToIntegerStub canonicalizes everything in Smi range to Smi
5048 // representation, so any HeapNumber returned is not in Smi range.
5049 // The only exception here is -0.0, which we treat as 0.
5050 Node* index_value = assembler->LoadHeapNumberValue(index);
5051 Label if_indexiszero(assembler, Label::kDeferred),
5052 if_indexisnotzero(assembler, Label::kDeferred);
5053 assembler->Branch(assembler->Float64Equal(
5054 index_value, assembler->Float64Constant(0.0)),
5055 &if_indexiszero, &if_indexisnotzero);
5056
5057 assembler->Bind(&if_indexiszero);
5058 {
5059 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
5060 assembler->Goto(&if_positionissmi);
5061 }
5062
5063 assembler->Bind(&if_indexisnotzero);
5064 {
5065 // The {index} is some other integral Number, that is definitely
5066 // neither -0.0 nor in Smi range.
5067 assembler->Return(assembler->NaNConstant());
5068 }
5069 }
5070 }
5071 assembler->Bind(&if_positionissmi);
5072 position = var_position.value();
5073
5074 // Determine the actual length of the {receiver} String.
5075 Node* receiver_length =
5076 assembler->LoadObjectField(receiver, String::kLengthOffset);
5077
5078 // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
5079 Label if_positioninbounds(assembler),
5080 if_positionnotinbounds(assembler, Label::kDeferred);
5081 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
5082 &if_positionnotinbounds, &if_positioninbounds);
5083 assembler->Bind(&if_positionnotinbounds);
5084 assembler->Return(assembler->NaNConstant());
5085 assembler->Bind(&if_positioninbounds);
5086 }
5087
5088 // Load the character at the {position} from the {receiver}.
5089 Node* value = assembler->StringCharCodeAt(receiver, position);
5090 Node* result = assembler->SmiFromWord32(value);
5091 assembler->Return(result);
5092}
5093
Ben Murdoch61f157c2016-09-16 13:49:30 +01005094// ES6 section 21.1.3.25 String.prototype.trim ()
5095BUILTIN(StringPrototypeTrim) {
5096 HandleScope scope(isolate);
5097 TO_THIS_STRING(string, "String.prototype.trim");
5098 return *String::Trim(string, String::kTrim);
5099}
5100
5101// Non-standard WebKit extension
5102BUILTIN(StringPrototypeTrimLeft) {
5103 HandleScope scope(isolate);
5104 TO_THIS_STRING(string, "String.prototype.trimLeft");
5105 return *String::Trim(string, String::kTrimLeft);
5106}
5107
5108// Non-standard WebKit extension
5109BUILTIN(StringPrototypeTrimRight) {
5110 HandleScope scope(isolate);
5111 TO_THIS_STRING(string, "String.prototype.trimRight");
5112 return *String::Trim(string, String::kTrimRight);
5113}
5114
Ben Murdochda12d292016-06-02 14:46:10 +01005115// -----------------------------------------------------------------------------
5116// ES6 section 21.1 ArrayBuffer Objects
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005117
5118// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
5119BUILTIN(ArrayBufferConstructor) {
5120 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005121 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005122 DCHECK(*target == target->native_context()->array_buffer_fun() ||
5123 *target == target->native_context()->shared_array_buffer_fun());
5124 THROW_NEW_ERROR_RETURN_FAILURE(
5125 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
5126 handle(target->shared()->name(), isolate)));
5127}
5128
5129
5130// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
5131BUILTIN(ArrayBufferConstructor_ConstructStub) {
5132 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01005133 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005134 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
5135 Handle<Object> length = args.atOrUndefined(isolate, 1);
5136 DCHECK(*target == target->native_context()->array_buffer_fun() ||
5137 *target == target->native_context()->shared_array_buffer_fun());
5138 Handle<Object> number_length;
5139 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
5140 Object::ToInteger(isolate, length));
5141 if (number_length->Number() < 0.0) {
5142 THROW_NEW_ERROR_RETURN_FAILURE(
5143 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
5144 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01005145 Handle<JSObject> result;
5146 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
5147 JSObject::New(target, new_target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005148 size_t byte_length;
5149 if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
5150 THROW_NEW_ERROR_RETURN_FAILURE(
5151 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
5152 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005153 SharedFlag shared_flag =
5154 (*target == target->native_context()->array_buffer_fun())
5155 ? SharedFlag::kNotShared
5156 : SharedFlag::kShared;
Ben Murdoch097c5b22016-05-18 11:27:45 +01005157 if (!JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer>::cast(result),
5158 isolate, byte_length, true,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005159 shared_flag)) {
5160 THROW_NEW_ERROR_RETURN_FAILURE(
5161 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
5162 }
5163 return *result;
5164}
5165
5166
5167// ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
5168BUILTIN(ArrayBufferIsView) {
5169 SealHandleScope shs(isolate);
5170 DCHECK_EQ(2, args.length());
5171 Object* arg = args[1];
5172 return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
5173}
5174
5175
5176// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
5177BUILTIN(ProxyConstructor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005178 HandleScope scope(isolate);
5179 THROW_NEW_ERROR_RETURN_FAILURE(
5180 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005181 NewTypeError(MessageTemplate::kConstructorNotFunction,
5182 isolate->factory()->NewStringFromAsciiChecked("Proxy")));
5183}
5184
5185
5186// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
5187BUILTIN(ProxyConstructor_ConstructStub) {
5188 HandleScope scope(isolate);
5189 DCHECK(isolate->proxy_function()->IsConstructor());
5190 Handle<Object> target = args.atOrUndefined(isolate, 1);
5191 Handle<Object> handler = args.atOrUndefined(isolate, 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01005192 RETURN_RESULT_OR_FAILURE(isolate, JSProxy::New(isolate, target, handler));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005193}
5194
5195
5196// -----------------------------------------------------------------------------
5197// Throwers for restricted function properties and strict arguments object
5198// properties
5199
5200
5201BUILTIN(RestrictedFunctionPropertiesThrower) {
5202 HandleScope scope(isolate);
5203 THROW_NEW_ERROR_RETURN_FAILURE(
5204 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
5205}
5206
5207
5208BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
5209 HandleScope scope(isolate);
5210 THROW_NEW_ERROR_RETURN_FAILURE(
5211 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005212}
5213
5214
Steve Block44f0eee2011-05-26 01:26:41 +01005215// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00005216//
5217
5218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005219namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +00005220
Ben Murdoch61f157c2016-09-16 13:49:30 +01005221// Returns the holder JSObject if the function can legally be called with this
5222// receiver. Returns nullptr if the call is illegal.
5223// TODO(dcarney): CallOptimization duplicates this logic, merge.
5224JSObject* GetCompatibleReceiver(Isolate* isolate, FunctionTemplateInfo* info,
5225 JSObject* receiver) {
5226 Object* recv_type = info->signature();
5227 // No signature, return holder.
5228 if (!recv_type->IsFunctionTemplateInfo()) return receiver;
5229 FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type);
5230
5231 // Check the receiver. Fast path for receivers with no hidden prototypes.
5232 if (signature->IsTemplateFor(receiver)) return receiver;
5233 if (!receiver->map()->has_hidden_prototype()) return nullptr;
5234 for (PrototypeIterator iter(isolate, receiver, kStartAtPrototype,
5235 PrototypeIterator::END_AT_NON_HIDDEN);
5236 !iter.IsAtEnd(); iter.Advance()) {
5237 JSObject* current = iter.GetCurrent<JSObject>();
5238 if (signature->IsTemplateFor(current)) return current;
5239 }
5240 return nullptr;
5241}
5242
5243template <bool is_construct>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005244MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
Ben Murdoch61f157c2016-09-16 13:49:30 +01005245 Isolate* isolate, Handle<HeapObject> function,
5246 Handle<HeapObject> new_target, Handle<FunctionTemplateInfo> fun_data,
5247 Handle<Object> receiver, BuiltinArguments args) {
5248 Handle<JSObject> js_receiver;
5249 JSObject* raw_holder;
Steve Blocka7e24c12009-10-30 11:49:00 +00005250 if (is_construct) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01005251 DCHECK(args.receiver()->IsTheHole(isolate));
5252 if (fun_data->instance_template()->IsUndefined(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005253 v8::Local<ObjectTemplate> templ =
5254 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
5255 ToApiHandle<v8::FunctionTemplate>(fun_data));
5256 fun_data->set_instance_template(*Utils::OpenHandle(*templ));
5257 }
5258 Handle<ObjectTemplateInfo> instance_template(
5259 ObjectTemplateInfo::cast(fun_data->instance_template()), isolate);
Ben Murdochc5610432016-08-08 18:44:38 +01005260 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdoch61f157c2016-09-16 13:49:30 +01005261 isolate, js_receiver,
Ben Murdochc5610432016-08-08 18:44:38 +01005262 ApiNatives::InstantiateObject(instance_template,
5263 Handle<JSReceiver>::cast(new_target)),
5264 Object);
Ben Murdoch61f157c2016-09-16 13:49:30 +01005265 args[0] = *js_receiver;
5266 DCHECK_EQ(*js_receiver, *args.receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00005267
Ben Murdoch61f157c2016-09-16 13:49:30 +01005268 raw_holder = *js_receiver;
5269 } else {
5270 DCHECK(receiver->IsJSReceiver());
5271
5272 if (!receiver->IsJSObject()) {
5273 // This function cannot be called with the given receiver. Abort!
5274 THROW_NEW_ERROR(
5275 isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
5276 }
5277
5278 js_receiver = Handle<JSObject>::cast(receiver);
5279
5280 if (!fun_data->accept_any_receiver() &&
5281 js_receiver->IsAccessCheckNeeded() &&
5282 !isolate->MayAccess(handle(isolate->context()), js_receiver)) {
5283 isolate->ReportFailedAccessCheck(js_receiver);
5284 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
5285 }
5286
5287 raw_holder = GetCompatibleReceiver(isolate, *fun_data, *js_receiver);
5288
5289 if (raw_holder == nullptr) {
5290 // This function cannot be called with the given receiver. Abort!
5291 THROW_NEW_ERROR(
5292 isolate, NewTypeError(MessageTemplate::kIllegalInvocation), Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005293 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005294 }
5295
Steve Blocka7e24c12009-10-30 11:49:00 +00005296 Object* raw_call_data = fun_data->call_code();
Ben Murdoch61f157c2016-09-16 13:49:30 +01005297 if (!raw_call_data->IsUndefined(isolate)) {
Ben Murdochda12d292016-06-02 14:46:10 +01005298 DCHECK(raw_call_data->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00005299 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
5300 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005301 v8::FunctionCallback callback =
5302 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00005303 Object* data_obj = call_data->data();
Steve Blocka7e24c12009-10-30 11:49:00 +00005304
Ben Murdoch61f157c2016-09-16 13:49:30 +01005305 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*js_receiver)));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005306
Ben Murdochc5610432016-08-08 18:44:38 +01005307 FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder,
5308 *new_target, &args[0] - 1,
5309 args.length() - 1);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005310
Ben Murdochda12d292016-06-02 14:46:10 +01005311 Handle<Object> result = custom.Call(callback);
Steve Blocka7e24c12009-10-30 11:49:00 +00005312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005313 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
Ben Murdoch61f157c2016-09-16 13:49:30 +01005314 if (result.is_null()) {
5315 if (is_construct) return js_receiver;
5316 return isolate->factory()->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005317 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01005318 // Rebox the result.
5319 result->VerifyApiCallResultType();
5320 if (!is_construct || result->IsJSObject()) return handle(*result, isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005321 }
5322
Ben Murdoch61f157c2016-09-16 13:49:30 +01005323 return js_receiver;
Steve Blocka7e24c12009-10-30 11:49:00 +00005324}
Leon Clarkee46be812010-01-19 14:06:41 +00005325
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005326} // namespace
5327
Leon Clarkee46be812010-01-19 14:06:41 +00005328
5329BUILTIN(HandleApiCall) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005330 HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +01005331 Handle<JSFunction> function = args.target<JSFunction>();
5332 Handle<Object> receiver = args.receiver();
5333 Handle<HeapObject> new_target = args.new_target();
5334 Handle<FunctionTemplateInfo> fun_data(function->shared()->get_api_func_data(),
5335 isolate);
5336 if (new_target->IsJSReceiver()) {
5337 RETURN_RESULT_OR_FAILURE(
5338 isolate, HandleApiCallHelper<true>(isolate, function, new_target,
5339 fun_data, receiver, args));
5340 } else {
5341 RETURN_RESULT_OR_FAILURE(
5342 isolate, HandleApiCallHelper<false>(isolate, function, new_target,
5343 fun_data, receiver, args));
5344 }
Leon Clarkee46be812010-01-19 14:06:41 +00005345}
5346
5347
Ben Murdoch097c5b22016-05-18 11:27:45 +01005348Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode,
5349 TailCallMode tail_call_mode) {
5350 switch (tail_call_mode) {
5351 case TailCallMode::kDisallow:
5352 switch (mode) {
5353 case ConvertReceiverMode::kNullOrUndefined:
5354 return CallFunction_ReceiverIsNullOrUndefined();
5355 case ConvertReceiverMode::kNotNullOrUndefined:
5356 return CallFunction_ReceiverIsNotNullOrUndefined();
5357 case ConvertReceiverMode::kAny:
5358 return CallFunction_ReceiverIsAny();
5359 }
5360 break;
5361 case TailCallMode::kAllow:
5362 switch (mode) {
5363 case ConvertReceiverMode::kNullOrUndefined:
5364 return TailCallFunction_ReceiverIsNullOrUndefined();
5365 case ConvertReceiverMode::kNotNullOrUndefined:
5366 return TailCallFunction_ReceiverIsNotNullOrUndefined();
5367 case ConvertReceiverMode::kAny:
5368 return TailCallFunction_ReceiverIsAny();
5369 }
5370 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005371 }
5372 UNREACHABLE();
5373 return Handle<Code>::null();
5374}
5375
Ben Murdoch097c5b22016-05-18 11:27:45 +01005376Handle<Code> Builtins::Call(ConvertReceiverMode mode,
5377 TailCallMode tail_call_mode) {
5378 switch (tail_call_mode) {
5379 case TailCallMode::kDisallow:
5380 switch (mode) {
5381 case ConvertReceiverMode::kNullOrUndefined:
5382 return Call_ReceiverIsNullOrUndefined();
5383 case ConvertReceiverMode::kNotNullOrUndefined:
5384 return Call_ReceiverIsNotNullOrUndefined();
5385 case ConvertReceiverMode::kAny:
5386 return Call_ReceiverIsAny();
5387 }
5388 break;
5389 case TailCallMode::kAllow:
5390 switch (mode) {
5391 case ConvertReceiverMode::kNullOrUndefined:
5392 return TailCall_ReceiverIsNullOrUndefined();
5393 case ConvertReceiverMode::kNotNullOrUndefined:
5394 return TailCall_ReceiverIsNotNullOrUndefined();
5395 case ConvertReceiverMode::kAny:
5396 return TailCall_ReceiverIsAny();
5397 }
5398 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005399 }
5400 UNREACHABLE();
5401 return Handle<Code>::null();
5402}
5403
Ben Murdoch097c5b22016-05-18 11:27:45 +01005404Handle<Code> Builtins::CallBoundFunction(TailCallMode tail_call_mode) {
5405 switch (tail_call_mode) {
5406 case TailCallMode::kDisallow:
5407 return CallBoundFunction();
5408 case TailCallMode::kAllow:
5409 return TailCallBoundFunction();
5410 }
5411 UNREACHABLE();
5412 return Handle<Code>::null();
5413}
5414
5415Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode) {
5416 switch (tail_call_mode) {
5417 case TailCallMode::kDisallow:
5418 return InterpreterPushArgsAndCall();
5419 case TailCallMode::kAllow:
5420 return InterpreterPushArgsAndTailCall();
5421 }
5422 UNREACHABLE();
5423 return Handle<Code>::null();
5424}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005425
5426namespace {
5427
Ben Murdoch61f157c2016-09-16 13:49:30 +01005428class RelocatableArguments : public BuiltinArguments, public Relocatable {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005429 public:
5430 RelocatableArguments(Isolate* isolate, int length, Object** arguments)
Ben Murdoch61f157c2016-09-16 13:49:30 +01005431 : BuiltinArguments(length, arguments), Relocatable(isolate) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005432
5433 virtual inline void IterateInstance(ObjectVisitor* v) {
5434 if (length() == 0) return;
5435 v->VisitPointers(lowest_address(), highest_address() + 1);
5436 }
5437
5438 private:
5439 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
5440};
5441
5442} // namespace
5443
Ben Murdoch61f157c2016-09-16 13:49:30 +01005444MaybeHandle<Object> Builtins::InvokeApiFunction(Isolate* isolate,
5445 Handle<HeapObject> function,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005446 Handle<Object> receiver,
5447 int argc,
5448 Handle<Object> args[]) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01005449 DCHECK(function->IsFunctionTemplateInfo() ||
5450 (function->IsJSFunction() &&
5451 JSFunction::cast(*function)->shared()->IsApiFunction()));
5452
Ben Murdochda12d292016-06-02 14:46:10 +01005453 // Do proper receiver conversion for non-strict mode api functions.
5454 if (!receiver->IsJSReceiver()) {
Ben Murdochda12d292016-06-02 14:46:10 +01005455 if (function->IsFunctionTemplateInfo() ||
5456 is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
Ben Murdochc5610432016-08-08 18:44:38 +01005457 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
5458 Object::ConvertReceiver(isolate, receiver),
5459 Object);
Ben Murdochda12d292016-06-02 14:46:10 +01005460 }
5461 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01005462
5463 Handle<FunctionTemplateInfo> fun_data =
5464 function->IsFunctionTemplateInfo()
5465 ? Handle<FunctionTemplateInfo>::cast(function)
5466 : handle(JSFunction::cast(*function)->shared()->get_api_func_data(),
5467 isolate);
5468 Handle<HeapObject> new_target = isolate->factory()->undefined_value();
Ben Murdochc5610432016-08-08 18:44:38 +01005469 // Construct BuiltinArguments object:
5470 // new target, function, arguments reversed, receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005471 const int kBufferSize = 32;
5472 Object* small_argv[kBufferSize];
5473 Object** argv;
Ben Murdochc5610432016-08-08 18:44:38 +01005474 if (argc + 3 <= kBufferSize) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005475 argv = small_argv;
5476 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01005477 argv = new Object*[argc + 3];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005478 }
Ben Murdochc5610432016-08-08 18:44:38 +01005479 argv[argc + 2] = *receiver;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005480 for (int i = 0; i < argc; ++i) {
Ben Murdochc5610432016-08-08 18:44:38 +01005481 argv[argc - i + 1] = *args[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005482 }
Ben Murdochc5610432016-08-08 18:44:38 +01005483 argv[1] = *function;
Ben Murdoch61f157c2016-09-16 13:49:30 +01005484 argv[0] = *new_target;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005485 MaybeHandle<Object> result;
5486 {
Ben Murdochc5610432016-08-08 18:44:38 +01005487 RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01005488 result = HandleApiCallHelper<false>(isolate, function, new_target, fun_data,
5489 receiver, arguments);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005490 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01005491 if (argv != small_argv) delete[] argv;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005492 return result;
Leon Clarkee46be812010-01-19 14:06:41 +00005493}
Steve Blocka7e24c12009-10-30 11:49:00 +00005494
5495
5496// Helper function to handle calls to non-function objects created through the
5497// API. The object can be called as either a constructor (using new) or just as
5498// a function (without new).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005499MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Ben Murdoch61f157c2016-09-16 13:49:30 +01005500 Isolate* isolate, bool is_construct_call, BuiltinArguments args) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005501 Handle<Object> receiver = args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00005502
5503 // Get the object called.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005504 JSObject* obj = JSObject::cast(*receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00005505
Ben Murdochc5610432016-08-08 18:44:38 +01005506 // Set the new target.
5507 HeapObject* new_target;
5508 if (is_construct_call) {
5509 // TODO(adamk): This should be passed through in args instead of
5510 // being patched in here. We need to set a non-undefined value
5511 // for v8::FunctionCallbackInfo::IsConstructCall() to get the
5512 // right answer.
5513 new_target = obj;
5514 } else {
5515 new_target = isolate->heap()->undefined_value();
5516 }
5517
Steve Blocka7e24c12009-10-30 11:49:00 +00005518 // Get the invocation callback from the function descriptor that was
5519 // used to create the called object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005520 DCHECK(obj->map()->is_callable());
5521 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
5522 // TODO(ishell): turn this back to a DCHECK.
5523 CHECK(constructor->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00005524 Object* handler =
Steve Block6ded16b2010-05-10 14:33:55 +01005525 constructor->shared()->get_api_func_data()->instance_call_handler();
Ben Murdoch61f157c2016-09-16 13:49:30 +01005526 DCHECK(!handler->IsUndefined(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005527 // TODO(ishell): remove this debugging code.
5528 CHECK(handler->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00005529 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
5530 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005531 v8::FunctionCallback callback =
5532 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00005533
5534 // Get the data for the call and perform the callback.
Steve Blocka7e24c12009-10-30 11:49:00 +00005535 Object* result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005536 {
Steve Block44f0eee2011-05-26 01:26:41 +01005537 HandleScope scope(isolate);
5538 LOG(isolate, ApiObjectAccess("call non-function", obj));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08005539
Ben Murdochc5610432016-08-08 18:44:38 +01005540 FunctionCallbackArguments custom(isolate, call_data->data(), constructor,
5541 obj, new_target, &args[0] - 1,
5542 args.length() - 1);
Ben Murdochda12d292016-06-02 14:46:10 +01005543 Handle<Object> result_handle = custom.Call(callback);
5544 if (result_handle.is_null()) {
5545 result = isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00005546 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01005547 result = *result_handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00005548 }
5549 }
5550 // Check for exceptions and return result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005551 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005552 return result;
5553}
5554
5555
5556// Handle calls to non-function objects created through the API. This delegate
5557// function is used when the call is a normal function call.
5558BUILTIN(HandleApiCallAsFunction) {
Steve Block44f0eee2011-05-26 01:26:41 +01005559 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00005560}
Steve Blocka7e24c12009-10-30 11:49:00 +00005561
5562
5563// Handle calls to non-function objects created through the API. This delegate
5564// function is used when the call is a construct call.
5565BUILTIN(HandleApiCallAsConstructor) {
Steve Block44f0eee2011-05-26 01:26:41 +01005566 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00005567}
Steve Blocka7e24c12009-10-30 11:49:00 +00005568
Ben Murdoch61f157c2016-09-16 13:49:30 +01005569namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +00005570
Ben Murdoch61f157c2016-09-16 13:49:30 +01005571void Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
5572 typedef compiler::Node Node;
5573
5574 Node* receiver = assembler->Parameter(0);
5575 Node* name = assembler->Parameter(1);
5576 Node* slot = assembler->Parameter(2);
5577 Node* vector = assembler->Parameter(3);
5578 Node* context = assembler->Parameter(4);
5579
5580 assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
5581 slot, vector);
Steve Blocka7e24c12009-10-30 11:49:00 +00005582}
5583
Ben Murdoch61f157c2016-09-16 13:49:30 +01005584void Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
5585 typedef compiler::Node Node;
Steve Blocka7e24c12009-10-30 11:49:00 +00005586
Ben Murdoch61f157c2016-09-16 13:49:30 +01005587 Node* slot = assembler->Parameter(0);
5588 Node* vector = assembler->Parameter(1);
5589 Node* context = assembler->Parameter(2);
5590
5591 assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
5592 vector);
5593}
5594
5595void Generate_LoadIC_Normal(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005596 LoadIC::GenerateNormal(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00005597}
5598
Ben Murdoch61f157c2016-09-16 13:49:30 +01005599void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005600 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
5601}
5602
Ben Murdoch61f157c2016-09-16 13:49:30 +01005603void Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
5604 typedef compiler::Node Node;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005605
Ben Murdoch61f157c2016-09-16 13:49:30 +01005606 Node* receiver = assembler->Parameter(0);
5607 Node* name = assembler->Parameter(1);
5608 // Node* slot = assembler->Parameter(2);
5609 // Node* vector = assembler->Parameter(3);
5610 Node* context = assembler->Parameter(4);
5611
5612 assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
Steve Blocka7e24c12009-10-30 11:49:00 +00005613}
5614
Ben Murdoch61f157c2016-09-16 13:49:30 +01005615void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
5616 typedef compiler::Node Node;
Steve Blocka7e24c12009-10-30 11:49:00 +00005617
Ben Murdoch61f157c2016-09-16 13:49:30 +01005618 Node* slot = assembler->Parameter(0);
5619 Node* vector = assembler->Parameter(1);
5620 Node* context = assembler->Parameter(2);
5621
5622 assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot,
5623 vector);
5624}
5625
5626void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005627 KeyedLoadIC::GenerateRuntimeGetProperty(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00005628}
5629
Ben Murdoch61f157c2016-09-16 13:49:30 +01005630void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005631 KeyedLoadIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00005632}
5633
Ben Murdoch61f157c2016-09-16 13:49:30 +01005634void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005635 KeyedLoadIC::GenerateMegamorphic(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00005636}
5637
Ben Murdoch61f157c2016-09-16 13:49:30 +01005638void Generate_StoreIC_Miss(MacroAssembler* masm) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005639 StoreIC::GenerateMiss(masm);
5640}
5641
Ben Murdoch61f157c2016-09-16 13:49:30 +01005642void Generate_StoreIC_Normal(MacroAssembler* masm) {
Steve Block8defd9f2010-07-08 12:39:36 +01005643 StoreIC::GenerateNormal(masm);
5644}
5645
Ben Murdoch61f157c2016-09-16 13:49:30 +01005646void Generate_StoreIC_Slow(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005647 NamedStoreHandlerCompiler::GenerateSlow(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00005648}
5649
Ben Murdoch61f157c2016-09-16 13:49:30 +01005650void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005651 ElementHandlerCompiler::GenerateStoreSlow(masm);
5652}
5653
Ben Murdoch61f157c2016-09-16 13:49:30 +01005654void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005655 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
5656}
5657
Ben Murdoch61f157c2016-09-16 13:49:30 +01005658void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005659 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
5660}
5661
Ben Murdoch61f157c2016-09-16 13:49:30 +01005662void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005663 KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
5664}
5665
Ben Murdoch61f157c2016-09-16 13:49:30 +01005666void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005667 KeyedStoreIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00005668}
5669
Ben Murdoch61f157c2016-09-16 13:49:30 +01005670void Generate_Return_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005671 DebugCodegen::GenerateDebugBreakStub(masm,
5672 DebugCodegen::SAVE_RESULT_REGISTER);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01005673}
5674
Ben Murdoch61f157c2016-09-16 13:49:30 +01005675void Generate_Slot_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005676 DebugCodegen::GenerateDebugBreakStub(masm,
5677 DebugCodegen::IGNORE_RESULT_REGISTER);
Steve Block6ded16b2010-05-10 14:33:55 +01005678}
5679
Ben Murdoch61f157c2016-09-16 13:49:30 +01005680void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005681 DebugCodegen::GenerateFrameDropperLiveEdit(masm);
Steve Block6ded16b2010-05-10 14:33:55 +01005682}
Steve Blocka7e24c12009-10-30 11:49:00 +00005683
Ben Murdoch61f157c2016-09-16 13:49:30 +01005684} // namespace
Steve Block44f0eee2011-05-26 01:26:41 +01005685
5686Builtins::Builtins() : initialized_(false) {
5687 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
5688 memset(names_, 0, sizeof(names_[0]) * builtin_count);
5689}
5690
5691
5692Builtins::~Builtins() {
5693}
5694
Ben Murdoch61f157c2016-09-16 13:49:30 +01005695#define DEF_ENUM_C(name) FUNCTION_ADDR(Builtin_##name),
Steve Block44f0eee2011-05-26 01:26:41 +01005696Address const Builtins::c_functions_[cfunction_count] = {
5697 BUILTIN_LIST_C(DEF_ENUM_C)
5698};
Steve Blocka7e24c12009-10-30 11:49:00 +00005699#undef DEF_ENUM_C
5700
Steve Blocka7e24c12009-10-30 11:49:00 +00005701
Steve Block44f0eee2011-05-26 01:26:41 +01005702struct BuiltinDesc {
Ben Murdochda12d292016-06-02 14:46:10 +01005703 Handle<Code> (*builder)(Isolate*, struct BuiltinDesc const*);
Steve Block44f0eee2011-05-26 01:26:41 +01005704 byte* generator;
5705 byte* c_code;
5706 const char* s_name; // name is only used for generating log information.
5707 int name;
5708 Code::Flags flags;
Ben Murdochda12d292016-06-02 14:46:10 +01005709 int argc;
Steve Block44f0eee2011-05-26 01:26:41 +01005710};
5711
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005712#define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
5713
Steve Block44f0eee2011-05-26 01:26:41 +01005714class BuiltinFunctionTable {
5715 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005716 BuiltinDesc* functions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005717 base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005718 return functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01005719 }
5720
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005721 base::OnceType once_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005722 BuiltinDesc functions_[Builtins::builtin_count + 1];
Steve Block44f0eee2011-05-26 01:26:41 +01005723
5724 friend class Builtins;
5725};
5726
Ben Murdochda12d292016-06-02 14:46:10 +01005727namespace {
5728
5729BuiltinFunctionTable builtin_function_table = BUILTIN_FUNCTION_TABLE_INIT;
5730
5731Handle<Code> MacroAssemblerBuilder(Isolate* isolate,
5732 BuiltinDesc const* builtin_desc) {
5733// For now we generate builtin adaptor code into a stack-allocated
5734// buffer, before copying it into individual code objects. Be careful
5735// with alignment, some platforms don't like unaligned code.
5736#ifdef DEBUG
5737 // We can generate a lot of debug code on Arm64.
5738 const size_t buffer_size = 32 * KB;
5739#elif V8_TARGET_ARCH_PPC64
5740 // 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
5741 const size_t buffer_size = 10 * KB;
5742#else
5743 const size_t buffer_size = 8 * KB;
5744#endif
5745 union {
5746 int force_alignment;
5747 byte buffer[buffer_size]; // NOLINT(runtime/arrays)
5748 } u;
5749
5750 MacroAssembler masm(isolate, u.buffer, sizeof(u.buffer),
5751 CodeObjectRequired::kYes);
5752 // Generate the code/adaptor.
Ben Murdoch61f157c2016-09-16 13:49:30 +01005753 typedef void (*Generator)(MacroAssembler*, int);
Ben Murdochda12d292016-06-02 14:46:10 +01005754 Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5755 // We pass all arguments to the generator, but it may not use all of
5756 // them. This works because the first arguments are on top of the
5757 // stack.
5758 DCHECK(!masm.has_frame());
Ben Murdoch61f157c2016-09-16 13:49:30 +01005759 g(&masm, builtin_desc->name);
Ben Murdochda12d292016-06-02 14:46:10 +01005760 // Move the code into the object heap.
5761 CodeDesc desc;
5762 masm.GetCode(&desc);
5763 Code::Flags flags = builtin_desc->flags;
5764 return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
5765}
5766
Ben Murdoch61f157c2016-09-16 13:49:30 +01005767// Builder for builtins implemented in TurboFan with JS linkage.
5768Handle<Code> CodeStubAssemblerBuilderJS(Isolate* isolate,
5769 BuiltinDesc const* builtin_desc) {
Ben Murdochda12d292016-06-02 14:46:10 +01005770 Zone zone(isolate->allocator());
Ben Murdochc5610432016-08-08 18:44:38 +01005771 CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
5772 builtin_desc->flags, builtin_desc->s_name);
Ben Murdochda12d292016-06-02 14:46:10 +01005773 // Generate the code/adaptor.
Ben Murdochc5610432016-08-08 18:44:38 +01005774 typedef void (*Generator)(CodeStubAssembler*);
Ben Murdochda12d292016-06-02 14:46:10 +01005775 Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5776 g(&assembler);
5777 return assembler.GenerateCode();
5778}
5779
Ben Murdoch61f157c2016-09-16 13:49:30 +01005780// Builder for builtins implemented in TurboFan with CallStub linkage.
5781Handle<Code> CodeStubAssemblerBuilderCS(Isolate* isolate,
5782 BuiltinDesc const* builtin_desc) {
5783 Zone zone(isolate->allocator());
5784 // The interface descriptor with given key must be initialized at this point
5785 // and this construction just queries the details from the descriptors table.
5786 CallInterfaceDescriptor descriptor(
5787 isolate, static_cast<CallDescriptors::Key>(builtin_desc->argc));
5788 // Ensure descriptor is already initialized.
5789 DCHECK_NOT_NULL(descriptor.GetFunctionType());
5790 CodeStubAssembler assembler(isolate, &zone, descriptor, builtin_desc->flags,
5791 builtin_desc->s_name);
5792 // Generate the code/adaptor.
5793 typedef void (*Generator)(CodeStubAssembler*);
5794 Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5795 g(&assembler);
5796 return assembler.GenerateCode();
5797}
5798
Ben Murdochda12d292016-06-02 14:46:10 +01005799} // namespace
Steve Block44f0eee2011-05-26 01:26:41 +01005800
5801// Define array of pointers to generators and C builtin functions.
5802// We do this in a sort of roundabout way so that we can do the initialization
5803// within the lexical scope of Builtins:: and within a context where
5804// Code::Flags names a non-abstract type.
5805void Builtins::InitBuiltinFunctionTable() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005806 BuiltinDesc* functions = builtin_function_table.functions_;
Ben Murdochda12d292016-06-02 14:46:10 +01005807 functions[builtin_count].builder = nullptr;
5808 functions[builtin_count].generator = nullptr;
5809 functions[builtin_count].c_code = nullptr;
5810 functions[builtin_count].s_name = nullptr;
Steve Block44f0eee2011-05-26 01:26:41 +01005811 functions[builtin_count].name = builtin_count;
5812 functions[builtin_count].flags = static_cast<Code::Flags>(0);
Ben Murdochda12d292016-06-02 14:46:10 +01005813 functions[builtin_count].argc = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01005814
Ben Murdoch61f157c2016-09-16 13:49:30 +01005815#define DEF_FUNCTION_PTR_C(aname) \
5816 functions->builder = &MacroAssemblerBuilder; \
5817 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
5818 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
5819 functions->s_name = #aname; \
5820 functions->name = c_##aname; \
5821 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
5822 functions->argc = 0; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005823 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01005824
Ben Murdoch61f157c2016-09-16 13:49:30 +01005825#define DEF_FUNCTION_PTR_A(aname, kind, extra) \
5826 functions->builder = &MacroAssemblerBuilder; \
5827 functions->generator = FUNCTION_ADDR(Generate_##aname); \
5828 functions->c_code = NULL; \
5829 functions->s_name = #aname; \
5830 functions->name = k##aname; \
5831 functions->flags = Code::ComputeFlags(Code::kind, extra); \
5832 functions->argc = 0; \
Ben Murdochda12d292016-06-02 14:46:10 +01005833 ++functions;
5834
Ben Murdoch61f157c2016-09-16 13:49:30 +01005835#define DEF_FUNCTION_PTR_T(aname, aargc) \
5836 functions->builder = &CodeStubAssemblerBuilderJS; \
5837 functions->generator = FUNCTION_ADDR(Generate_##aname); \
5838 functions->c_code = NULL; \
5839 functions->s_name = #aname; \
5840 functions->name = k##aname; \
5841 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
5842 functions->argc = aargc; \
5843 ++functions;
5844
5845#define DEF_FUNCTION_PTR_S(aname, kind, extra, interface_descriptor) \
5846 functions->builder = &CodeStubAssemblerBuilderCS; \
5847 functions->generator = FUNCTION_ADDR(Generate_##aname); \
5848 functions->c_code = NULL; \
5849 functions->s_name = #aname; \
5850 functions->name = k##aname; \
5851 functions->flags = Code::ComputeFlags(Code::kind, extra); \
5852 functions->argc = CallDescriptors::interface_descriptor; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005853 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01005854
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005855#define DEF_FUNCTION_PTR_H(aname, kind) \
Ben Murdochda12d292016-06-02 14:46:10 +01005856 functions->builder = &MacroAssemblerBuilder; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005857 functions->generator = FUNCTION_ADDR(Generate_##aname); \
5858 functions->c_code = NULL; \
5859 functions->s_name = #aname; \
5860 functions->name = k##aname; \
5861 functions->flags = Code::ComputeHandlerFlags(Code::kind); \
Ben Murdochda12d292016-06-02 14:46:10 +01005862 functions->argc = 0; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005863 ++functions;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005864
Steve Block44f0eee2011-05-26 01:26:41 +01005865 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
5866 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
Ben Murdochda12d292016-06-02 14:46:10 +01005867 BUILTIN_LIST_T(DEF_FUNCTION_PTR_T)
Ben Murdoch61f157c2016-09-16 13:49:30 +01005868 BUILTIN_LIST_S(DEF_FUNCTION_PTR_S)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005869 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01005870 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
5871
5872#undef DEF_FUNCTION_PTR_C
5873#undef DEF_FUNCTION_PTR_A
Ben Murdochda12d292016-06-02 14:46:10 +01005874#undef DEF_FUNCTION_PTR_T
Ben Murdoch61f157c2016-09-16 13:49:30 +01005875#undef DEF_FUNCTION_PTR_S
5876#undef DEF_FUNCTION_PTR_H
Steve Block44f0eee2011-05-26 01:26:41 +01005877}
5878
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005879
5880void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
5881 DCHECK(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +00005882
5883 // Create a scope for the handles in the builtins.
Ben Murdoch8b112d22011-06-08 16:22:53 +01005884 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005885
Ben Murdoch61f157c2016-09-16 13:49:30 +01005886#define INITIALIZE_CALL_DESCRIPTOR(name, kind, extra, interface_descriptor) \
5887 { interface_descriptor##Descriptor descriptor(isolate); }
5888 BUILTIN_LIST_S(INITIALIZE_CALL_DESCRIPTOR)
5889#undef INITIALIZE_CALL_DESCRIPTOR
5890
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005891 const BuiltinDesc* functions = builtin_function_table.functions();
Steve Blocka7e24c12009-10-30 11:49:00 +00005892
Steve Blocka7e24c12009-10-30 11:49:00 +00005893 // Traverse the list of builtins and generate an adaptor in a
5894 // separate code object for each one.
5895 for (int i = 0; i < builtin_count; i++) {
5896 if (create_heap_objects) {
Ben Murdochda12d292016-06-02 14:46:10 +01005897 Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
Steve Blocka7e24c12009-10-30 11:49:00 +00005898 // Log the event and add the code to the builtins array.
Ben Murdoch8b112d22011-06-08 16:22:53 +01005899 PROFILE(isolate,
Ben Murdoch61f157c2016-09-16 13:49:30 +01005900 CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
5901 AbstractCode::cast(*code), functions[i].s_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005902 builtins_[i] = *code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005903 code->set_builtin_index(i);
Steve Blocka7e24c12009-10-30 11:49:00 +00005904#ifdef ENABLE_DISASSEMBLER
5905 if (FLAG_print_builtin_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005906 CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
5907 OFStream os(trace_scope.file());
5908 os << "Builtin: " << functions[i].s_name << "\n";
5909 code->Disassemble(functions[i].s_name, os);
5910 os << "\n";
Steve Blocka7e24c12009-10-30 11:49:00 +00005911 }
5912#endif
5913 } else {
5914 // Deserializing. The values will be filled in during IterateBuiltins.
5915 builtins_[i] = NULL;
5916 }
5917 names_[i] = functions[i].s_name;
5918 }
5919
5920 // Mark as initialized.
Steve Block44f0eee2011-05-26 01:26:41 +01005921 initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00005922}
5923
5924
5925void Builtins::TearDown() {
Steve Block44f0eee2011-05-26 01:26:41 +01005926 initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00005927}
5928
5929
5930void Builtins::IterateBuiltins(ObjectVisitor* v) {
5931 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
5932}
5933
5934
5935const char* Builtins::Lookup(byte* pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01005936 // may be called during initialization (disassembler!)
5937 if (initialized_) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005938 for (int i = 0; i < builtin_count; i++) {
5939 Code* entry = Code::cast(builtins_[i]);
5940 if (entry->contains(pc)) {
5941 return names_[i];
5942 }
5943 }
5944 }
5945 return NULL;
5946}
5947
Ben Murdochb0fe1622011-05-05 13:52:32 +01005948
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005949void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005950 masm->TailCallRuntime(Runtime::kInterrupt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005951}
5952
5953
5954void Builtins::Generate_StackCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005955 masm->TailCallRuntime(Runtime::kStackGuard);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005956}
5957
Ben Murdochc5610432016-08-08 18:44:38 +01005958namespace {
5959
5960void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
5961 compiler::Node* context,
5962 compiler::Node** out_instance_type,
5963 compiler::Node** out_backing_store) {
5964 using namespace compiler;
5965 CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a),
5966 not_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a),
5967 not_float_or_clamped(a), invalid(a);
5968
5969 // Fail if it is not a heap object.
5970 a->Branch(a->WordIsSmi(tagged), &is_smi, &not_smi);
5971 a->Bind(&is_smi);
5972 a->Goto(&invalid);
5973
5974 // Fail if the array's instance type is not JSTypedArray.
5975 a->Bind(&not_smi);
5976 a->Branch(a->WordEqual(a->LoadInstanceType(tagged),
5977 a->Int32Constant(JS_TYPED_ARRAY_TYPE)),
5978 &is_typed_array, &not_typed_array);
5979 a->Bind(&not_typed_array);
5980 a->Goto(&invalid);
5981
5982 // Fail if the array's JSArrayBuffer is not shared.
5983 a->Bind(&is_typed_array);
5984 Node* array_buffer = a->LoadObjectField(tagged, JSTypedArray::kBufferOffset);
5985 Node* is_buffer_shared = a->BitFieldDecode<JSArrayBuffer::IsShared>(
5986 a->LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldSlot));
5987 a->Branch(is_buffer_shared, &is_shared, &not_shared);
5988 a->Bind(&not_shared);
5989 a->Goto(&invalid);
5990
5991 // Fail if the array's element type is float32, float64 or clamped.
5992 a->Bind(&is_shared);
5993 Node* elements_instance_type = a->LoadInstanceType(
5994 a->LoadObjectField(tagged, JSObject::kElementsOffset));
5995 STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5996 STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5997 STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5998 STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5999 STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
6000 STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
6001 a->Branch(a->Int32LessThan(elements_instance_type,
6002 a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)),
6003 &not_float_or_clamped, &is_float_or_clamped);
6004 a->Bind(&is_float_or_clamped);
6005 a->Goto(&invalid);
6006
6007 a->Bind(&invalid);
6008 a->CallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context,
6009 tagged);
6010 a->Return(a->UndefinedConstant());
6011
6012 a->Bind(&not_float_or_clamped);
6013 *out_instance_type = elements_instance_type;
6014
6015 Node* backing_store =
6016 a->LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset);
6017 Node* byte_offset = a->ChangeUint32ToWord(a->TruncateTaggedToWord32(
6018 context,
6019 a->LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset)));
6020 *out_backing_store = a->IntPtrAdd(backing_store, byte_offset);
6021}
6022
6023// https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess
6024compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
6025 compiler::Node* tagged,
6026 compiler::Node* context) {
6027 using namespace compiler;
6028 CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32);
6029
6030 Callable to_number = CodeFactory::ToNumber(a->isolate());
6031 Node* number_index = a->CallStub(to_number, context, tagged);
6032 CodeStubAssembler::Label done(a, &var_result);
6033
6034 CodeStubAssembler::Label if_numberissmi(a), if_numberisnotsmi(a);
6035 a->Branch(a->WordIsSmi(number_index), &if_numberissmi, &if_numberisnotsmi);
6036
6037 a->Bind(&if_numberissmi);
6038 {
6039 var_result.Bind(a->SmiToWord32(number_index));
6040 a->Goto(&done);
6041 }
6042
6043 a->Bind(&if_numberisnotsmi);
6044 {
6045 Node* number_index_value = a->LoadHeapNumberValue(number_index);
6046 Node* access_index = a->TruncateFloat64ToWord32(number_index_value);
6047 Node* test_index = a->ChangeInt32ToFloat64(access_index);
6048
6049 CodeStubAssembler::Label if_indexesareequal(a), if_indexesarenotequal(a);
6050 a->Branch(a->Float64Equal(number_index_value, test_index),
6051 &if_indexesareequal, &if_indexesarenotequal);
6052
6053 a->Bind(&if_indexesareequal);
6054 {
6055 var_result.Bind(access_index);
6056 a->Goto(&done);
6057 }
6058
6059 a->Bind(&if_indexesarenotequal);
6060 a->Return(
6061 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
6062 }
6063
6064 a->Bind(&done);
6065 return var_result.value();
6066}
6067
6068void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
6069 compiler::Node* array_length_word,
6070 compiler::Node* context) {
6071 using namespace compiler;
6072 // Check if the index is in bounds. If not, throw RangeError.
6073 CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a);
6074 a->Branch(
6075 a->WordOr(a->Int32LessThan(index_word, a->Int32Constant(0)),
6076 a->Int32GreaterThanOrEqual(index_word, array_length_word)),
6077 &if_notinbounds, &if_inbounds);
6078 a->Bind(&if_notinbounds);
6079 a->Return(
6080 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
6081 a->Bind(&if_inbounds);
6082}
6083
6084} // anonymous namespace
6085
6086void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) {
6087 using namespace compiler;
6088 Node* array = a->Parameter(1);
6089 Node* index = a->Parameter(2);
6090 Node* context = a->Parameter(3 + 2);
6091
6092 Node* instance_type;
6093 Node* backing_store;
6094 ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
6095
6096 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
6097 Node* array_length_word32 = a->TruncateTaggedToWord32(
6098 context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
6099 ValidateAtomicIndex(a, index_word32, array_length_word32, context);
6100 Node* index_word = a->ChangeUint32ToWord(index_word32);
6101
6102 CodeStubAssembler::Label i8(a), u8(a), i16(a), u16(a), i32(a), u32(a),
6103 other(a);
6104 int32_t case_values[] = {
6105 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
6106 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
6107 };
6108 CodeStubAssembler::Label* case_labels[] = {
6109 &i8, &u8, &i16, &u16, &i32, &u32,
6110 };
6111 a->Switch(instance_type, &other, case_values, case_labels,
6112 arraysize(case_labels));
6113
6114 a->Bind(&i8);
6115 a->Return(
6116 a->SmiTag(a->AtomicLoad(MachineType::Int8(), backing_store, index_word)));
6117
6118 a->Bind(&u8);
6119 a->Return(a->SmiTag(
6120 a->AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
6121
6122 a->Bind(&i16);
6123 a->Return(a->SmiTag(a->AtomicLoad(MachineType::Int16(), backing_store,
6124 a->WordShl(index_word, 1))));
6125
6126 a->Bind(&u16);
6127 a->Return(a->SmiTag(a->AtomicLoad(MachineType::Uint16(), backing_store,
6128 a->WordShl(index_word, 1))));
6129
6130 a->Bind(&i32);
6131 a->Return(a->ChangeInt32ToTagged(a->AtomicLoad(
6132 MachineType::Int32(), backing_store, a->WordShl(index_word, 2))));
6133
6134 a->Bind(&u32);
6135 a->Return(a->ChangeUint32ToTagged(a->AtomicLoad(
6136 MachineType::Uint32(), backing_store, a->WordShl(index_word, 2))));
6137
6138 // This shouldn't happen, we've already validated the type.
6139 a->Bind(&other);
6140 a->Return(a->Int32Constant(0));
6141}
6142
6143void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) {
6144 using namespace compiler;
6145 Node* array = a->Parameter(1);
6146 Node* index = a->Parameter(2);
6147 Node* value = a->Parameter(3);
6148 Node* context = a->Parameter(4 + 2);
6149
6150 Node* instance_type;
6151 Node* backing_store;
6152 ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
6153
6154 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
6155 Node* array_length_word32 = a->TruncateTaggedToWord32(
6156 context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
6157 ValidateAtomicIndex(a, index_word32, array_length_word32, context);
6158 Node* index_word = a->ChangeUint32ToWord(index_word32);
6159
6160 Callable to_integer = CodeFactory::ToInteger(a->isolate());
6161 Node* value_integer = a->CallStub(to_integer, context, value);
6162 Node* value_word32 = a->TruncateTaggedToWord32(context, value_integer);
6163
6164 CodeStubAssembler::Label u8(a), u16(a), u32(a), other(a);
6165 int32_t case_values[] = {
6166 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
6167 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
6168 };
6169 CodeStubAssembler::Label* case_labels[] = {
6170 &u8, &u8, &u16, &u16, &u32, &u32,
6171 };
6172 a->Switch(instance_type, &other, case_values, case_labels,
6173 arraysize(case_labels));
6174
6175 a->Bind(&u8);
6176 a->AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
6177 value_word32);
6178 a->Return(value_integer);
6179
6180 a->Bind(&u16);
6181 a->SmiTag(a->AtomicStore(MachineRepresentation::kWord16, backing_store,
6182 a->WordShl(index_word, 1), value_word32));
6183 a->Return(value_integer);
6184
6185 a->Bind(&u32);
6186 a->AtomicStore(MachineRepresentation::kWord32, backing_store,
6187 a->WordShl(index_word, 2), value_word32);
6188 a->Return(value_integer);
6189
6190 // This shouldn't happen, we've already validated the type.
6191 a->Bind(&other);
6192 a->Return(a->Int32Constant(0));
6193}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006194
Ben Murdoch61f157c2016-09-16 13:49:30 +01006195#define DEFINE_BUILTIN_ACCESSOR_C(name) \
6196 Handle<Code> Builtins::name() { \
6197 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6198 return Handle<Code>(code_address); \
6199 }
6200#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, extra) \
6201 Handle<Code> Builtins::name() { \
6202 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6203 return Handle<Code>(code_address); \
6204 }
Ben Murdochda12d292016-06-02 14:46:10 +01006205#define DEFINE_BUILTIN_ACCESSOR_T(name, argc) \
6206 Handle<Code> Builtins::name() { \
6207 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6208 return Handle<Code>(code_address); \
6209 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01006210#define DEFINE_BUILTIN_ACCESSOR_S(name, kind, extra, interface_descriptor) \
6211 Handle<Code> Builtins::name() { \
6212 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
6213 return Handle<Code>(code_address); \
6214 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006215#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
6216Handle<Code> Builtins::name() { \
6217 Code** code_address = \
6218 reinterpret_cast<Code**>(builtin_address(k##name)); \
6219 return Handle<Code>(code_address); \
6220}
Steve Block44f0eee2011-05-26 01:26:41 +01006221BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
6222BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
Ben Murdochda12d292016-06-02 14:46:10 +01006223BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
Ben Murdoch61f157c2016-09-16 13:49:30 +01006224BUILTIN_LIST_S(DEFINE_BUILTIN_ACCESSOR_S)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006225BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01006226BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
6227#undef DEFINE_BUILTIN_ACCESSOR_C
6228#undef DEFINE_BUILTIN_ACCESSOR_A
Ben Murdochda12d292016-06-02 14:46:10 +01006229#undef DEFINE_BUILTIN_ACCESSOR_T
Ben Murdoch61f157c2016-09-16 13:49:30 +01006230#undef DEFINE_BUILTIN_ACCESSOR_S
Ben Murdochda12d292016-06-02 14:46:10 +01006231#undef DEFINE_BUILTIN_ACCESSOR_H
Steve Block44f0eee2011-05-26 01:26:41 +01006232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006233} // namespace internal
6234} // namespace v8