blob: 34b370fe664fe416f871bb7cf5d09779ca37211e [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 Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/api.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/api-natives.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/arguments.h"
10#include "src/base/once.h"
11#include "src/bootstrapper.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/dateparser-inl.h"
13#include "src/elements.h"
14#include "src/frames-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/gdb-jit.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/ic/handler-compiler.h"
17#include "src/ic/ic.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/isolate-inl.h"
19#include "src/messages.h"
20#include "src/profiler/cpu-profiler.h"
21#include "src/property-descriptor.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022#include "src/prototype.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023#include "src/string-builder.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000025
26namespace v8 {
27namespace internal {
28
Leon Clarkee46be812010-01-19 14:06:41 +000029namespace {
30
31// Arguments object passed to C++ builtins.
32template <BuiltinExtraArguments extra_args>
33class BuiltinArguments : public Arguments {
34 public:
35 BuiltinArguments(int length, Object** arguments)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 : Arguments(length, arguments) {
37 // Check we have at least the receiver.
38 DCHECK_LE(1, this->length());
39 }
Leon Clarkee46be812010-01-19 14:06:41 +000040
41 Object*& operator[] (int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042 DCHECK(index < length());
Leon Clarkee46be812010-01-19 14:06:41 +000043 return Arguments::operator[](index);
44 }
45
46 template <class S> Handle<S> at(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 DCHECK(index < length());
Leon Clarkee46be812010-01-19 14:06:41 +000048 return Arguments::at<S>(index);
49 }
50
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 Handle<Object> atOrUndefined(Isolate* isolate, int index) {
52 if (index >= length()) {
53 return isolate->factory()->undefined_value();
54 }
55 return at<Object>(index);
56 }
57
Leon Clarkee46be812010-01-19 14:06:41 +000058 Handle<Object> receiver() {
59 return Arguments::at<Object>(0);
60 }
61
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 Handle<JSFunction> target();
63 Handle<HeapObject> new_target();
Leon Clarkee46be812010-01-19 14:06:41 +000064
65 // Gets the total number of arguments including the receiver (but
66 // excluding extra arguments).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 int length() const;
Leon Clarkee46be812010-01-19 14:06:41 +000068};
69
70
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071// Specialize BuiltinArguments for the extra arguments.
Leon Clarkee46be812010-01-19 14:06:41 +000072
73template <>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
75 return Arguments::length();
76}
77
78template <>
79int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
Leon Clarkee46be812010-01-19 14:06:41 +000080 return Arguments::length() - 1;
81}
82
Leon Clarkee46be812010-01-19 14:06:41 +000083template <>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084Handle<JSFunction> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
85 return Arguments::at<JSFunction>(Arguments::length() - 1);
Leon Clarkee46be812010-01-19 14:06:41 +000086}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000087
88template <>
89int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
90 return Arguments::length() - 1;
91}
92
93template <>
94Handle<HeapObject>
95BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
96 return Arguments::at<HeapObject>(Arguments::length() - 1);
97}
98
99template <>
100int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
101 const {
102 return Arguments::length() - 2;
103}
104
105template <>
106Handle<JSFunction>
107BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
108 return Arguments::at<JSFunction>(Arguments::length() - 2);
109}
110
111template <>
112Handle<HeapObject>
113BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
114 return Arguments::at<HeapObject>(Arguments::length() - 1);
115}
Leon Clarkee46be812010-01-19 14:06:41 +0000116
117
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118#define DEF_ARG_TYPE(name, spec) \
119 typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
Leon Clarkee46be812010-01-19 14:06:41 +0000120BUILTIN_LIST_C(DEF_ARG_TYPE)
121#undef DEF_ARG_TYPE
122
Leon Clarkee46be812010-01-19 14:06:41 +0000123
Steve Blocka7e24c12009-10-30 11:49:00 +0000124// ----------------------------------------------------------------------------
Leon Clarkee46be812010-01-19 14:06:41 +0000125// Support macro for defining builtins in C++.
Steve Blocka7e24c12009-10-30 11:49:00 +0000126// ----------------------------------------------------------------------------
127//
128// A builtin function is defined by writing:
129//
130// BUILTIN(name) {
131// ...
132// }
Steve Blocka7e24c12009-10-30 11:49:00 +0000133//
Leon Clarkee46be812010-01-19 14:06:41 +0000134// In the body of the builtin function the arguments can be accessed
135// through the BuiltinArguments object args.
Steve Blocka7e24c12009-10-30 11:49:00 +0000136
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137#define BUILTIN(name) \
138 MUST_USE_RESULT static Object* Builtin_Impl_##name( \
139 name##ArgumentsType args, Isolate* isolate); \
140 MUST_USE_RESULT static Object* Builtin_##name( \
141 int args_length, Object** args_object, Isolate* isolate) { \
142 name##ArgumentsType args(args_length, args_object); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000143 return Builtin_Impl_##name(args, isolate); \
144 } \
145 MUST_USE_RESULT static Object* Builtin_Impl_##name( \
Steve Block44f0eee2011-05-26 01:26:41 +0100146 name##ArgumentsType args, Isolate* isolate)
Steve Blocka7e24c12009-10-30 11:49:00 +0000147
Steve Blocka7e24c12009-10-30 11:49:00 +0000148
149// ----------------------------------------------------------------------------
150
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151
152#define CHECK_RECEIVER(Type, name, method) \
153 if (!args.receiver()->Is##Type()) { \
154 THROW_NEW_ERROR_RETURN_FAILURE( \
155 isolate, \
156 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
157 isolate->factory()->NewStringFromAsciiChecked(method), \
158 args.receiver())); \
159 } \
160 Handle<Type> name = Handle<Type>::cast(args.receiver())
161
162
163inline bool ClampedToInteger(Object* object, int* out) {
164 // This is an extended version of ECMA-262 7.1.11 handling signed values
165 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
166 if (object->IsSmi()) {
167 *out = Smi::cast(object)->value();
168 return true;
169 } else if (object->IsHeapNumber()) {
170 double value = HeapNumber::cast(object)->value();
171 if (std::isnan(value)) {
172 *out = 0;
173 } else if (value > kMaxInt) {
174 *out = kMaxInt;
175 } else if (value < kMinInt) {
176 *out = kMinInt;
177 } else {
178 *out = static_cast<int>(value);
179 }
180 return true;
181 } else if (object->IsUndefined() || object->IsNull()) {
182 *out = 0;
183 return true;
184 } else if (object->IsBoolean()) {
185 *out = object->IsTrue();
186 return true;
187 }
188 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000189}
Steve Blocka7e24c12009-10-30 11:49:00 +0000190
191
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
193 int* out) {
194 Map* arguments_map = isolate->native_context()->sloppy_arguments_map();
195 if (object->map() != arguments_map) return false;
196 DCHECK(object->HasFastElements());
197 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
198 if (!len_obj->IsSmi()) return false;
199 *out = Max(0, Smi::cast(len_obj)->value());
200 return *out <= object->elements()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000201}
Steve Blocka7e24c12009-10-30 11:49:00 +0000202
203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204inline bool PrototypeHasNoElements(PrototypeIterator* iter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 DisallowHeapAllocation no_gc;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206 for (; !iter->IsAtEnd(); iter->Advance()) {
207 if (iter->GetCurrent()->IsJSProxy()) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 JSObject* current = iter->GetCurrent<JSObject>();
209 if (current->IsAccessCheckNeeded()) return false;
210 if (current->HasIndexedInterceptor()) return false;
211 if (current->elements()->length() != 0) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 return true;
214}
215
216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
218 JSArray* receiver) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 // If the array prototype chain is intact (and free of elements), and if the
221 // receiver's prototype is the array prototype, then we are done.
222 Object* prototype = receiver->map()->prototype();
223 if (prototype->IsJSArray() &&
224 isolate->is_initial_array_prototype(JSArray::cast(prototype)) &&
225 isolate->IsFastArrayConstructorPrototypeChainIntact()) {
226 return true;
227 }
228
229 // Slow case.
230 PrototypeIterator iter(isolate, receiver);
231 return PrototypeHasNoElements(&iter);
Steve Block6ded16b2010-05-10 14:33:55 +0100232}
233
234
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235// Returns empty handle if not applicable.
John Reck59135872010-11-02 12:39:01 -0700236MUST_USE_RESULT
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
238 Isolate* isolate, Handle<Object> receiver, Arguments* args,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 int first_added_arg) {
240 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
241 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
242 // If there may be elements accessors in the prototype chain, the fast path
243 // cannot be used if there arguments to add to the array.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400244 Heap* heap = isolate->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 return MaybeHandle<FixedArrayBase>();
247 }
248 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
249 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
250 Handle<FixedArrayBase> elms(array->elements(), isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100251 Map* map = elms->map();
252 if (map == heap->fixed_array_map()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 if (args == NULL || array->HasFastObjectElements()) return elms;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100254 } else if (map == heap->fixed_cow_array_map()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 elms = JSObject::EnsureWritableFastElements(array);
256 if (args == NULL || array->HasFastObjectElements()) return elms;
257 } else if (map == heap->fixed_double_array_map()) {
258 if (args == NULL) return elms;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100259 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 return MaybeHandle<FixedArrayBase>();
Steve Block6ded16b2010-05-10 14:33:55 +0100261 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100262
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 // Adding elements to the array prototype would break code that makes sure
264 // it has no elements. Handle that elsewhere.
265 if (isolate->IsAnyInitialArrayPrototype(array)) {
266 return MaybeHandle<FixedArrayBase>();
267 }
268
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100269 // Need to ensure that the arguments passed in args can be contained in
270 // the array.
271 int args_length = args->length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 if (first_added_arg >= args_length) return handle(array->elements(), isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100273
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 ElementsKind origin_kind = array->map()->elements_kind();
275 DCHECK(!IsFastObjectElementsKind(origin_kind));
276 ElementsKind target_kind = origin_kind;
277 {
278 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 int arg_count = args_length - first_added_arg;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1);
281 for (int i = 0; i < arg_count; i++) {
282 Object* arg = arguments[i];
283 if (arg->IsHeapObject()) {
284 if (arg->IsHeapNumber()) {
285 target_kind = FAST_DOUBLE_ELEMENTS;
286 } else {
287 target_kind = FAST_ELEMENTS;
288 break;
289 }
290 }
291 }
292 }
293 if (target_kind != origin_kind) {
294 JSObject::TransitionElementsKind(array, target_kind);
295 return handle(array->elements(), isolate);
296 }
297 return elms;
Steve Block6ded16b2010-05-10 14:33:55 +0100298}
299
300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301MUST_USE_RESULT static Object* CallJsIntrinsic(
302 Isolate* isolate, Handle<JSFunction> function,
303 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100304 HandleScope handleScope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100305 int argc = args.length() - 1;
306 ScopedVector<Handle<Object> > argv(argc);
307 for (int i = 0; i < argc; ++i) {
308 argv[i] = args.at<Object>(i + 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100309 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 Handle<Object> result;
311 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
312 isolate, result,
313 Execution::Call(isolate,
314 function,
315 args.receiver(),
316 argc,
317 argv.start()));
Steve Block6ded16b2010-05-10 14:33:55 +0100318 return *result;
319}
320
321
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322} // namespace
323
324
325BUILTIN(Illegal) {
326 UNREACHABLE();
327 return isolate->heap()->undefined_value(); // Make compiler happy.
328}
329
330
331BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
332
333
Steve Blocka7e24c12009-10-30 11:49:00 +0000334BUILTIN(ArrayPush) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 HandleScope scope(isolate);
336 Handle<Object> receiver = args.receiver();
337 MaybeHandle<FixedArrayBase> maybe_elms_obj =
338 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
339 Handle<FixedArrayBase> elms_obj;
340 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 return CallJsIntrinsic(isolate, isolate->array_push(), args);
John Reck59135872010-11-02 12:39:01 -0700342 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 // Fast Elements Path
344 int push_size = args.length() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 int len = Smi::cast(array->length())->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 if (push_size == 0) {
348 return Smi::FromInt(len);
349 }
350 if (push_size > 0 &&
351 JSArray::WouldChangeReadOnlyLength(array, len + push_size)) {
352 return CallJsIntrinsic(isolate, isolate->array_push(), args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000353 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354 DCHECK(!array->map()->is_observed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 ElementsAccessor* accessor = array->GetElementsAccessor();
356 int new_length = accessor->Push(array, elms_obj, &args, push_size);
357 return Smi::FromInt(new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000358}
Steve Blocka7e24c12009-10-30 11:49:00 +0000359
360
361BUILTIN(ArrayPop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 HandleScope scope(isolate);
363 Handle<Object> receiver = args.receiver();
364 MaybeHandle<FixedArrayBase> maybe_elms_obj =
365 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
366 Handle<FixedArrayBase> elms_obj;
367 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
John Reck59135872010-11-02 12:39:01 -0700369 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370
371 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
372 DCHECK(!array->map()->is_observed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000373
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000375 if (len == 0) return isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000376
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400377 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000378 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400379 }
380
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 Handle<Object> result;
382 if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
383 // Fast Elements Path
384 result = array->GetElementsAccessor()->Pop(array, elms_obj);
385 } else {
386 // Use Slow Lookup otherwise
387 uint32_t new_length = len - 1;
388 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
389 isolate, result, Object::GetElement(isolate, array, new_length));
390 JSArray::SetLength(array, new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 return *result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000393}
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
395
Andrei Popescu402d9372010-02-26 13:31:12 +0000396BUILTIN(ArrayShift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100398 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 Handle<Object> receiver = args.receiver();
400 MaybeHandle<FixedArrayBase> maybe_elms_obj =
401 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
402 Handle<FixedArrayBase> elms_obj;
403 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
405 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100406 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
408 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000409
410 int len = Smi::cast(array->length())->value();
Steve Block44f0eee2011-05-26 01:26:41 +0100411 if (len == 0) return heap->undefined_value();
Andrei Popescu402d9372010-02-26 13:31:12 +0000412
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400413 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400415 }
416
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417 Handle<Object> first = array->GetElementsAccessor()->Shift(array, elms_obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418 return *first;
Andrei Popescu402d9372010-02-26 13:31:12 +0000419}
420
421
422BUILTIN(ArrayUnshift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000423 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 Handle<Object> receiver = args.receiver();
425 MaybeHandle<FixedArrayBase> maybe_elms_obj =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400426 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000427 Handle<FixedArrayBase> elms_obj;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400428 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100430 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
432 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000433 int to_add = args.length() - 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 if (to_add == 0) {
435 return array->length();
436 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000437 // Currently fixed arrays cannot grow too big, so
438 // we should never hit this case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 DCHECK(to_add <= (Smi::kMaxValue - Smi::cast(array->length())->value()));
Andrei Popescu402d9372010-02-26 13:31:12 +0000440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 if (to_add > 0 && JSArray::HasReadOnlyLength(array)) {
442 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 }
444
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 ElementsAccessor* accessor = array->GetElementsAccessor();
446 int new_length = accessor->Unshift(array, elms_obj, &args, to_add);
Andrei Popescu402d9372010-02-26 13:31:12 +0000447 return Smi::FromInt(new_length);
448}
449
450
Andrei Popescu402d9372010-02-26 13:31:12 +0000451BUILTIN(ArraySlice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000453 Handle<Object> receiver = args.receiver();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 Handle<JSObject> object;
455 Handle<FixedArrayBase> elms_obj;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100456 int len = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 int relative_start = 0;
458 int relative_end = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 bool is_sloppy_arguments = false;
460
461 // TODO(littledan): Look up @@species only once, not once here and
462 // again in the JS builtin. Pass the species out?
463 Handle<Object> species;
464 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
465 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
466 if (*species != isolate->context()->native_context()->array_function()) {
467 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
468 }
469 if (receiver->IsJSArray()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 JSArray* array = JSArray::cast(*receiver);
472 if (!array->HasFastElements() ||
473 !IsJSArrayFastElementMovingAllowed(isolate, array)) {
474 AllowHeapAllocation allow_allocation;
475 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Steve Block9fac8402011-05-12 15:51:54 +0100476 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 len = Smi::cast(array->length())->value();
478 object = Handle<JSObject>::cast(receiver);
479 elms_obj = handle(array->elements(), isolate);
480 } else if (receiver->IsJSObject() &&
481 GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
482 &len)) {
483 // Array.prototype.slice(arguments, ...) is quite a common idiom
484 // (notably more than 50% of invocations in Web apps).
485 // Treat it in C++ as well.
486 is_sloppy_arguments = true;
487 object = Handle<JSObject>::cast(receiver);
488 elms_obj = handle(object->elements(), isolate);
489 } else {
490 AllowHeapAllocation allow_allocation;
491 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
492 }
493 DCHECK(len >= 0);
494 int argument_count = args.length() - 1;
495 // Note carefully chosen defaults---if argument is missing,
496 // it's undefined which gets converted to 0 for relative_start
497 // and to len for relative_end.
498 relative_start = 0;
499 relative_end = len;
500 if (argument_count > 0) {
501 DisallowHeapAllocation no_gc;
502 if (!ClampedToInteger(args[1], &relative_start)) {
503 AllowHeapAllocation allow_allocation;
504 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
505 }
506 if (argument_count > 1) {
507 Object* end_arg = args[2];
508 // slice handles the end_arg specially
509 if (end_arg->IsUndefined()) {
510 relative_end = len;
511 } else if (!ClampedToInteger(end_arg, &relative_end)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000515 }
516 }
517
518 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
520 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000521
522 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523 uint32_t actual_end =
524 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526 if (actual_end <= actual_start) {
527 Handle<JSArray> result_array = isolate->factory()->NewJSArray(
528 GetPackedElementsKind(object->GetElementsKind()), 0, 0);
529 return *result_array;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 }
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100531
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 ElementsAccessor* accessor = object->GetElementsAccessor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 if (is_sloppy_arguments &&
534 !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) {
535 // Don't deal with arguments with holes in C++
536 AllowHeapAllocation allow_allocation;
537 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
538 }
539 Handle<JSArray> result_array =
540 accessor->Slice(object, elms_obj, actual_start, actual_end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000541 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000542}
543
544
545BUILTIN(ArraySplice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 Handle<Object> receiver = args.receiver();
548 MaybeHandle<FixedArrayBase> maybe_elms_obj =
549 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
550 Handle<FixedArrayBase> elms_obj;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400551 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
553 }
554 // TODO(littledan): Look up @@species only once, not once here and
555 // again in the JS builtin. Pass the species out?
556 Handle<Object> species;
557 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
558 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
559 if (*species != isolate->context()->native_context()->array_function()) {
560 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100561 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
563 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000564
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 int argument_count = args.length() - 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100566 int relative_start = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 if (argument_count > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 if (!ClampedToInteger(args[1], &relative_start)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100572 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000573 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 int len = Smi::cast(array->length())->value();
575 // clip relative start to [0, len]
Steve Block6ded16b2010-05-10 14:33:55 +0100576 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
577 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000578
Steve Block1e0659c2011-05-24 12:43:12 +0100579 int actual_delete_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 if (argument_count == 1) {
581 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
582 // given as a request to delete all the elements from the start.
583 // And it differs from the case of undefined delete count.
584 // This does not follow ECMA-262, but we do the same for compatibility.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000585 DCHECK(len - actual_start >= 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100586 actual_delete_count = len - actual_start;
587 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 int delete_count = 0;
589 DisallowHeapAllocation no_gc;
590 if (argument_count > 1) {
591 if (!ClampedToInteger(args[2], &delete_count)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100594 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000595 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
Andrei Popescu402d9372010-02-26 13:31:12 +0000597 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599 int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
600 int new_length = len - actual_delete_count + add_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400602 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
603 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400605 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000606 ElementsAccessor* accessor = array->GetElementsAccessor();
607 Handle<JSArray> result_array = accessor->Splice(
608 array, elms_obj, actual_start, actual_delete_count, &args, add_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000610}
611
612
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613// Array Concat -------------------------------------------------------------
Steve Block6ded16b2010-05-10 14:33:55 +0100614
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615namespace {
616
617/**
618 * A simple visitor visits every element of Array's.
619 * The backend storage can be a fixed array for fast elements case,
620 * or a dictionary for sparse array. Since Dictionary is a subtype
621 * of FixedArray, the class can be used by both fast and slow cases.
622 * The second parameter of the constructor, fast_elements, specifies
623 * whether the storage is a FixedArray or Dictionary.
624 *
625 * An index limit is used to deal with the situation that a result array
626 * length overflows 32-bit non-negative integer.
627 */
628class ArrayConcatVisitor {
629 public:
630 ArrayConcatVisitor(Isolate* isolate, Handle<FixedArray> storage,
631 bool fast_elements)
632 : isolate_(isolate),
633 storage_(Handle<FixedArray>::cast(
634 isolate->global_handles()->Create(*storage))),
635 index_offset_(0u),
636 bit_field_(FastElementsField::encode(fast_elements) |
637 ExceedsLimitField::encode(false)) {}
638
639 ~ArrayConcatVisitor() { clear_storage(); }
640
641 void visit(uint32_t i, Handle<Object> elm) {
642 if (i >= JSObject::kMaxElementCount - index_offset_) {
643 set_exceeds_array_limit(true);
644 return;
645 }
646 uint32_t index = index_offset_ + i;
647
648 if (fast_elements()) {
649 if (index < static_cast<uint32_t>(storage_->length())) {
650 storage_->set(index, *elm);
651 return;
652 }
653 // Our initial estimate of length was foiled, possibly by
654 // getters on the arrays increasing the length of later arrays
655 // during iteration.
656 // This shouldn't happen in anything but pathological cases.
657 SetDictionaryMode();
658 // Fall-through to dictionary mode.
659 }
660 DCHECK(!fast_elements());
661 Handle<SeededNumberDictionary> dict(
662 SeededNumberDictionary::cast(*storage_));
663 // The object holding this backing store has just been allocated, so
664 // it cannot yet be used as a prototype.
665 Handle<SeededNumberDictionary> result =
666 SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
667 if (!result.is_identical_to(dict)) {
668 // Dictionary needed to grow.
669 clear_storage();
670 set_storage(*result);
671 }
672 }
673
674 void increase_index_offset(uint32_t delta) {
675 if (JSObject::kMaxElementCount - index_offset_ < delta) {
676 index_offset_ = JSObject::kMaxElementCount;
677 } else {
678 index_offset_ += delta;
679 }
680 // If the initial length estimate was off (see special case in visit()),
681 // but the array blowing the limit didn't contain elements beyond the
682 // provided-for index range, go to dictionary mode now.
683 if (fast_elements() &&
684 index_offset_ >
685 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
686 SetDictionaryMode();
687 }
688 }
689
690 bool exceeds_array_limit() const {
691 return ExceedsLimitField::decode(bit_field_);
692 }
693
694 Handle<JSArray> ToArray() {
695 Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
696 Handle<Object> length =
697 isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
698 Handle<Map> map = JSObject::GetElementsTransitionMap(
699 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
700 array->set_map(*map);
701 array->set_length(*length);
702 array->set_elements(*storage_);
703 return array;
704 }
705
706 private:
707 // Convert storage to dictionary mode.
708 void SetDictionaryMode() {
709 DCHECK(fast_elements());
710 Handle<FixedArray> current_storage(*storage_);
711 Handle<SeededNumberDictionary> slow_storage(
712 SeededNumberDictionary::New(isolate_, current_storage->length()));
713 uint32_t current_length = static_cast<uint32_t>(current_storage->length());
714 for (uint32_t i = 0; i < current_length; i++) {
715 HandleScope loop_scope(isolate_);
716 Handle<Object> element(current_storage->get(i), isolate_);
717 if (!element->IsTheHole()) {
718 // The object holding this backing store has just been allocated, so
719 // it cannot yet be used as a prototype.
720 Handle<SeededNumberDictionary> new_storage =
721 SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
722 false);
723 if (!new_storage.is_identical_to(slow_storage)) {
724 slow_storage = loop_scope.CloseAndEscape(new_storage);
725 }
726 }
727 }
728 clear_storage();
729 set_storage(*slow_storage);
730 set_fast_elements(false);
731 }
732
733 inline void clear_storage() {
734 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
735 }
736
737 inline void set_storage(FixedArray* storage) {
738 storage_ =
739 Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage));
740 }
741
742 class FastElementsField : public BitField<bool, 0, 1> {};
743 class ExceedsLimitField : public BitField<bool, 1, 1> {};
744
745 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
746 void set_fast_elements(bool fast) {
747 bit_field_ = FastElementsField::update(bit_field_, fast);
748 }
749 void set_exceeds_array_limit(bool exceeds) {
750 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
751 }
752
753 Isolate* isolate_;
754 Handle<FixedArray> storage_; // Always a global handle.
755 // Index after last seen index. Always less than or equal to
756 // JSObject::kMaxElementCount.
757 uint32_t index_offset_;
758 uint32_t bit_field_;
759};
760
761
762uint32_t EstimateElementCount(Handle<JSArray> array) {
763 uint32_t length = static_cast<uint32_t>(array->length()->Number());
764 int element_count = 0;
765 switch (array->GetElementsKind()) {
766 case FAST_SMI_ELEMENTS:
767 case FAST_HOLEY_SMI_ELEMENTS:
768 case FAST_ELEMENTS:
769 case FAST_HOLEY_ELEMENTS: {
770 // Fast elements can't have lengths that are not representable by
771 // a 32-bit signed integer.
772 DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
773 int fast_length = static_cast<int>(length);
774 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
775 for (int i = 0; i < fast_length; i++) {
776 if (!elements->get(i)->IsTheHole()) element_count++;
777 }
778 break;
779 }
780 case FAST_DOUBLE_ELEMENTS:
781 case FAST_HOLEY_DOUBLE_ELEMENTS: {
782 // Fast elements can't have lengths that are not representable by
783 // a 32-bit signed integer.
784 DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
785 int fast_length = static_cast<int>(length);
786 if (array->elements()->IsFixedArray()) {
787 DCHECK(FixedArray::cast(array->elements())->length() == 0);
788 break;
789 }
790 Handle<FixedDoubleArray> elements(
791 FixedDoubleArray::cast(array->elements()));
792 for (int i = 0; i < fast_length; i++) {
793 if (!elements->is_the_hole(i)) element_count++;
794 }
795 break;
796 }
797 case DICTIONARY_ELEMENTS: {
798 Handle<SeededNumberDictionary> dictionary(
799 SeededNumberDictionary::cast(array->elements()));
800 int capacity = dictionary->Capacity();
801 for (int i = 0; i < capacity; i++) {
802 Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
803 if (dictionary->IsKey(*key)) {
804 element_count++;
805 }
806 }
807 break;
808 }
809 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
810 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
811#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
812
813 TYPED_ARRAYS(TYPED_ARRAY_CASE)
814#undef TYPED_ARRAY_CASE
815 // External arrays are always dense.
816 return length;
817 }
818 // As an estimate, we assume that the prototype doesn't contain any
819 // inherited elements.
820 return element_count;
821}
822
823
824template <class ExternalArrayClass, class ElementType>
825void IterateTypedArrayElements(Isolate* isolate, Handle<JSObject> receiver,
826 bool elements_are_ints,
827 bool elements_are_guaranteed_smis,
828 ArrayConcatVisitor* visitor) {
829 Handle<ExternalArrayClass> array(
830 ExternalArrayClass::cast(receiver->elements()));
831 uint32_t len = static_cast<uint32_t>(array->length());
832
833 DCHECK(visitor != NULL);
834 if (elements_are_ints) {
835 if (elements_are_guaranteed_smis) {
836 for (uint32_t j = 0; j < len; j++) {
837 HandleScope loop_scope(isolate);
838 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
839 isolate);
840 visitor->visit(j, e);
841 }
842 } else {
843 for (uint32_t j = 0; j < len; j++) {
844 HandleScope loop_scope(isolate);
845 int64_t val = static_cast<int64_t>(array->get_scalar(j));
846 if (Smi::IsValid(static_cast<intptr_t>(val))) {
847 Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
848 visitor->visit(j, e);
849 } else {
850 Handle<Object> e =
851 isolate->factory()->NewNumber(static_cast<ElementType>(val));
852 visitor->visit(j, e);
853 }
854 }
855 }
856 } else {
857 for (uint32_t j = 0; j < len; j++) {
858 HandleScope loop_scope(isolate);
859 Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
860 visitor->visit(j, e);
861 }
862 }
863}
864
865
866// Used for sorting indices in a List<uint32_t>.
867int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
868 uint32_t a = *ap;
869 uint32_t b = *bp;
870 return (a == b) ? 0 : (a < b) ? -1 : 1;
871}
872
873
874void CollectElementIndices(Handle<JSObject> object, uint32_t range,
875 List<uint32_t>* indices) {
876 Isolate* isolate = object->GetIsolate();
877 ElementsKind kind = object->GetElementsKind();
878 switch (kind) {
879 case FAST_SMI_ELEMENTS:
880 case FAST_ELEMENTS:
881 case FAST_HOLEY_SMI_ELEMENTS:
882 case FAST_HOLEY_ELEMENTS: {
883 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
884 uint32_t length = static_cast<uint32_t>(elements->length());
885 if (range < length) length = range;
886 for (uint32_t i = 0; i < length; i++) {
887 if (!elements->get(i)->IsTheHole()) {
888 indices->Add(i);
889 }
890 }
891 break;
892 }
893 case FAST_HOLEY_DOUBLE_ELEMENTS:
894 case FAST_DOUBLE_ELEMENTS: {
895 if (object->elements()->IsFixedArray()) {
896 DCHECK(object->elements()->length() == 0);
897 break;
898 }
899 Handle<FixedDoubleArray> elements(
900 FixedDoubleArray::cast(object->elements()));
901 uint32_t length = static_cast<uint32_t>(elements->length());
902 if (range < length) length = range;
903 for (uint32_t i = 0; i < length; i++) {
904 if (!elements->is_the_hole(i)) {
905 indices->Add(i);
906 }
907 }
908 break;
909 }
910 case DICTIONARY_ELEMENTS: {
911 Handle<SeededNumberDictionary> dict(
912 SeededNumberDictionary::cast(object->elements()));
913 uint32_t capacity = dict->Capacity();
914 for (uint32_t j = 0; j < capacity; j++) {
915 HandleScope loop_scope(isolate);
916 Handle<Object> k(dict->KeyAt(j), isolate);
917 if (dict->IsKey(*k)) {
918 DCHECK(k->IsNumber());
919 uint32_t index = static_cast<uint32_t>(k->Number());
920 if (index < range) {
921 indices->Add(index);
922 }
923 }
924 }
925 break;
926 }
927#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
928
929 TYPED_ARRAYS(TYPED_ARRAY_CASE)
930#undef TYPED_ARRAY_CASE
931 {
932 uint32_t length = static_cast<uint32_t>(
933 FixedArrayBase::cast(object->elements())->length());
934 if (range <= length) {
935 length = range;
936 // We will add all indices, so we might as well clear it first
937 // and avoid duplicates.
938 indices->Clear();
939 }
940 for (uint32_t i = 0; i < length; i++) {
941 indices->Add(i);
942 }
943 if (length == range) return; // All indices accounted for already.
944 break;
945 }
946 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
947 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
948 ElementsAccessor* accessor = object->GetElementsAccessor();
949 for (uint32_t i = 0; i < range; i++) {
950 if (accessor->HasElement(object, i)) {
951 indices->Add(i);
952 }
953 }
954 break;
955 }
956 }
957
958 PrototypeIterator iter(isolate, object);
959 if (!iter.IsAtEnd()) {
960 // The prototype will usually have no inherited element indices,
961 // but we have to check.
962 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
963 indices);
964 }
965}
966
967
968bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
969 uint32_t length, ArrayConcatVisitor* visitor) {
970 for (uint32_t i = 0; i < length; ++i) {
971 HandleScope loop_scope(isolate);
972 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
973 if (!maybe.IsJust()) return false;
974 if (maybe.FromJust()) {
975 Handle<Object> element_value;
976 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value,
977 Object::GetElement(isolate, receiver, i),
978 false);
979 visitor->visit(i, element_value);
980 }
981 }
982 visitor->increase_index_offset(length);
983 return true;
984}
985
986
987/**
988 * A helper function that visits "array" elements of a JSReceiver in numerical
989 * order.
990 *
991 * The visitor argument called for each existing element in the array
992 * with the element index and the element's value.
993 * Afterwards it increments the base-index of the visitor by the array
994 * length.
995 * Returns false if any access threw an exception, otherwise true.
996 */
997bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
998 ArrayConcatVisitor* visitor) {
999 uint32_t length = 0;
1000
1001 if (receiver->IsJSArray()) {
1002 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
1003 length = static_cast<uint32_t>(array->length()->Number());
1004 } else {
1005 Handle<Object> val;
1006 Handle<Object> key = isolate->factory()->length_string();
1007 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1008 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
1009 false);
1010 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
1011 Object::ToLength(isolate, val), false);
1012 // TODO(caitp): Support larger element indexes (up to 2^53-1).
1013 if (!val->ToUint32(&length)) {
1014 length = 0;
1015 }
1016 }
1017
1018 if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) {
1019 // For classes which are not known to be safe to access via elements alone,
1020 // use the slow case.
1021 return IterateElementsSlow(isolate, receiver, length, visitor);
1022 }
1023 Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1024
1025 switch (array->GetElementsKind()) {
1026 case FAST_SMI_ELEMENTS:
1027 case FAST_ELEMENTS:
1028 case FAST_HOLEY_SMI_ELEMENTS:
1029 case FAST_HOLEY_ELEMENTS: {
1030 // Run through the elements FixedArray and use HasElement and GetElement
1031 // to check the prototype for missing elements.
1032 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1033 int fast_length = static_cast<int>(length);
1034 DCHECK(fast_length <= elements->length());
1035 for (int j = 0; j < fast_length; j++) {
1036 HandleScope loop_scope(isolate);
1037 Handle<Object> element_value(elements->get(j), isolate);
1038 if (!element_value->IsTheHole()) {
1039 visitor->visit(j, element_value);
1040 } else {
1041 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1042 if (!maybe.IsJust()) return false;
1043 if (maybe.FromJust()) {
1044 // Call GetElement on array, not its prototype, or getters won't
1045 // have the correct receiver.
1046 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1047 isolate, element_value, Object::GetElement(isolate, array, j),
1048 false);
1049 visitor->visit(j, element_value);
1050 }
1051 }
1052 }
1053 break;
1054 }
1055 case FAST_HOLEY_DOUBLE_ELEMENTS:
1056 case FAST_DOUBLE_ELEMENTS: {
1057 // Empty array is FixedArray but not FixedDoubleArray.
1058 if (length == 0) break;
1059 // Run through the elements FixedArray and use HasElement and GetElement
1060 // to check the prototype for missing elements.
1061 if (array->elements()->IsFixedArray()) {
1062 DCHECK(array->elements()->length() == 0);
1063 break;
1064 }
1065 Handle<FixedDoubleArray> elements(
1066 FixedDoubleArray::cast(array->elements()));
1067 int fast_length = static_cast<int>(length);
1068 DCHECK(fast_length <= elements->length());
1069 for (int j = 0; j < fast_length; j++) {
1070 HandleScope loop_scope(isolate);
1071 if (!elements->is_the_hole(j)) {
1072 double double_value = elements->get_scalar(j);
1073 Handle<Object> element_value =
1074 isolate->factory()->NewNumber(double_value);
1075 visitor->visit(j, element_value);
1076 } else {
1077 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1078 if (!maybe.IsJust()) return false;
1079 if (maybe.FromJust()) {
1080 // Call GetElement on array, not its prototype, or getters won't
1081 // have the correct receiver.
1082 Handle<Object> element_value;
1083 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1084 isolate, element_value, Object::GetElement(isolate, array, j),
1085 false);
1086 visitor->visit(j, element_value);
1087 }
1088 }
1089 }
1090 break;
1091 }
1092 case DICTIONARY_ELEMENTS: {
1093 // CollectElementIndices() can't be called when there's a JSProxy
1094 // on the prototype chain.
1095 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd();
1096 iter.Advance()) {
1097 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1098 return IterateElementsSlow(isolate, array, length, visitor);
1099 }
1100 }
1101 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1102 List<uint32_t> indices(dict->Capacity() / 2);
1103 // Collect all indices in the object and the prototypes less
1104 // than length. This might introduce duplicates in the indices list.
1105 CollectElementIndices(array, length, &indices);
1106 indices.Sort(&compareUInt32);
1107 int j = 0;
1108 int n = indices.length();
1109 while (j < n) {
1110 HandleScope loop_scope(isolate);
1111 uint32_t index = indices[j];
1112 Handle<Object> element;
1113 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1114 isolate, element, Object::GetElement(isolate, array, index), false);
1115 visitor->visit(index, element);
1116 // Skip to next different index (i.e., omit duplicates).
1117 do {
1118 j++;
1119 } while (j < n && indices[j] == index);
1120 }
1121 break;
1122 }
1123 case UINT8_CLAMPED_ELEMENTS: {
1124 Handle<FixedUint8ClampedArray> pixels(
1125 FixedUint8ClampedArray::cast(array->elements()));
1126 for (uint32_t j = 0; j < length; j++) {
1127 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
1128 visitor->visit(j, e);
1129 }
1130 break;
1131 }
1132 case INT8_ELEMENTS: {
1133 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true,
1134 true, visitor);
1135 break;
1136 }
1137 case UINT8_ELEMENTS: {
1138 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true,
1139 true, visitor);
1140 break;
1141 }
1142 case INT16_ELEMENTS: {
1143 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true,
1144 true, visitor);
1145 break;
1146 }
1147 case UINT16_ELEMENTS: {
1148 IterateTypedArrayElements<FixedUint16Array, uint16_t>(
1149 isolate, array, true, true, visitor);
1150 break;
1151 }
1152 case INT32_ELEMENTS: {
1153 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true,
1154 false, visitor);
1155 break;
1156 }
1157 case UINT32_ELEMENTS: {
1158 IterateTypedArrayElements<FixedUint32Array, uint32_t>(
1159 isolate, array, true, false, visitor);
1160 break;
1161 }
1162 case FLOAT32_ELEMENTS: {
1163 IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false,
1164 false, visitor);
1165 break;
1166 }
1167 case FLOAT64_ELEMENTS: {
1168 IterateTypedArrayElements<FixedFloat64Array, double>(
1169 isolate, array, false, false, visitor);
1170 break;
1171 }
1172 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1173 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1174 for (uint32_t index = 0; index < length; index++) {
1175 HandleScope loop_scope(isolate);
1176 Handle<Object> element;
1177 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1178 isolate, element, Object::GetElement(isolate, array, index), false);
1179 visitor->visit(index, element);
1180 }
1181 break;
1182 }
1183 }
1184 visitor->increase_index_offset(length);
1185 return true;
1186}
1187
1188
1189bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
1190 DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact());
1191 if (!FLAG_harmony_concat_spreadable) return false;
1192 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1193 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1194 return maybe.FromMaybe(false);
1195}
1196
1197
1198static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1199 HandleScope handle_scope(isolate);
1200 if (!obj->IsJSReceiver()) return Just(false);
1201 if (FLAG_harmony_concat_spreadable) {
1202 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1203 Handle<Object> value;
1204 MaybeHandle<Object> maybeValue =
1205 i::Runtime::GetObjectProperty(isolate, obj, key);
1206 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1207 if (!value->IsUndefined()) return Just(value->BooleanValue());
1208 }
1209 return Object::IsArray(obj);
1210}
1211
1212
1213Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
1214 int argument_count = args->length();
1215
1216 // Pass 1: estimate the length and number of elements of the result.
1217 // The actual length can be larger if any of the arguments have getters
1218 // that mutate other arguments (but will otherwise be precise).
1219 // The number of elements is precise if there are no inherited elements.
1220
1221 ElementsKind kind = FAST_SMI_ELEMENTS;
1222
1223 uint32_t estimate_result_length = 0;
1224 uint32_t estimate_nof_elements = 0;
1225 for (int i = 0; i < argument_count; i++) {
1226 HandleScope loop_scope(isolate);
1227 Handle<Object> obj((*args)[i], isolate);
1228 uint32_t length_estimate;
1229 uint32_t element_estimate;
1230 if (obj->IsJSArray()) {
1231 Handle<JSArray> array(Handle<JSArray>::cast(obj));
1232 length_estimate = static_cast<uint32_t>(array->length()->Number());
1233 if (length_estimate != 0) {
1234 ElementsKind array_kind =
1235 GetPackedElementsKind(array->map()->elements_kind());
1236 kind = GetMoreGeneralElementsKind(kind, array_kind);
1237 }
1238 element_estimate = EstimateElementCount(array);
1239 } else {
1240 if (obj->IsHeapObject()) {
1241 if (obj->IsNumber()) {
1242 kind = GetMoreGeneralElementsKind(kind, FAST_DOUBLE_ELEMENTS);
1243 } else {
1244 kind = GetMoreGeneralElementsKind(kind, FAST_ELEMENTS);
1245 }
1246 }
1247 length_estimate = 1;
1248 element_estimate = 1;
1249 }
1250 // Avoid overflows by capping at kMaxElementCount.
1251 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1252 estimate_result_length = JSObject::kMaxElementCount;
1253 } else {
1254 estimate_result_length += length_estimate;
1255 }
1256 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1257 estimate_nof_elements = JSObject::kMaxElementCount;
1258 } else {
1259 estimate_nof_elements += element_estimate;
1260 }
1261 }
1262
1263 // If estimated number of elements is more than half of length, a
1264 // fixed array (fast case) is more time and space-efficient than a
1265 // dictionary.
1266 bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
1267
1268 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1269 Handle<FixedArrayBase> storage =
1270 isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1271 int j = 0;
1272 bool failure = false;
1273 if (estimate_result_length > 0) {
1274 Handle<FixedDoubleArray> double_storage =
1275 Handle<FixedDoubleArray>::cast(storage);
1276 for (int i = 0; i < argument_count; i++) {
1277 Handle<Object> obj((*args)[i], isolate);
1278 if (obj->IsSmi()) {
1279 double_storage->set(j, Smi::cast(*obj)->value());
1280 j++;
1281 } else if (obj->IsNumber()) {
1282 double_storage->set(j, obj->Number());
1283 j++;
1284 } else {
1285 JSArray* array = JSArray::cast(*obj);
1286 uint32_t length = static_cast<uint32_t>(array->length()->Number());
1287 switch (array->map()->elements_kind()) {
1288 case FAST_HOLEY_DOUBLE_ELEMENTS:
1289 case FAST_DOUBLE_ELEMENTS: {
1290 // Empty array is FixedArray but not FixedDoubleArray.
1291 if (length == 0) break;
1292 FixedDoubleArray* elements =
1293 FixedDoubleArray::cast(array->elements());
1294 for (uint32_t i = 0; i < length; i++) {
1295 if (elements->is_the_hole(i)) {
1296 // TODO(jkummerow/verwaest): We could be a bit more clever
1297 // here: Check if there are no elements/getters on the
1298 // prototype chain, and if so, allow creation of a holey
1299 // result array.
1300 // Same thing below (holey smi case).
1301 failure = true;
1302 break;
1303 }
1304 double double_value = elements->get_scalar(i);
1305 double_storage->set(j, double_value);
1306 j++;
1307 }
1308 break;
1309 }
1310 case FAST_HOLEY_SMI_ELEMENTS:
1311 case FAST_SMI_ELEMENTS: {
1312 FixedArray* elements(FixedArray::cast(array->elements()));
1313 for (uint32_t i = 0; i < length; i++) {
1314 Object* element = elements->get(i);
1315 if (element->IsTheHole()) {
1316 failure = true;
1317 break;
1318 }
1319 int32_t int_value = Smi::cast(element)->value();
1320 double_storage->set(j, int_value);
1321 j++;
1322 }
1323 break;
1324 }
1325 case FAST_HOLEY_ELEMENTS:
1326 case FAST_ELEMENTS:
1327 case DICTIONARY_ELEMENTS:
1328 DCHECK_EQ(0u, length);
1329 break;
1330 default:
1331 UNREACHABLE();
1332 }
1333 }
1334 if (failure) break;
1335 }
1336 }
1337 if (!failure) {
1338 Handle<JSArray> array = isolate->factory()->NewJSArray(0);
1339 Smi* length = Smi::FromInt(j);
1340 Handle<Map> map;
1341 map = JSObject::GetElementsTransitionMap(array, kind);
1342 array->set_map(*map);
1343 array->set_length(length);
1344 array->set_elements(*storage);
1345 return *array;
1346 }
1347 // In case of failure, fall through.
1348 }
1349
1350 Handle<FixedArray> storage;
1351 if (fast_case) {
1352 // The backing storage array must have non-existing elements to preserve
1353 // holes across concat operations.
1354 storage =
1355 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
1356 } else {
1357 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1358 uint32_t at_least_space_for =
1359 estimate_nof_elements + (estimate_nof_elements >> 2);
1360 storage = Handle<FixedArray>::cast(
1361 SeededNumberDictionary::New(isolate, at_least_space_for));
1362 }
1363
1364 ArrayConcatVisitor visitor(isolate, storage, fast_case);
1365
1366 for (int i = 0; i < argument_count; i++) {
1367 Handle<Object> obj((*args)[i], isolate);
1368 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1369 MAYBE_RETURN(spreadable, isolate->heap()->exception());
1370 if (spreadable.FromJust()) {
1371 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1372 if (!IterateElements(isolate, object, &visitor)) {
1373 return isolate->heap()->exception();
1374 }
1375 } else {
1376 visitor.visit(0, obj);
1377 visitor.increase_index_offset(1);
1378 }
1379 }
1380
1381 if (visitor.exceeds_array_limit()) {
1382 THROW_NEW_ERROR_RETURN_FAILURE(
1383 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1384 }
1385 return *visitor.ToArray();
1386}
1387
1388
1389MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
1390 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) {
1391 return MaybeHandle<JSArray>();
1392 }
1393 int n_arguments = args->length();
Steve Block6ded16b2010-05-10 14:33:55 +01001394 int result_len = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001395 {
1396 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397 Object* array_proto = isolate->array_function()->prototype();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398 // Iterate through all the arguments performing checks
1399 // and calculating total length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400 for (int i = 0; i < n_arguments; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401 Object* arg = (*args)[i];
1402 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
1403 Handle<JSArray> array(JSArray::cast(arg), isolate);
1404 if (!array->HasFastElements()) return MaybeHandle<JSArray>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001405 PrototypeIterator iter(isolate, arg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001406 if (iter.GetCurrent() != array_proto) return MaybeHandle<JSArray>();
1407 if (HasConcatSpreadableModifier(isolate, array)) {
1408 return MaybeHandle<JSArray>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001410 int len = Smi::cast(array->length())->value();
Steve Block6ded16b2010-05-10 14:33:55 +01001411
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412 // We shouldn't overflow when adding another len.
1413 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1414 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1415 USE(kHalfOfMaxInt);
1416 result_len += len;
1417 DCHECK(result_len >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001418 // Throw an Error if we overflow the FixedArray limits
1419 if (FixedArray::kMaxLength < result_len) {
1420 THROW_NEW_ERROR(isolate,
1421 NewRangeError(MessageTemplate::kInvalidArrayLength),
1422 JSArray);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423 }
Steve Block6ded16b2010-05-10 14:33:55 +01001424 }
Steve Block6ded16b2010-05-10 14:33:55 +01001425 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001426 return ElementsAccessor::Concat(isolate, args, n_arguments);
1427}
Steve Block6ded16b2010-05-10 14:33:55 +01001428
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001429} // namespace
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001430
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001431// ES6 22.1.3.1 Array.prototype.concat
1432BUILTIN(ArrayConcat) {
1433 HandleScope scope(isolate);
1434
1435 Handle<Object> receiver;
1436 if (!Object::ToObject(isolate, handle(args[0], isolate))
1437 .ToHandle(&receiver)) {
1438 THROW_NEW_ERROR_RETURN_FAILURE(
1439 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1440 isolate->factory()->NewStringFromAsciiChecked(
1441 "Array.prototype.concat")));
1442 }
1443 args[0] = *receiver;
1444
1445 Handle<JSArray> result_array;
1446 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1447 return *result_array;
1448 }
1449 if (isolate->has_pending_exception()) return isolate->heap()->exception();
1450 return Slow_ArrayConcat(&args, isolate);
1451}
1452
1453
1454// ES6 22.1.2.2 Array.isArray
1455BUILTIN(ArrayIsArray) {
1456 HandleScope scope(isolate);
1457 DCHECK_EQ(2, args.length());
1458 Handle<Object> object = args.at<Object>(1);
1459 Maybe<bool> result = Object::IsArray(object);
1460 MAYBE_RETURN(result, isolate->heap()->exception());
1461 return *isolate->factory()->ToBoolean(result.FromJust());
1462}
1463
1464
1465// ES6 19.1.2.1 Object.assign
1466BUILTIN(ObjectAssign) {
1467 HandleScope scope(isolate);
1468 Handle<Object> target = args.atOrUndefined(isolate, 1);
1469
1470 // 1. Let to be ? ToObject(target).
1471 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
1472 Execution::ToObject(isolate, target));
1473 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
1474 // 2. If only one argument was passed, return to.
1475 if (args.length() == 2) return *to;
1476 // 3. Let sources be the List of argument values starting with the
1477 // second argument.
1478 // 4. For each element nextSource of sources, in ascending index order,
1479 for (int i = 2; i < args.length(); ++i) {
1480 Handle<Object> next_source = args.at<Object>(i);
1481 // 4a. If nextSource is undefined or null, let keys be an empty List.
1482 if (next_source->IsUndefined() || next_source->IsNull()) continue;
1483 // 4b. Else,
1484 // 4b i. Let from be ToObject(nextSource).
1485 Handle<JSReceiver> from =
1486 Object::ToObject(isolate, next_source).ToHandleChecked();
1487 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
1488 Handle<FixedArray> keys;
1489 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1490 isolate, keys, JSReceiver::GetKeys(from, JSReceiver::OWN_ONLY,
1491 ALL_PROPERTIES, KEEP_NUMBERS));
1492 // 4c. Repeat for each element nextKey of keys in List order,
1493 for (int j = 0; j < keys->length(); ++j) {
1494 Handle<Object> next_key(keys->get(j), isolate);
1495 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
1496 PropertyDescriptor desc;
1497 Maybe<bool> found =
1498 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
1499 if (found.IsNothing()) return isolate->heap()->exception();
1500 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
1501 if (found.FromJust() && desc.enumerable()) {
1502 // 4c ii 1. Let propValue be ? Get(from, nextKey).
1503 Handle<Object> prop_value;
1504 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1505 isolate, prop_value,
1506 Runtime::GetObjectProperty(isolate, from, next_key, STRICT));
1507 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
1508 Handle<Object> status;
1509 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1510 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
1511 prop_value, STRICT));
1512 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001513 }
Steve Block6ded16b2010-05-10 14:33:55 +01001514 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001515 // 5. Return to.
1516 return *to;
1517}
Steve Block6ded16b2010-05-10 14:33:55 +01001518
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001520// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
1521BUILTIN(ObjectCreate) {
1522 HandleScope scope(isolate);
1523 Handle<Object> prototype = args.atOrUndefined(isolate, 1);
1524 if (!prototype->IsNull() && !prototype->IsJSReceiver()) {
1525 THROW_NEW_ERROR_RETURN_FAILURE(
1526 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
1527 }
1528
1529 // Generate the map with the specified {prototype} based on the Object
1530 // function's initial map from the current native context.
1531 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1532 // slack tracking for Object.create.
1533 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
1534 isolate);
1535 if (map->prototype() != *prototype) {
1536 map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
1537 }
1538
1539 // Actually allocate the object.
1540 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
1541
1542 // Define the properties if properties was specified and is not undefined.
1543 Handle<Object> properties = args.atOrUndefined(isolate, 2);
1544 if (!properties->IsUndefined()) {
1545 RETURN_FAILURE_ON_EXCEPTION(
1546 isolate, JSReceiver::DefineProperties(isolate, object, properties));
1547 }
1548
1549 return *object;
1550}
1551
1552
1553// ES6 section 19.1.2.5 Object.freeze ( O )
1554BUILTIN(ObjectFreeze) {
1555 HandleScope scope(isolate);
1556 Handle<Object> object = args.atOrUndefined(isolate, 1);
1557 if (object->IsJSReceiver()) {
1558 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1559 FROZEN, Object::THROW_ON_ERROR),
1560 isolate->heap()->exception());
1561 }
1562 return *object;
1563}
1564
1565
1566// ES6 section 19.1.2.11 Object.isExtensible ( O )
1567BUILTIN(ObjectIsExtensible) {
1568 HandleScope scope(isolate);
1569 Handle<Object> object = args.atOrUndefined(isolate, 1);
1570 Maybe<bool> result =
1571 object->IsJSReceiver()
1572 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
1573 : Just(false);
1574 MAYBE_RETURN(result, isolate->heap()->exception());
1575 return isolate->heap()->ToBoolean(result.FromJust());
1576}
1577
1578
1579// ES6 section 19.1.2.12 Object.isFrozen ( O )
1580BUILTIN(ObjectIsFrozen) {
1581 HandleScope scope(isolate);
1582 Handle<Object> object = args.atOrUndefined(isolate, 1);
1583 Maybe<bool> result = object->IsJSReceiver()
1584 ? JSReceiver::TestIntegrityLevel(
1585 Handle<JSReceiver>::cast(object), FROZEN)
1586 : Just(true);
1587 MAYBE_RETURN(result, isolate->heap()->exception());
1588 return isolate->heap()->ToBoolean(result.FromJust());
1589}
1590
1591
1592// ES6 section 19.1.2.13 Object.isSealed ( O )
1593BUILTIN(ObjectIsSealed) {
1594 HandleScope scope(isolate);
1595 Handle<Object> object = args.atOrUndefined(isolate, 1);
1596 Maybe<bool> result = object->IsJSReceiver()
1597 ? JSReceiver::TestIntegrityLevel(
1598 Handle<JSReceiver>::cast(object), SEALED)
1599 : Just(true);
1600 MAYBE_RETURN(result, isolate->heap()->exception());
1601 return isolate->heap()->ToBoolean(result.FromJust());
1602}
1603
1604
1605// ES6 section 19.1.2.14 Object.keys ( O )
1606BUILTIN(ObjectKeys) {
1607 HandleScope scope(isolate);
1608 Handle<Object> object = args.atOrUndefined(isolate, 1);
1609 Handle<JSReceiver> receiver;
1610 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1611 Execution::ToObject(isolate, object));
1612 Handle<FixedArray> keys;
1613
1614 int enum_length = receiver->map()->EnumLength();
1615 if (enum_length != kInvalidEnumCacheSentinel &&
1616 JSObject::cast(*receiver)->elements() ==
1617 isolate->heap()->empty_fixed_array()) {
1618 DCHECK(receiver->IsJSObject());
1619 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
1620 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
1621 DCHECK(!HeapObject::cast(receiver->map()->prototype())
1622 ->map()
1623 ->is_hidden_prototype());
1624 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
1625 if (enum_length == 0) {
1626 keys = isolate->factory()->empty_fixed_array();
1627 } else {
1628 Handle<FixedArray> cache(
1629 receiver->map()->instance_descriptors()->GetEnumCache());
1630 keys = isolate->factory()->NewFixedArray(enum_length);
1631 for (int i = 0; i < enum_length; i++) {
1632 keys->set(i, cache->get(i));
1633 }
1634 }
1635 } else {
1636 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1637 isolate, keys,
1638 JSReceiver::GetKeys(receiver, JSReceiver::OWN_ONLY, ENUMERABLE_STRINGS,
1639 CONVERT_TO_STRING));
1640 }
1641 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
1642}
1643
1644
1645// ES6 section 19.1.2.15 Object.preventExtensions ( O )
1646BUILTIN(ObjectPreventExtensions) {
1647 HandleScope scope(isolate);
1648 Handle<Object> object = args.atOrUndefined(isolate, 1);
1649 if (object->IsJSReceiver()) {
1650 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
1651 Object::THROW_ON_ERROR),
1652 isolate->heap()->exception());
1653 }
1654 return *object;
1655}
1656
1657
1658// ES6 section 19.1.2.17 Object.seal ( O )
1659BUILTIN(ObjectSeal) {
1660 HandleScope scope(isolate);
1661 Handle<Object> object = args.atOrUndefined(isolate, 1);
1662 if (object->IsJSReceiver()) {
1663 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1664 SEALED, Object::THROW_ON_ERROR),
1665 isolate->heap()->exception());
1666 }
1667 return *object;
1668}
1669
1670
1671namespace {
1672
1673bool CodeGenerationFromStringsAllowed(Isolate* isolate,
1674 Handle<Context> context) {
1675 DCHECK(context->allow_code_gen_from_strings()->IsFalse());
1676 // Check with callback if set.
1677 AllowCodeGenerationFromStringsCallback callback =
1678 isolate->allow_code_gen_callback();
1679 if (callback == NULL) {
1680 // No callback set and code generation disallowed.
1681 return false;
1682 } else {
1683 // Callback set. Let it decide if code generation is allowed.
1684 VMState<EXTERNAL> state(isolate);
1685 return callback(v8::Utils::ToLocal(context));
1686 }
1687}
1688
1689
1690MaybeHandle<JSFunction> CompileString(Handle<Context> context,
1691 Handle<String> source,
1692 ParseRestriction restriction) {
1693 Isolate* const isolate = context->GetIsolate();
1694 Handle<Context> native_context(context->native_context(), isolate);
1695
1696 // Check if native context allows code generation from
1697 // strings. Throw an exception if it doesn't.
1698 if (native_context->allow_code_gen_from_strings()->IsFalse() &&
1699 !CodeGenerationFromStringsAllowed(isolate, native_context)) {
1700 Handle<Object> error_message =
1701 native_context->ErrorMessageForCodeGenerationFromStrings();
1702 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1703 error_message),
1704 JSFunction);
1705 }
1706
1707 // Compile source string in the native context.
1708 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared(),
1709 isolate);
1710 return Compiler::GetFunctionFromEval(source, outer_info, native_context,
1711 SLOPPY, restriction,
1712 RelocInfo::kNoPosition);
1713}
1714
1715} // namespace
1716
1717
1718// ES6 section 18.2.1 eval (x)
1719BUILTIN(GlobalEval) {
1720 HandleScope scope(isolate);
1721 Handle<Object> x = args.atOrUndefined(isolate, 1);
1722 Handle<JSFunction> target = args.target();
1723 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
1724 if (!x->IsString()) return *x;
1725 Handle<JSFunction> function;
1726 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1727 isolate, function,
1728 CompileString(handle(target->native_context(), isolate),
1729 Handle<String>::cast(x), NO_PARSE_RESTRICTION));
1730 Handle<Object> result;
1731 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1732 isolate, result,
1733 Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
1734 return *result;
1735}
1736
1737
1738// ES6 section 26.1.3 Reflect.defineProperty
1739BUILTIN(ReflectDefineProperty) {
1740 HandleScope scope(isolate);
1741 DCHECK_EQ(4, args.length());
1742 Handle<Object> target = args.at<Object>(1);
1743 Handle<Object> key = args.at<Object>(2);
1744 Handle<Object> attributes = args.at<Object>(3);
1745
1746 if (!target->IsJSReceiver()) {
1747 THROW_NEW_ERROR_RETURN_FAILURE(
1748 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1749 isolate->factory()->NewStringFromAsciiChecked(
1750 "Reflect.defineProperty")));
1751 }
1752
1753 Handle<Name> name;
1754 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1755 Object::ToName(isolate, key));
1756
1757 PropertyDescriptor desc;
1758 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
1759 return isolate->heap()->exception();
1760 }
1761
1762 Maybe<bool> result =
1763 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
1764 name, &desc, Object::DONT_THROW);
1765 MAYBE_RETURN(result, isolate->heap()->exception());
1766 return *isolate->factory()->ToBoolean(result.FromJust());
1767}
1768
1769
1770// ES6 section 26.1.4 Reflect.deleteProperty
1771BUILTIN(ReflectDeleteProperty) {
1772 HandleScope scope(isolate);
1773 DCHECK_EQ(3, args.length());
1774 Handle<Object> target = args.at<Object>(1);
1775 Handle<Object> key = args.at<Object>(2);
1776
1777 if (!target->IsJSReceiver()) {
1778 THROW_NEW_ERROR_RETURN_FAILURE(
1779 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1780 isolate->factory()->NewStringFromAsciiChecked(
1781 "Reflect.deleteProperty")));
1782 }
1783
1784 Handle<Name> name;
1785 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1786 Object::ToName(isolate, key));
1787
1788 Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
1789 Handle<JSReceiver>::cast(target), name, SLOPPY);
1790 MAYBE_RETURN(result, isolate->heap()->exception());
1791 return *isolate->factory()->ToBoolean(result.FromJust());
1792}
1793
1794
1795// ES6 section 26.1.6 Reflect.get
1796BUILTIN(ReflectGet) {
1797 HandleScope scope(isolate);
1798 Handle<Object> target = args.atOrUndefined(isolate, 1);
1799 Handle<Object> key = args.atOrUndefined(isolate, 2);
1800 Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
1801
1802 if (!target->IsJSReceiver()) {
1803 THROW_NEW_ERROR_RETURN_FAILURE(
1804 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1805 isolate->factory()->NewStringFromAsciiChecked(
1806 "Reflect.get")));
1807 }
1808
1809 Handle<Name> name;
1810 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1811 Object::ToName(isolate, key));
1812
1813 Handle<Object> result;
1814 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1815 isolate, result, Object::GetPropertyOrElement(
1816 Handle<JSReceiver>::cast(target), name, receiver));
1817
1818 return *result;
1819}
1820
1821
1822// ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
1823BUILTIN(ReflectGetOwnPropertyDescriptor) {
1824 HandleScope scope(isolate);
1825 DCHECK_EQ(3, args.length());
1826 Handle<Object> target = args.at<Object>(1);
1827 Handle<Object> key = args.at<Object>(2);
1828
1829 if (!target->IsJSReceiver()) {
1830 THROW_NEW_ERROR_RETURN_FAILURE(
1831 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1832 isolate->factory()->NewStringFromAsciiChecked(
1833 "Reflect.getOwnPropertyDescriptor")));
1834 }
1835
1836 Handle<Name> name;
1837 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1838 Object::ToName(isolate, key));
1839
1840 PropertyDescriptor desc;
1841 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
1842 isolate, Handle<JSReceiver>::cast(target), name, &desc);
1843 MAYBE_RETURN(found, isolate->heap()->exception());
1844 if (!found.FromJust()) return isolate->heap()->undefined_value();
1845 return *desc.ToObject(isolate);
1846}
1847
1848
1849// ES6 section 26.1.8 Reflect.getPrototypeOf
1850BUILTIN(ReflectGetPrototypeOf) {
1851 HandleScope scope(isolate);
1852 DCHECK_EQ(2, args.length());
1853 Handle<Object> target = args.at<Object>(1);
1854
1855 if (!target->IsJSReceiver()) {
1856 THROW_NEW_ERROR_RETURN_FAILURE(
1857 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1858 isolate->factory()->NewStringFromAsciiChecked(
1859 "Reflect.getPrototypeOf")));
1860 }
1861 Handle<Object> prototype;
1862 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
1863 Object::GetPrototype(isolate, target));
1864 return *prototype;
1865}
1866
1867
1868// ES6 section 26.1.9 Reflect.has
1869BUILTIN(ReflectHas) {
1870 HandleScope scope(isolate);
1871 DCHECK_EQ(3, args.length());
1872 Handle<Object> target = args.at<Object>(1);
1873 Handle<Object> key = args.at<Object>(2);
1874
1875 if (!target->IsJSReceiver()) {
1876 THROW_NEW_ERROR_RETURN_FAILURE(
1877 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1878 isolate->factory()->NewStringFromAsciiChecked(
1879 "Reflect.has")));
1880 }
1881
1882 Handle<Name> name;
1883 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1884 Object::ToName(isolate, key));
1885
1886 Maybe<bool> result =
1887 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
1888 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
1889 : isolate->heap()->exception();
1890}
1891
1892
1893// ES6 section 26.1.10 Reflect.isExtensible
1894BUILTIN(ReflectIsExtensible) {
1895 HandleScope scope(isolate);
1896 DCHECK_EQ(2, args.length());
1897 Handle<Object> target = args.at<Object>(1);
1898
1899 if (!target->IsJSReceiver()) {
1900 THROW_NEW_ERROR_RETURN_FAILURE(
1901 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1902 isolate->factory()->NewStringFromAsciiChecked(
1903 "Reflect.isExtensible")));
1904 }
1905
1906 Maybe<bool> result =
1907 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
1908 MAYBE_RETURN(result, isolate->heap()->exception());
1909 return *isolate->factory()->ToBoolean(result.FromJust());
1910}
1911
1912
1913// ES6 section 26.1.11 Reflect.ownKeys
1914BUILTIN(ReflectOwnKeys) {
1915 HandleScope scope(isolate);
1916 DCHECK_EQ(2, args.length());
1917 Handle<Object> target = args.at<Object>(1);
1918
1919 if (!target->IsJSReceiver()) {
1920 THROW_NEW_ERROR_RETURN_FAILURE(
1921 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1922 isolate->factory()->NewStringFromAsciiChecked(
1923 "Reflect.ownKeys")));
1924 }
1925
1926 Handle<FixedArray> keys;
1927 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1928 isolate, keys, JSReceiver::GetKeys(Handle<JSReceiver>::cast(target),
1929 JSReceiver::OWN_ONLY, ALL_PROPERTIES,
1930 CONVERT_TO_STRING));
1931 return *isolate->factory()->NewJSArrayWithElements(keys);
1932}
1933
1934
1935// ES6 section 26.1.12 Reflect.preventExtensions
1936BUILTIN(ReflectPreventExtensions) {
1937 HandleScope scope(isolate);
1938 DCHECK_EQ(2, args.length());
1939 Handle<Object> target = args.at<Object>(1);
1940
1941 if (!target->IsJSReceiver()) {
1942 THROW_NEW_ERROR_RETURN_FAILURE(
1943 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1944 isolate->factory()->NewStringFromAsciiChecked(
1945 "Reflect.preventExtensions")));
1946 }
1947
1948 Maybe<bool> result = JSReceiver::PreventExtensions(
1949 Handle<JSReceiver>::cast(target), Object::DONT_THROW);
1950 MAYBE_RETURN(result, isolate->heap()->exception());
1951 return *isolate->factory()->ToBoolean(result.FromJust());
1952}
1953
1954
1955// ES6 section 26.1.13 Reflect.set
1956BUILTIN(ReflectSet) {
1957 HandleScope scope(isolate);
1958 Handle<Object> target = args.atOrUndefined(isolate, 1);
1959 Handle<Object> key = args.atOrUndefined(isolate, 2);
1960 Handle<Object> value = args.atOrUndefined(isolate, 3);
1961 Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
1962
1963 if (!target->IsJSReceiver()) {
1964 THROW_NEW_ERROR_RETURN_FAILURE(
1965 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1966 isolate->factory()->NewStringFromAsciiChecked(
1967 "Reflect.set")));
1968 }
1969
1970 Handle<Name> name;
1971 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1972 Object::ToName(isolate, key));
1973
1974 LookupIterator it = LookupIterator::PropertyOrElement(
1975 isolate, receiver, name, Handle<JSReceiver>::cast(target));
1976 Maybe<bool> result = Object::SetSuperProperty(
1977 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
1978 MAYBE_RETURN(result, isolate->heap()->exception());
1979 return *isolate->factory()->ToBoolean(result.FromJust());
1980}
1981
1982
1983// ES6 section 26.1.14 Reflect.setPrototypeOf
1984BUILTIN(ReflectSetPrototypeOf) {
1985 HandleScope scope(isolate);
1986 DCHECK_EQ(3, args.length());
1987 Handle<Object> target = args.at<Object>(1);
1988 Handle<Object> proto = args.at<Object>(2);
1989
1990 if (!target->IsJSReceiver()) {
1991 THROW_NEW_ERROR_RETURN_FAILURE(
1992 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1993 isolate->factory()->NewStringFromAsciiChecked(
1994 "Reflect.setPrototypeOf")));
1995 }
1996
1997 if (!proto->IsJSReceiver() && !proto->IsNull()) {
1998 THROW_NEW_ERROR_RETURN_FAILURE(
1999 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2000 }
2001
2002 Maybe<bool> result = JSReceiver::SetPrototype(
2003 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2004 MAYBE_RETURN(result, isolate->heap()->exception());
2005 return *isolate->factory()->ToBoolean(result.FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002006}
2007
2008
Steve Blocka7e24c12009-10-30 11:49:00 +00002009// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002010// ES6 section 20.3 Date Objects
Steve Block44f0eee2011-05-26 01:26:41 +01002011
2012
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002013namespace {
2014
2015// ES6 section 20.3.1.1 Time Values and Time Range
2016const double kMinYear = -1000000.0;
2017const double kMaxYear = -kMinYear;
2018const double kMinMonth = -10000000.0;
2019const double kMaxMonth = -kMinMonth;
2020
2021
2022// 20.3.1.2 Day Number and Time within Day
2023const double kMsPerDay = 86400000.0;
2024
2025
2026// ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
2027const double kMsPerSecond = 1000.0;
2028const double kMsPerMinute = 60000.0;
2029const double kMsPerHour = 3600000.0;
2030
2031
2032// ES6 section 20.3.1.14 MakeDate (day, time)
2033double MakeDate(double day, double time) {
2034 if (std::isfinite(day) && std::isfinite(time)) {
2035 return time + day * kMsPerDay;
2036 }
2037 return std::numeric_limits<double>::quiet_NaN();
Steve Block44f0eee2011-05-26 01:26:41 +01002038}
2039
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002040
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002041// ES6 section 20.3.1.13 MakeDay (year, month, date)
2042double MakeDay(double year, double month, double date) {
2043 if ((kMinYear <= year && year <= kMaxYear) &&
2044 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
2045 int y = FastD2I(year);
2046 int m = FastD2I(month);
2047 y += m / 12;
2048 m %= 12;
2049 if (m < 0) {
2050 m += 12;
2051 y -= 1;
2052 }
2053 DCHECK_LE(0, m);
2054 DCHECK_LT(m, 12);
2055
2056 // kYearDelta is an arbitrary number such that:
2057 // a) kYearDelta = -1 (mod 400)
2058 // b) year + kYearDelta > 0 for years in the range defined by
2059 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
2060 // Jan 1 1970. This is required so that we don't run into integer
2061 // division of negative numbers.
2062 // c) there shouldn't be an overflow for 32-bit integers in the following
2063 // operations.
2064 static const int kYearDelta = 399999;
2065 static const int kBaseDay =
2066 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
2067 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
2068 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
2069 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
2070 kBaseDay;
2071 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
2072 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151,
2073 181, 212, 243, 273, 304, 334};
2074 day_from_year += kDayFromMonth[m];
2075 } else {
2076 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152,
2077 182, 213, 244, 274, 305, 335};
2078 day_from_year += kDayFromMonth[m];
2079 }
2080 return static_cast<double>(day_from_year - 1) + date;
2081 }
2082 return std::numeric_limits<double>::quiet_NaN();
2083}
2084
2085
2086// ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
2087double MakeTime(double hour, double min, double sec, double ms) {
2088 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
2089 std::isfinite(ms)) {
2090 double const h = DoubleToInteger(hour);
2091 double const m = DoubleToInteger(min);
2092 double const s = DoubleToInteger(sec);
2093 double const milli = DoubleToInteger(ms);
2094 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
2095 }
2096 return std::numeric_limits<double>::quiet_NaN();
2097}
2098
2099
2100// ES6 section 20.3.1.15 TimeClip (time)
2101double TimeClip(double time) {
2102 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
2103 return DoubleToInteger(time) + 0.0;
2104 }
2105 return std::numeric_limits<double>::quiet_NaN();
2106}
2107
2108
2109const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
2110 "Thu", "Fri", "Sat"};
2111const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
2112 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
2113
2114
2115// ES6 section 20.3.1.16 Date Time String Format
2116double ParseDateTimeString(Handle<String> str) {
2117 Isolate* const isolate = str->GetIsolate();
2118 str = String::Flatten(str);
2119 // TODO(bmeurer): Change DateParser to not use the FixedArray.
2120 Handle<FixedArray> tmp =
2121 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
2122 DisallowHeapAllocation no_gc;
2123 String::FlatContent str_content = str->GetFlatContent();
2124 bool result;
2125 if (str_content.IsOneByte()) {
2126 result = DateParser::Parse(str_content.ToOneByteVector(), *tmp,
2127 isolate->unicode_cache());
2128 } else {
2129 result = DateParser::Parse(str_content.ToUC16Vector(), *tmp,
2130 isolate->unicode_cache());
2131 }
2132 if (!result) return std::numeric_limits<double>::quiet_NaN();
2133 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
2134 tmp->get(2)->Number());
2135 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
2136 tmp->get(5)->Number(), tmp->get(6)->Number());
2137 double date = MakeDate(day, time);
2138 if (tmp->get(7)->IsNull()) {
2139 if (!std::isnan(date)) {
2140 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
2141 }
2142 } else {
2143 date -= tmp->get(7)->Number() * 1000.0;
2144 }
2145 return date;
2146}
2147
2148
2149enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
2150
2151
2152// ES6 section 20.3.4.41.1 ToDateString(tv)
2153void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
2154 ToDateStringMode mode = kDateAndTime) {
2155 if (std::isnan(time_val)) {
2156 SNPrintF(str, "Invalid Date");
2157 return;
2158 }
2159 int64_t time_ms = static_cast<int64_t>(time_val);
2160 int64_t local_time_ms = date_cache->ToLocal(time_ms);
2161 int year, month, day, weekday, hour, min, sec, ms;
2162 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
2163 &min, &sec, &ms);
2164 int timezone_offset = -date_cache->TimezoneOffset(time_ms);
2165 int timezone_hour = std::abs(timezone_offset) / 60;
2166 int timezone_min = std::abs(timezone_offset) % 60;
2167 const char* local_timezone = date_cache->LocalTimezone(time_ms);
2168 switch (mode) {
2169 case kDateOnly:
2170 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
2171 kShortMonths[month], day, year);
2172 return;
2173 case kTimeOnly:
2174 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
2175 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
2176 local_timezone);
2177 return;
2178 case kDateAndTime:
2179 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
2180 kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
2181 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
2182 timezone_min, local_timezone);
2183 return;
2184 }
2185 UNREACHABLE();
2186}
2187
2188
2189Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
2190 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2191 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2192 Isolate* const isolate = date->GetIsolate();
2193 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2194 } else {
2195 time_val = std::numeric_limits<double>::quiet_NaN();
2196 }
2197 return *JSDate::SetValue(date, TimeClip(time_val));
2198}
2199
2200} // namespace
2201
2202
2203// ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
2204BUILTIN(DateConstructor) {
2205 HandleScope scope(isolate);
2206 double const time_val = JSDate::CurrentTimeValue(isolate);
2207 char buffer[128];
2208 Vector<char> str(buffer, arraysize(buffer));
2209 ToDateString(time_val, str, isolate->date_cache());
2210 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2211}
2212
2213
2214// ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
2215BUILTIN(DateConstructor_ConstructStub) {
2216 HandleScope scope(isolate);
2217 int const argc = args.length() - 1;
2218 Handle<JSFunction> target = args.target();
2219 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2220 double time_val;
2221 if (argc == 0) {
2222 time_val = JSDate::CurrentTimeValue(isolate);
2223 } else if (argc == 1) {
2224 Handle<Object> value = args.at<Object>(1);
2225 if (value->IsJSDate()) {
2226 time_val = Handle<JSDate>::cast(value)->value()->Number();
2227 } else {
2228 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2229 Object::ToPrimitive(value));
2230 if (value->IsString()) {
2231 time_val = ParseDateTimeString(Handle<String>::cast(value));
2232 } else {
2233 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2234 Object::ToNumber(value));
2235 time_val = value->Number();
2236 }
2237 }
2238 } else {
2239 Handle<Object> year_object;
2240 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2241 Object::ToNumber(args.at<Object>(1)));
2242 Handle<Object> month_object;
2243 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2244 Object::ToNumber(args.at<Object>(2)));
2245 double year = year_object->Number();
2246 double month = month_object->Number();
2247 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2248 if (argc >= 3) {
2249 Handle<Object> date_object;
2250 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
2251 Object::ToNumber(args.at<Object>(3)));
2252 date = date_object->Number();
2253 if (argc >= 4) {
2254 Handle<Object> hours_object;
2255 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2256 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2257 hours = hours_object->Number();
2258 if (argc >= 5) {
2259 Handle<Object> minutes_object;
2260 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2261 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2262 minutes = minutes_object->Number();
2263 if (argc >= 6) {
2264 Handle<Object> seconds_object;
2265 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2266 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
2267 seconds = seconds_object->Number();
2268 if (argc >= 7) {
2269 Handle<Object> ms_object;
2270 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2271 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2272 ms = ms_object->Number();
2273 }
2274 }
2275 }
2276 }
2277 }
2278 if (!std::isnan(year)) {
2279 double const y = DoubleToInteger(year);
2280 if (0.0 <= y && y <= 99) year = 1900 + y;
2281 }
2282 double const day = MakeDay(year, month, date);
2283 double const time = MakeTime(hours, minutes, seconds, ms);
2284 time_val = MakeDate(day, time);
2285 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2286 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2287 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2288 } else {
2289 time_val = std::numeric_limits<double>::quiet_NaN();
2290 }
2291 }
2292 Handle<JSDate> result;
2293 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2294 JSDate::New(target, new_target, time_val));
2295 return *result;
2296}
2297
2298
2299// ES6 section 20.3.3.1 Date.now ( )
2300BUILTIN(DateNow) {
2301 HandleScope scope(isolate);
2302 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
2303}
2304
2305
2306// ES6 section 20.3.3.2 Date.parse ( string )
2307BUILTIN(DateParse) {
2308 HandleScope scope(isolate);
2309 Handle<String> string;
2310 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2311 isolate, string,
2312 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2313 return *isolate->factory()->NewNumber(ParseDateTimeString(string));
2314}
2315
2316
2317// ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
2318BUILTIN(DateUTC) {
2319 HandleScope scope(isolate);
2320 int const argc = args.length() - 1;
2321 double year = std::numeric_limits<double>::quiet_NaN();
2322 double month = std::numeric_limits<double>::quiet_NaN();
2323 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2324 if (argc >= 1) {
2325 Handle<Object> year_object;
2326 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2327 Object::ToNumber(args.at<Object>(1)));
2328 year = year_object->Number();
2329 if (argc >= 2) {
2330 Handle<Object> month_object;
2331 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2332 Object::ToNumber(args.at<Object>(2)));
2333 month = month_object->Number();
2334 if (argc >= 3) {
2335 Handle<Object> date_object;
2336 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2337 isolate, date_object, Object::ToNumber(args.at<Object>(3)));
2338 date = date_object->Number();
2339 if (argc >= 4) {
2340 Handle<Object> hours_object;
2341 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2342 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2343 hours = hours_object->Number();
2344 if (argc >= 5) {
2345 Handle<Object> minutes_object;
2346 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2347 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2348 minutes = minutes_object->Number();
2349 if (argc >= 6) {
2350 Handle<Object> seconds_object;
2351 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2352 isolate, seconds_object,
2353 Object::ToNumber(args.at<Object>(6)));
2354 seconds = seconds_object->Number();
2355 if (argc >= 7) {
2356 Handle<Object> ms_object;
2357 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2358 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2359 ms = ms_object->Number();
2360 }
2361 }
2362 }
2363 }
2364 }
2365 }
2366 }
2367 if (!std::isnan(year)) {
2368 double const y = DoubleToInteger(year);
2369 if (0.0 <= y && y <= 99) year = 1900 + y;
2370 }
2371 double const day = MakeDay(year, month, date);
2372 double const time = MakeTime(hours, minutes, seconds, ms);
2373 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
2374}
2375
2376
2377// ES6 section 20.3.4.20 Date.prototype.setDate ( date )
2378BUILTIN(DatePrototypeSetDate) {
2379 HandleScope scope(isolate);
2380 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
2381 Handle<Object> value = args.atOrUndefined(isolate, 1);
2382 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2383 double time_val = date->value()->Number();
2384 if (!std::isnan(time_val)) {
2385 int64_t const time_ms = static_cast<int64_t>(time_val);
2386 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2387 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2388 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2389 int year, month, day;
2390 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2391 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
2392 }
2393 return SetLocalDateValue(date, time_val);
2394}
2395
2396
2397// ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
2398BUILTIN(DatePrototypeSetFullYear) {
2399 HandleScope scope(isolate);
2400 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
2401 int const argc = args.length() - 1;
2402 Handle<Object> year = args.atOrUndefined(isolate, 1);
2403 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2404 double y = year->Number(), m = 0.0, dt = 1.0;
2405 int time_within_day = 0;
2406 if (!std::isnan(date->value()->Number())) {
2407 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2408 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2409 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2410 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2411 int year, month, day;
2412 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2413 m = month;
2414 dt = day;
2415 }
2416 if (argc >= 2) {
2417 Handle<Object> month = args.at<Object>(2);
2418 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2419 m = month->Number();
2420 if (argc >= 3) {
2421 Handle<Object> date = args.at<Object>(3);
2422 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2423 dt = date->Number();
2424 }
2425 }
2426 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2427 return SetLocalDateValue(date, time_val);
2428}
2429
2430
2431// ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
2432BUILTIN(DatePrototypeSetHours) {
2433 HandleScope scope(isolate);
2434 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
2435 int const argc = args.length() - 1;
2436 Handle<Object> hour = args.atOrUndefined(isolate, 1);
2437 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
2438 double h = hour->Number();
2439 double time_val = date->value()->Number();
2440 if (!std::isnan(time_val)) {
2441 int64_t const time_ms = static_cast<int64_t>(time_val);
2442 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2443 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2444 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2445 double m = (time_within_day / (60 * 1000)) % 60;
2446 double s = (time_within_day / 1000) % 60;
2447 double milli = time_within_day % 1000;
2448 if (argc >= 2) {
2449 Handle<Object> min = args.at<Object>(2);
2450 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2451 m = min->Number();
2452 if (argc >= 3) {
2453 Handle<Object> sec = args.at<Object>(3);
2454 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2455 s = sec->Number();
2456 if (argc >= 4) {
2457 Handle<Object> ms = args.at<Object>(4);
2458 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2459 milli = ms->Number();
2460 }
2461 }
2462 }
2463 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2464 }
2465 return SetLocalDateValue(date, time_val);
2466}
2467
2468
2469// ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
2470BUILTIN(DatePrototypeSetMilliseconds) {
2471 HandleScope scope(isolate);
2472 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
2473 Handle<Object> ms = args.atOrUndefined(isolate, 1);
2474 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2475 double time_val = date->value()->Number();
2476 if (!std::isnan(time_val)) {
2477 int64_t const time_ms = static_cast<int64_t>(time_val);
2478 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2479 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2480 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2481 int h = time_within_day / (60 * 60 * 1000);
2482 int m = (time_within_day / (60 * 1000)) % 60;
2483 int s = (time_within_day / 1000) % 60;
2484 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
2485 }
2486 return SetLocalDateValue(date, time_val);
2487}
2488
2489
2490// ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
2491BUILTIN(DatePrototypeSetMinutes) {
2492 HandleScope scope(isolate);
2493 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
2494 int const argc = args.length() - 1;
2495 Handle<Object> min = args.atOrUndefined(isolate, 1);
2496 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2497 double time_val = date->value()->Number();
2498 if (!std::isnan(time_val)) {
2499 int64_t const time_ms = static_cast<int64_t>(time_val);
2500 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2501 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2502 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2503 int h = time_within_day / (60 * 60 * 1000);
2504 double m = min->Number();
2505 double s = (time_within_day / 1000) % 60;
2506 double milli = time_within_day % 1000;
2507 if (argc >= 2) {
2508 Handle<Object> sec = args.at<Object>(2);
2509 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2510 s = sec->Number();
2511 if (argc >= 3) {
2512 Handle<Object> ms = args.at<Object>(3);
2513 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2514 milli = ms->Number();
2515 }
2516 }
2517 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2518 }
2519 return SetLocalDateValue(date, time_val);
2520}
2521
2522
2523// ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
2524BUILTIN(DatePrototypeSetMonth) {
2525 HandleScope scope(isolate);
2526 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
2527 int const argc = args.length() - 1;
2528 Handle<Object> month = args.atOrUndefined(isolate, 1);
2529 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2530 double time_val = date->value()->Number();
2531 if (!std::isnan(time_val)) {
2532 int64_t const time_ms = static_cast<int64_t>(time_val);
2533 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2534 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
2535 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2536 int year, unused, day;
2537 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
2538 double m = month->Number();
2539 double dt = day;
2540 if (argc >= 2) {
2541 Handle<Object> date = args.at<Object>(2);
2542 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2543 dt = date->Number();
2544 }
2545 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
2546 }
2547 return SetLocalDateValue(date, time_val);
2548}
2549
2550
2551// ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
2552BUILTIN(DatePrototypeSetSeconds) {
2553 HandleScope scope(isolate);
2554 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
2555 int const argc = args.length() - 1;
2556 Handle<Object> sec = args.atOrUndefined(isolate, 1);
2557 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2558 double time_val = date->value()->Number();
2559 if (!std::isnan(time_val)) {
2560 int64_t const time_ms = static_cast<int64_t>(time_val);
2561 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2562 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2563 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2564 int h = time_within_day / (60 * 60 * 1000);
2565 double m = (time_within_day / (60 * 1000)) % 60;
2566 double s = sec->Number();
2567 double milli = time_within_day % 1000;
2568 if (argc >= 2) {
2569 Handle<Object> ms = args.at<Object>(2);
2570 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2571 milli = ms->Number();
2572 }
2573 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2574 }
2575 return SetLocalDateValue(date, time_val);
2576}
2577
2578
2579// ES6 section 20.3.4.27 Date.prototype.setTime ( time )
2580BUILTIN(DatePrototypeSetTime) {
2581 HandleScope scope(isolate);
2582 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
2583 Handle<Object> value = args.atOrUndefined(isolate, 1);
2584 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2585 return *JSDate::SetValue(date, TimeClip(value->Number()));
2586}
2587
2588
2589// ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
2590BUILTIN(DatePrototypeSetUTCDate) {
2591 HandleScope scope(isolate);
2592 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
2593 Handle<Object> value = args.atOrUndefined(isolate, 1);
2594 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2595 if (std::isnan(date->value()->Number())) return date->value();
2596 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2597 int const days = isolate->date_cache()->DaysFromTime(time_ms);
2598 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
2599 int year, month, day;
2600 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2601 double const time_val =
2602 MakeDate(MakeDay(year, month, value->Number()), time_within_day);
2603 return *JSDate::SetValue(date, TimeClip(time_val));
2604}
2605
2606
2607// ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
2608BUILTIN(DatePrototypeSetUTCFullYear) {
2609 HandleScope scope(isolate);
2610 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
2611 int const argc = args.length() - 1;
2612 Handle<Object> year = args.atOrUndefined(isolate, 1);
2613 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2614 double y = year->Number(), m = 0.0, dt = 1.0;
2615 int time_within_day = 0;
2616 if (!std::isnan(date->value()->Number())) {
2617 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2618 int const days = isolate->date_cache()->DaysFromTime(time_ms);
2619 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
2620 int year, month, day;
2621 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2622 m = month;
2623 dt = day;
2624 }
2625 if (argc >= 2) {
2626 Handle<Object> month = args.at<Object>(2);
2627 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2628 m = month->Number();
2629 if (argc >= 3) {
2630 Handle<Object> date = args.at<Object>(3);
2631 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2632 dt = date->Number();
2633 }
2634 }
2635 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2636 return *JSDate::SetValue(date, TimeClip(time_val));
2637}
2638
2639
2640// ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
2641BUILTIN(DatePrototypeSetUTCHours) {
2642 HandleScope scope(isolate);
2643 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
2644 int const argc = args.length() - 1;
2645 Handle<Object> hour = args.atOrUndefined(isolate, 1);
2646 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
2647 double h = hour->Number();
2648 double time_val = date->value()->Number();
2649 if (!std::isnan(time_val)) {
2650 int64_t const time_ms = static_cast<int64_t>(time_val);
2651 int day = isolate->date_cache()->DaysFromTime(time_ms);
2652 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2653 double m = (time_within_day / (60 * 1000)) % 60;
2654 double s = (time_within_day / 1000) % 60;
2655 double milli = time_within_day % 1000;
2656 if (argc >= 2) {
2657 Handle<Object> min = args.at<Object>(2);
2658 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2659 m = min->Number();
2660 if (argc >= 3) {
2661 Handle<Object> sec = args.at<Object>(3);
2662 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2663 s = sec->Number();
2664 if (argc >= 4) {
2665 Handle<Object> ms = args.at<Object>(4);
2666 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2667 milli = ms->Number();
2668 }
2669 }
2670 }
2671 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2672 }
2673 return *JSDate::SetValue(date, TimeClip(time_val));
2674}
2675
2676
2677// ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
2678BUILTIN(DatePrototypeSetUTCMilliseconds) {
2679 HandleScope scope(isolate);
2680 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
2681 Handle<Object> ms = args.atOrUndefined(isolate, 1);
2682 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2683 double time_val = date->value()->Number();
2684 if (!std::isnan(time_val)) {
2685 int64_t const time_ms = static_cast<int64_t>(time_val);
2686 int day = isolate->date_cache()->DaysFromTime(time_ms);
2687 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2688 int h = time_within_day / (60 * 60 * 1000);
2689 int m = (time_within_day / (60 * 1000)) % 60;
2690 int s = (time_within_day / 1000) % 60;
2691 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
2692 }
2693 return *JSDate::SetValue(date, TimeClip(time_val));
2694}
2695
2696
2697// ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
2698BUILTIN(DatePrototypeSetUTCMinutes) {
2699 HandleScope scope(isolate);
2700 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
2701 int const argc = args.length() - 1;
2702 Handle<Object> min = args.atOrUndefined(isolate, 1);
2703 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2704 double time_val = date->value()->Number();
2705 if (!std::isnan(time_val)) {
2706 int64_t const time_ms = static_cast<int64_t>(time_val);
2707 int day = isolate->date_cache()->DaysFromTime(time_ms);
2708 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2709 int h = time_within_day / (60 * 60 * 1000);
2710 double m = min->Number();
2711 double s = (time_within_day / 1000) % 60;
2712 double milli = time_within_day % 1000;
2713 if (argc >= 2) {
2714 Handle<Object> sec = args.at<Object>(2);
2715 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2716 s = sec->Number();
2717 if (argc >= 3) {
2718 Handle<Object> ms = args.at<Object>(3);
2719 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2720 milli = ms->Number();
2721 }
2722 }
2723 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2724 }
2725 return *JSDate::SetValue(date, TimeClip(time_val));
2726}
2727
2728
2729// ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
2730BUILTIN(DatePrototypeSetUTCMonth) {
2731 HandleScope scope(isolate);
2732 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
2733 int const argc = args.length() - 1;
2734 Handle<Object> month = args.atOrUndefined(isolate, 1);
2735 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2736 double time_val = date->value()->Number();
2737 if (!std::isnan(time_val)) {
2738 int64_t const time_ms = static_cast<int64_t>(time_val);
2739 int days = isolate->date_cache()->DaysFromTime(time_ms);
2740 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
2741 int year, unused, day;
2742 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
2743 double m = month->Number();
2744 double dt = day;
2745 if (argc >= 2) {
2746 Handle<Object> date = args.at<Object>(2);
2747 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2748 dt = date->Number();
2749 }
2750 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
2751 }
2752 return *JSDate::SetValue(date, TimeClip(time_val));
2753}
2754
2755
2756// ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
2757BUILTIN(DatePrototypeSetUTCSeconds) {
2758 HandleScope scope(isolate);
2759 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
2760 int const argc = args.length() - 1;
2761 Handle<Object> sec = args.atOrUndefined(isolate, 1);
2762 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2763 double time_val = date->value()->Number();
2764 if (!std::isnan(time_val)) {
2765 int64_t const time_ms = static_cast<int64_t>(time_val);
2766 int day = isolate->date_cache()->DaysFromTime(time_ms);
2767 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2768 int h = time_within_day / (60 * 60 * 1000);
2769 double m = (time_within_day / (60 * 1000)) % 60;
2770 double s = sec->Number();
2771 double milli = time_within_day % 1000;
2772 if (argc >= 2) {
2773 Handle<Object> ms = args.at<Object>(2);
2774 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2775 milli = ms->Number();
2776 }
2777 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2778 }
2779 return *JSDate::SetValue(date, TimeClip(time_val));
2780}
2781
2782
2783// ES6 section 20.3.4.35 Date.prototype.toDateString ( )
2784BUILTIN(DatePrototypeToDateString) {
2785 HandleScope scope(isolate);
2786 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
2787 char buffer[128];
2788 Vector<char> str(buffer, arraysize(buffer));
2789 ToDateString(date->value()->Number(), str, isolate->date_cache(), kDateOnly);
2790 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2791}
2792
2793
2794// ES6 section 20.3.4.36 Date.prototype.toISOString ( )
2795BUILTIN(DatePrototypeToISOString) {
2796 HandleScope scope(isolate);
2797 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
2798 double const time_val = date->value()->Number();
2799 if (std::isnan(time_val)) {
2800 THROW_NEW_ERROR_RETURN_FAILURE(
2801 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
2802 }
2803 int64_t const time_ms = static_cast<int64_t>(time_val);
2804 int year, month, day, weekday, hour, min, sec, ms;
2805 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
2806 &hour, &min, &sec, &ms);
2807 char buffer[128];
2808 Vector<char> str(buffer, arraysize(buffer));
2809 if (year >= 0 && year <= 9999) {
2810 SNPrintF(str, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
2811 hour, min, sec, ms);
2812 } else if (year < 0) {
2813 SNPrintF(str, "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, month + 1, day,
2814 hour, min, sec, ms);
2815 } else {
2816 SNPrintF(str, "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
2817 hour, min, sec, ms);
2818 }
2819 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2820}
2821
2822
2823// ES6 section 20.3.4.41 Date.prototype.toString ( )
2824BUILTIN(DatePrototypeToString) {
2825 HandleScope scope(isolate);
2826 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
2827 char buffer[128];
2828 Vector<char> str(buffer, arraysize(buffer));
2829 ToDateString(date->value()->Number(), str, isolate->date_cache());
2830 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2831}
2832
2833
2834// ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
2835BUILTIN(DatePrototypeToTimeString) {
2836 HandleScope scope(isolate);
2837 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
2838 char buffer[128];
2839 Vector<char> str(buffer, arraysize(buffer));
2840 ToDateString(date->value()->Number(), str, isolate->date_cache(), kTimeOnly);
2841 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2842}
2843
2844
2845// ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
2846BUILTIN(DatePrototypeToUTCString) {
2847 HandleScope scope(isolate);
2848 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
2849 double const time_val = date->value()->Number();
2850 if (std::isnan(time_val)) {
2851 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
2852 }
2853 char buffer[128];
2854 Vector<char> str(buffer, arraysize(buffer));
2855 int64_t time_ms = static_cast<int64_t>(time_val);
2856 int year, month, day, weekday, hour, min, sec, ms;
2857 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
2858 &hour, &min, &sec, &ms);
2859 SNPrintF(str, "%s, %02d %s %4d %02d:%02d:%02d GMT", kShortWeekDays[weekday],
2860 day, kShortMonths[month], year, hour, min, sec);
2861 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2862}
2863
2864
2865// ES6 section 20.3.4.44 Date.prototype.valueOf ( )
2866BUILTIN(DatePrototypeValueOf) {
2867 HandleScope scope(isolate);
2868 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
2869 return date->value();
2870}
2871
2872
2873// ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
2874BUILTIN(DatePrototypeToPrimitive) {
2875 HandleScope scope(isolate);
2876 DCHECK_EQ(2, args.length());
2877 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
2878 Handle<Object> hint = args.at<Object>(1);
2879 Handle<Object> result;
2880 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2881 JSDate::ToPrimitive(receiver, hint));
2882 return *result;
2883}
2884
2885
2886// ES6 section B.2.4.1 Date.prototype.getYear ( )
2887BUILTIN(DatePrototypeGetYear) {
2888 HandleScope scope(isolate);
2889 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
2890 double time_val = date->value()->Number();
2891 if (std::isnan(time_val)) return date->value();
2892 int64_t time_ms = static_cast<int64_t>(time_val);
2893 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2894 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
2895 int year, month, day;
2896 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2897 return Smi::FromInt(year - 1900);
2898}
2899
2900
2901// ES6 section B.2.4.2 Date.prototype.setYear ( year )
2902BUILTIN(DatePrototypeSetYear) {
2903 HandleScope scope(isolate);
2904 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
2905 Handle<Object> year = args.atOrUndefined(isolate, 1);
2906 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2907 double m = 0.0, dt = 1.0, y = year->Number();
2908 if (0.0 <= y && y <= 99.0) {
2909 y = 1900.0 + DoubleToInteger(y);
2910 }
2911 int time_within_day = 0;
2912 if (!std::isnan(date->value()->Number())) {
2913 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2914 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2915 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2916 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2917 int year, month, day;
2918 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2919 m = month;
2920 dt = day;
2921 }
2922 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2923 return SetLocalDateValue(date, time_val);
2924}
2925
2926
2927// static
2928void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
2929 Generate_DatePrototype_GetField(masm, JSDate::kDay);
2930}
2931
2932
2933// static
2934void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
2935 Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
2936}
2937
2938
2939// static
2940void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
2941 Generate_DatePrototype_GetField(masm, JSDate::kYear);
2942}
2943
2944
2945// static
2946void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
2947 Generate_DatePrototype_GetField(masm, JSDate::kHour);
2948}
2949
2950
2951// static
2952void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
2953 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
2954}
2955
2956
2957// static
2958void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
2959 Generate_DatePrototype_GetField(masm, JSDate::kMinute);
2960}
2961
2962
2963// static
2964void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
2965 Generate_DatePrototype_GetField(masm, JSDate::kMonth);
2966}
2967
2968
2969// static
2970void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
2971 Generate_DatePrototype_GetField(masm, JSDate::kSecond);
2972}
2973
2974
2975// static
2976void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
2977 Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
2978}
2979
2980
2981// static
2982void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
2983 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
2984}
2985
2986
2987// static
2988void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
2989 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
2990}
2991
2992
2993// static
2994void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
2995 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
2996}
2997
2998
2999// static
3000void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
3001 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
3002}
3003
3004
3005// static
3006void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
3007 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
3008}
3009
3010
3011// static
3012void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
3013 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
3014}
3015
3016
3017// static
3018void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
3019 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
3020}
3021
3022
3023// static
3024void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
3025 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
3026}
3027
3028
3029// static
3030void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
3031 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
3032}
3033
3034
3035namespace {
3036
3037// ES6 section 19.2.1.1.1 CreateDynamicFunction
3038MaybeHandle<JSFunction> CreateDynamicFunction(
3039 Isolate* isolate,
3040 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,
3041 const char* token) {
3042 // Compute number of arguments, ignoring the receiver.
3043 DCHECK_LE(1, args.length());
3044 int const argc = args.length() - 1;
3045
3046 // Build the source string.
3047 Handle<String> source;
3048 {
3049 IncrementalStringBuilder builder(isolate);
3050 builder.AppendCharacter('(');
3051 builder.AppendCString(token);
3052 builder.AppendCharacter('(');
3053 bool parenthesis_in_arg_string = false;
3054 if (argc > 1) {
3055 for (int i = 1; i < argc; ++i) {
3056 if (i > 1) builder.AppendCharacter(',');
3057 Handle<String> param;
3058 ASSIGN_RETURN_ON_EXCEPTION(
3059 isolate, param, Object::ToString(isolate, args.at<Object>(i)),
3060 JSFunction);
3061 param = String::Flatten(param);
3062 builder.AppendString(param);
3063 // If the formal parameters string include ) - an illegal
3064 // character - it may make the combined function expression
3065 // compile. We avoid this problem by checking for this early on.
3066 DisallowHeapAllocation no_gc; // Ensure vectors stay valid.
3067 String::FlatContent param_content = param->GetFlatContent();
3068 for (int i = 0, length = param->length(); i < length; ++i) {
3069 if (param_content.Get(i) == ')') {
3070 parenthesis_in_arg_string = true;
3071 break;
3072 }
3073 }
3074 }
3075 // If the formal parameters include an unbalanced block comment, the
3076 // function must be rejected. Since JavaScript does not allow nested
3077 // comments we can include a trailing block comment to catch this.
3078 builder.AppendCString("\n/**/");
3079 }
3080 builder.AppendCString(") {\n");
3081 if (argc > 0) {
3082 Handle<String> body;
3083 ASSIGN_RETURN_ON_EXCEPTION(
3084 isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
3085 JSFunction);
3086 builder.AppendString(body);
3087 }
3088 builder.AppendCString("\n})");
3089 ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction);
3090
3091 // The SyntaxError must be thrown after all the (observable) ToString
3092 // conversions are done.
3093 if (parenthesis_in_arg_string) {
3094 THROW_NEW_ERROR(isolate,
3095 NewSyntaxError(MessageTemplate::kParenthesisInArgString),
3096 JSFunction);
3097 }
3098 }
3099
3100 // Compile the string in the constructor and not a helper so that errors to
3101 // come from here.
3102 Handle<JSFunction> target = args.target();
3103 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
3104 Handle<JSFunction> function;
3105 {
3106 ASSIGN_RETURN_ON_EXCEPTION(
3107 isolate, function,
3108 CompileString(handle(target->native_context(), isolate), source,
3109 ONLY_SINGLE_FUNCTION_LITERAL),
3110 JSFunction);
3111 Handle<Object> result;
3112 ASSIGN_RETURN_ON_EXCEPTION(
3113 isolate, result,
3114 Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
3115 JSFunction);
3116 function = Handle<JSFunction>::cast(result);
3117 function->shared()->set_name_should_print_as_anonymous(true);
3118 }
3119
3120 // If new.target is equal to target then the function created
3121 // is already correctly setup and nothing else should be done
3122 // here. But if new.target is not equal to target then we are
3123 // have a Function builtin subclassing case and therefore the
3124 // function has wrong initial map. To fix that we create a new
3125 // function object with correct initial map.
3126 Handle<Object> unchecked_new_target = args.new_target();
3127 if (!unchecked_new_target->IsUndefined() &&
3128 !unchecked_new_target.is_identical_to(target)) {
3129 Handle<JSReceiver> new_target =
3130 Handle<JSReceiver>::cast(unchecked_new_target);
3131 Handle<Map> initial_map;
3132 ASSIGN_RETURN_ON_EXCEPTION(
3133 isolate, initial_map,
3134 JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction);
3135
3136 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
3137 Handle<Map> map = Map::AsLanguageMode(
3138 initial_map, shared_info->language_mode(), shared_info->kind());
3139
3140 Handle<Context> context(function->context(), isolate);
3141 function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
3142 map, shared_info, context, NOT_TENURED);
3143 }
3144 return function;
3145}
3146
3147} // namespace
3148
3149
3150// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
3151BUILTIN(FunctionConstructor) {
3152 HandleScope scope(isolate);
3153 Handle<JSFunction> result;
3154 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3155 isolate, result, CreateDynamicFunction(isolate, args, "function"));
3156 return *result;
3157}
3158
3159
3160// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
3161BUILTIN(FunctionPrototypeBind) {
3162 HandleScope scope(isolate);
3163 DCHECK_LE(1, args.length());
3164 if (!args.receiver()->IsCallable()) {
3165 THROW_NEW_ERROR_RETURN_FAILURE(
3166 isolate, NewTypeError(MessageTemplate::kFunctionBind));
3167 }
3168
3169 // Allocate the bound function with the given {this_arg} and {args}.
3170 Handle<JSReceiver> target = args.at<JSReceiver>(0);
3171 Handle<Object> this_arg = isolate->factory()->undefined_value();
3172 ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
3173 if (args.length() > 1) {
3174 this_arg = args.at<Object>(1);
3175 for (int i = 2; i < args.length(); ++i) {
3176 argv[i - 2] = args.at<Object>(i);
3177 }
3178 }
3179 Handle<JSBoundFunction> function;
3180 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3181 isolate, function,
3182 isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
3183
3184 // TODO(bmeurer): Optimize the rest for the common cases where {target} is
3185 // a function with some initial map or even a bound function.
3186 // Setup the "length" property based on the "length" of the {target}.
3187 Handle<Object> length(Smi::FromInt(0), isolate);
3188 Maybe<bool> target_has_length =
3189 JSReceiver::HasOwnProperty(target, isolate->factory()->length_string());
3190 if (!target_has_length.IsJust()) {
3191 return isolate->heap()->exception();
3192 } else if (target_has_length.FromJust()) {
3193 Handle<Object> target_length;
3194 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3195 isolate, target_length,
3196 JSReceiver::GetProperty(target, isolate->factory()->length_string()));
3197 if (target_length->IsNumber()) {
3198 length = isolate->factory()->NewNumber(std::max(
3199 0.0, DoubleToInteger(target_length->Number()) - argv.length()));
3200 }
3201 }
3202 function->set_length(*length);
3203
3204 // Setup the "name" property based on the "name" of the {target}.
3205 Handle<Object> target_name;
3206 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3207 isolate, target_name,
3208 JSReceiver::GetProperty(target, isolate->factory()->name_string()));
3209 Handle<String> name;
3210 if (!target_name->IsString()) {
3211 name = isolate->factory()->bound__string();
3212 } else {
3213 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3214 isolate, name, Name::ToFunctionName(Handle<String>::cast(target_name)));
3215 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3216 isolate, name, isolate->factory()->NewConsString(
3217 isolate->factory()->bound__string(), name));
3218 }
3219 function->set_name(*name);
3220 return *function;
3221}
3222
3223
3224// ES6 section 19.2.3.5 Function.prototype.toString ( )
3225BUILTIN(FunctionPrototypeToString) {
3226 HandleScope scope(isolate);
3227 Handle<Object> receiver = args.receiver();
3228 if (receiver->IsJSBoundFunction()) {
3229 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
3230 } else if (receiver->IsJSFunction()) {
3231 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
3232 }
3233 THROW_NEW_ERROR_RETURN_FAILURE(
3234 isolate, NewTypeError(MessageTemplate::kNotGeneric,
3235 isolate->factory()->NewStringFromAsciiChecked(
3236 "Function.prototype.toString")));
3237}
3238
3239
3240// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
3241BUILTIN(GeneratorFunctionConstructor) {
3242 HandleScope scope(isolate);
3243 Handle<JSFunction> result;
3244 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3245 isolate, result, CreateDynamicFunction(isolate, args, "function*"));
3246 return *result;
3247}
3248
3249
3250// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
3251BUILTIN(SymbolConstructor) {
3252 HandleScope scope(isolate);
3253 Handle<Symbol> result = isolate->factory()->NewSymbol();
3254 Handle<Object> description = args.atOrUndefined(isolate, 1);
3255 if (!description->IsUndefined()) {
3256 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
3257 Object::ToString(isolate, description));
3258 result->set_name(*description);
3259 }
3260 return *result;
3261}
3262
3263
3264// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
3265BUILTIN(SymbolConstructor_ConstructStub) {
3266 HandleScope scope(isolate);
3267 THROW_NEW_ERROR_RETURN_FAILURE(
3268 isolate, NewTypeError(MessageTemplate::kNotConstructor,
3269 isolate->factory()->Symbol_string()));
3270}
3271
3272
3273// ES6 19.1.3.6 Object.prototype.toString
3274BUILTIN(ObjectProtoToString) {
3275 HandleScope scope(isolate);
3276 Handle<Object> object = args.at<Object>(0);
3277 Handle<String> result;
3278 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3279 isolate, result, JSObject::ObjectProtoToString(isolate, object));
3280 return *result;
3281}
3282
3283
3284// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
3285BUILTIN(ArrayBufferConstructor) {
3286 HandleScope scope(isolate);
3287 Handle<JSFunction> target = args.target();
3288 DCHECK(*target == target->native_context()->array_buffer_fun() ||
3289 *target == target->native_context()->shared_array_buffer_fun());
3290 THROW_NEW_ERROR_RETURN_FAILURE(
3291 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
3292 handle(target->shared()->name(), isolate)));
3293}
3294
3295
3296// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
3297BUILTIN(ArrayBufferConstructor_ConstructStub) {
3298 HandleScope scope(isolate);
3299 Handle<JSFunction> target = args.target();
3300 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3301 Handle<Object> length = args.atOrUndefined(isolate, 1);
3302 DCHECK(*target == target->native_context()->array_buffer_fun() ||
3303 *target == target->native_context()->shared_array_buffer_fun());
3304 Handle<Object> number_length;
3305 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
3306 Object::ToInteger(isolate, length));
3307 if (number_length->Number() < 0.0) {
3308 THROW_NEW_ERROR_RETURN_FAILURE(
3309 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
3310 }
3311 Handle<Map> initial_map;
3312 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3313 isolate, initial_map,
3314 JSFunction::GetDerivedMap(isolate, target, new_target));
3315 size_t byte_length;
3316 if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
3317 THROW_NEW_ERROR_RETURN_FAILURE(
3318 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
3319 }
3320 Handle<JSArrayBuffer> result = Handle<JSArrayBuffer>::cast(
3321 isolate->factory()->NewJSObjectFromMap(initial_map));
3322 SharedFlag shared_flag =
3323 (*target == target->native_context()->array_buffer_fun())
3324 ? SharedFlag::kNotShared
3325 : SharedFlag::kShared;
3326 if (!JSArrayBuffer::SetupAllocatingData(result, isolate, byte_length, true,
3327 shared_flag)) {
3328 THROW_NEW_ERROR_RETURN_FAILURE(
3329 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
3330 }
3331 return *result;
3332}
3333
3334
3335// ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
3336BUILTIN(ArrayBufferIsView) {
3337 SealHandleScope shs(isolate);
3338 DCHECK_EQ(2, args.length());
3339 Object* arg = args[1];
3340 return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
3341}
3342
3343
3344// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
3345BUILTIN(ProxyConstructor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003346 HandleScope scope(isolate);
3347 THROW_NEW_ERROR_RETURN_FAILURE(
3348 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003349 NewTypeError(MessageTemplate::kConstructorNotFunction,
3350 isolate->factory()->NewStringFromAsciiChecked("Proxy")));
3351}
3352
3353
3354// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
3355BUILTIN(ProxyConstructor_ConstructStub) {
3356 HandleScope scope(isolate);
3357 DCHECK(isolate->proxy_function()->IsConstructor());
3358 Handle<Object> target = args.atOrUndefined(isolate, 1);
3359 Handle<Object> handler = args.atOrUndefined(isolate, 2);
3360 Handle<JSProxy> result;
3361 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3362 JSProxy::New(isolate, target, handler));
3363 return *result;
3364}
3365
3366
3367// -----------------------------------------------------------------------------
3368// Throwers for restricted function properties and strict arguments object
3369// properties
3370
3371
3372BUILTIN(RestrictedFunctionPropertiesThrower) {
3373 HandleScope scope(isolate);
3374 THROW_NEW_ERROR_RETURN_FAILURE(
3375 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
3376}
3377
3378
3379BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
3380 HandleScope scope(isolate);
3381 THROW_NEW_ERROR_RETURN_FAILURE(
3382 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003383}
3384
3385
Steve Block44f0eee2011-05-26 01:26:41 +01003386// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00003387//
3388
3389
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003390namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +00003391
Leon Clarkee46be812010-01-19 14:06:41 +00003392template <bool is_construct>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003393MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
3394 Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
Steve Block44f0eee2011-05-26 01:26:41 +01003395 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003396 Handle<JSFunction> function = args.target();
3397 DCHECK(args.receiver()->IsJSReceiver());
3398 // TODO(ishell): turn this back to a DCHECK.
3399 CHECK(function->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00003400
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003401 Handle<FunctionTemplateInfo> fun_data(
3402 function->shared()->get_api_func_data(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003403 if (is_construct) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003404 ASSIGN_RETURN_ON_EXCEPTION(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003405 isolate, fun_data,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003406 ApiNatives::ConfigureInstance(isolate, fun_data,
3407 Handle<JSObject>::cast(args.receiver())),
3408 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +00003409 }
3410
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003411 if (!is_construct && !fun_data->accept_any_receiver()) {
3412 Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
3413 if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
3414 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
3415 if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
3416 isolate->ReportFailedAccessCheck(js_receiver);
3417 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3418 }
3419 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003420 }
3421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003422 Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, args[0]);
Steve Blocka7e24c12009-10-30 11:49:00 +00003423
3424 if (raw_holder->IsNull()) {
3425 // This function cannot be called with the given receiver. Abort!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003426 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
3427 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +00003428 }
3429
3430 Object* raw_call_data = fun_data->call_code();
3431 if (!raw_call_data->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003432 // TODO(ishell): remove this debugging code.
3433 CHECK(raw_call_data->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00003434 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
3435 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003436 v8::FunctionCallback callback =
3437 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003438 Object* data_obj = call_data->data();
Steve Blocka7e24c12009-10-30 11:49:00 +00003439
Steve Block44f0eee2011-05-26 01:26:41 +01003440 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003441 DCHECK(raw_holder->IsJSObject());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003442
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003443 FunctionCallbackArguments custom(isolate,
3444 data_obj,
3445 *function,
3446 raw_holder,
3447 &args[0] - 1,
3448 args.length() - 1,
3449 is_construct);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003451 v8::Local<v8::Value> value = custom.Call(callback);
3452 Handle<Object> result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003453 if (value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003454 result = isolate->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003455 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003456 result = v8::Utils::OpenHandle(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003457 result->VerifyApiCallResultType();
Steve Blocka7e24c12009-10-30 11:49:00 +00003458 }
3459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003460 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3461 if (!is_construct || result->IsJSObject()) {
3462 return scope.CloseAndEscape(result);
3463 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003464 }
3465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003466 return scope.CloseAndEscape(args.receiver());
Steve Blocka7e24c12009-10-30 11:49:00 +00003467}
Leon Clarkee46be812010-01-19 14:06:41 +00003468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003469} // namespace
3470
Leon Clarkee46be812010-01-19 14:06:41 +00003471
3472BUILTIN(HandleApiCall) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003473 HandleScope scope(isolate);
3474 Handle<Object> result;
3475 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3476 HandleApiCallHelper<false>(isolate, args));
3477 return *result;
Leon Clarkee46be812010-01-19 14:06:41 +00003478}
3479
3480
3481BUILTIN(HandleApiCallConstruct) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003482 HandleScope scope(isolate);
3483 Handle<Object> result;
3484 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3485 HandleApiCallHelper<true>(isolate, args));
3486 return *result;
3487}
3488
3489
3490Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode) {
3491 switch (mode) {
3492 case ConvertReceiverMode::kNullOrUndefined:
3493 return CallFunction_ReceiverIsNullOrUndefined();
3494 case ConvertReceiverMode::kNotNullOrUndefined:
3495 return CallFunction_ReceiverIsNotNullOrUndefined();
3496 case ConvertReceiverMode::kAny:
3497 return CallFunction_ReceiverIsAny();
3498 }
3499 UNREACHABLE();
3500 return Handle<Code>::null();
3501}
3502
3503
3504Handle<Code> Builtins::Call(ConvertReceiverMode mode) {
3505 switch (mode) {
3506 case ConvertReceiverMode::kNullOrUndefined:
3507 return Call_ReceiverIsNullOrUndefined();
3508 case ConvertReceiverMode::kNotNullOrUndefined:
3509 return Call_ReceiverIsNotNullOrUndefined();
3510 case ConvertReceiverMode::kAny:
3511 return Call_ReceiverIsAny();
3512 }
3513 UNREACHABLE();
3514 return Handle<Code>::null();
3515}
3516
3517
3518namespace {
3519
3520class RelocatableArguments
3521 : public BuiltinArguments<BuiltinExtraArguments::kTarget>,
3522 public Relocatable {
3523 public:
3524 RelocatableArguments(Isolate* isolate, int length, Object** arguments)
3525 : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
3526 Relocatable(isolate) {}
3527
3528 virtual inline void IterateInstance(ObjectVisitor* v) {
3529 if (length() == 0) return;
3530 v->VisitPointers(lowest_address(), highest_address() + 1);
3531 }
3532
3533 private:
3534 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
3535};
3536
3537} // namespace
3538
3539
3540MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<JSFunction> function,
3541 Handle<Object> receiver,
3542 int argc,
3543 Handle<Object> args[]) {
3544 // Construct BuiltinArguments object: function, arguments reversed, receiver.
3545 const int kBufferSize = 32;
3546 Object* small_argv[kBufferSize];
3547 Object** argv;
3548 if (argc + 2 <= kBufferSize) {
3549 argv = small_argv;
3550 } else {
3551 argv = new Object* [argc + 2];
3552 }
3553 argv[argc + 1] = *receiver;
3554 for (int i = 0; i < argc; ++i) {
3555 argv[argc - i] = *args[i];
3556 }
3557 argv[0] = *function;
3558 MaybeHandle<Object> result;
3559 {
3560 auto isolate = function->GetIsolate();
3561 RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
3562 result = HandleApiCallHelper<false>(isolate, arguments);
3563 }
3564 if (argv != small_argv) {
3565 delete[] argv;
3566 }
3567 return result;
Leon Clarkee46be812010-01-19 14:06:41 +00003568}
Steve Blocka7e24c12009-10-30 11:49:00 +00003569
3570
3571// Helper function to handle calls to non-function objects created through the
3572// API. The object can be called as either a constructor (using new) or just as
3573// a function (without new).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003574MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003575 Isolate* isolate, bool is_construct_call,
3576 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Steve Block44f0eee2011-05-26 01:26:41 +01003577 Heap* heap = isolate->heap();
Steve Blocka7e24c12009-10-30 11:49:00 +00003578
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003579 Handle<Object> receiver = args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00003580
3581 // Get the object called.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003582 JSObject* obj = JSObject::cast(*receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00003583
3584 // Get the invocation callback from the function descriptor that was
3585 // used to create the called object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003586 DCHECK(obj->map()->is_callable());
3587 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
3588 // TODO(ishell): turn this back to a DCHECK.
3589 CHECK(constructor->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00003590 Object* handler =
Steve Block6ded16b2010-05-10 14:33:55 +01003591 constructor->shared()->get_api_func_data()->instance_call_handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003592 DCHECK(!handler->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003593 // TODO(ishell): remove this debugging code.
3594 CHECK(handler->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00003595 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
3596 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003597 v8::FunctionCallback callback =
3598 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003599
3600 // Get the data for the call and perform the callback.
Steve Blocka7e24c12009-10-30 11:49:00 +00003601 Object* result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003602 {
Steve Block44f0eee2011-05-26 01:26:41 +01003603 HandleScope scope(isolate);
3604 LOG(isolate, ApiObjectAccess("call non-function", obj));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003605
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003606 FunctionCallbackArguments custom(isolate,
3607 call_data->data(),
3608 constructor,
3609 obj,
3610 &args[0] - 1,
3611 args.length() - 1,
3612 is_construct_call);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003613 v8::Local<v8::Value> value = custom.Call(callback);
Steve Blocka7e24c12009-10-30 11:49:00 +00003614 if (value.IsEmpty()) {
Steve Block44f0eee2011-05-26 01:26:41 +01003615 result = heap->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003616 } else {
3617 result = *reinterpret_cast<Object**>(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003618 result->VerifyApiCallResultType();
Steve Blocka7e24c12009-10-30 11:49:00 +00003619 }
3620 }
3621 // Check for exceptions and return result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003622 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003623 return result;
3624}
3625
3626
3627// Handle calls to non-function objects created through the API. This delegate
3628// function is used when the call is a normal function call.
3629BUILTIN(HandleApiCallAsFunction) {
Steve Block44f0eee2011-05-26 01:26:41 +01003630 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003631}
Steve Blocka7e24c12009-10-30 11:49:00 +00003632
3633
3634// Handle calls to non-function objects created through the API. This delegate
3635// function is used when the call is a construct call.
3636BUILTIN(HandleApiCallAsConstructor) {
Steve Block44f0eee2011-05-26 01:26:41 +01003637 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003638}
Steve Blocka7e24c12009-10-30 11:49:00 +00003639
3640
Steve Blocka7e24c12009-10-30 11:49:00 +00003641static void Generate_LoadIC_Miss(MacroAssembler* masm) {
3642 LoadIC::GenerateMiss(masm);
3643}
3644
3645
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003646static void Generate_LoadIC_Normal(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003647 LoadIC::GenerateNormal(masm, SLOPPY);
3648}
3649
3650
3651static void Generate_LoadIC_Normal_Strong(MacroAssembler* masm) {
3652 LoadIC::GenerateNormal(masm, STRONG);
Steve Blocka7e24c12009-10-30 11:49:00 +00003653}
3654
3655
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003656static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
3657 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
3658}
3659
3660
3661static void Generate_LoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003662 LoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
Steve Blocka7e24c12009-10-30 11:49:00 +00003663}
3664
3665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003666static void Generate_LoadIC_Slow_Strong(MacroAssembler* masm) {
3667 LoadIC::GenerateRuntimeGetProperty(masm, STRONG);
Steve Blocka7e24c12009-10-30 11:49:00 +00003668}
3669
3670
Ben Murdoch257744e2011-11-30 15:57:28 +00003671static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003672 KeyedLoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
3673}
3674
3675
3676static void Generate_KeyedLoadIC_Slow_Strong(MacroAssembler* masm) {
3677 KeyedLoadIC::GenerateRuntimeGetProperty(masm, STRONG);
Ben Murdoch257744e2011-11-30 15:57:28 +00003678}
3679
3680
Steve Blocka7e24c12009-10-30 11:49:00 +00003681static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003682 KeyedLoadIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00003683}
3684
3685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003686static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
3687 KeyedLoadIC::GenerateMegamorphic(masm, SLOPPY);
Steve Blocka7e24c12009-10-30 11:49:00 +00003688}
3689
3690
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003691static void Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler* masm) {
3692 KeyedLoadIC::GenerateMegamorphic(masm, STRONG);
Steve Blocka7e24c12009-10-30 11:49:00 +00003693}
3694
Steve Block1e0659c2011-05-24 12:43:12 +01003695
Steve Blocka7e24c12009-10-30 11:49:00 +00003696static void Generate_StoreIC_Miss(MacroAssembler* masm) {
3697 StoreIC::GenerateMiss(masm);
3698}
3699
3700
Steve Block8defd9f2010-07-08 12:39:36 +01003701static void Generate_StoreIC_Normal(MacroAssembler* masm) {
3702 StoreIC::GenerateNormal(masm);
3703}
3704
3705
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003706static void Generate_StoreIC_Slow(MacroAssembler* masm) {
3707 NamedStoreHandlerCompiler::GenerateSlow(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00003708}
3709
3710
3711static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003712 ElementHandlerCompiler::GenerateStoreSlow(masm);
3713}
3714
3715
3716static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
3717 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
3718}
3719
3720
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003721static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
3722 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
3723}
3724
3725
3726static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
3727 KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
3728}
3729
3730
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003731static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
3732 KeyedStoreIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00003733}
3734
3735
3736static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
3737 KeyedStoreIC::GenerateInitialize(masm);
3738}
3739
3740
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003741static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
3742 KeyedStoreIC::GenerateInitialize(masm);
3743}
3744
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003745
3746static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
3747 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003748}
Ben Murdoche0cee9b2011-05-25 10:26:03 +01003749
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003750
3751static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
3752 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003753}
3754
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003755
Steve Blocka7e24c12009-10-30 11:49:00 +00003756static void Generate_Return_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003757 DebugCodegen::GenerateDebugBreakStub(masm,
3758 DebugCodegen::SAVE_RESULT_REGISTER);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01003759}
3760
3761
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003762static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003763 DebugCodegen::GenerateDebugBreakStub(masm,
3764 DebugCodegen::IGNORE_RESULT_REGISTER);
Steve Block6ded16b2010-05-10 14:33:55 +01003765}
3766
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01003767
Steve Block6ded16b2010-05-10 14:33:55 +01003768static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003769 DebugCodegen::GenerateFrameDropperLiveEdit(masm);
Steve Block6ded16b2010-05-10 14:33:55 +01003770}
Steve Blocka7e24c12009-10-30 11:49:00 +00003771
Steve Block44f0eee2011-05-26 01:26:41 +01003772
3773Builtins::Builtins() : initialized_(false) {
3774 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
3775 memset(names_, 0, sizeof(names_[0]) * builtin_count);
3776}
3777
3778
3779Builtins::~Builtins() {
3780}
3781
Steve Blocka7e24c12009-10-30 11:49:00 +00003782
Leon Clarkee46be812010-01-19 14:06:41 +00003783#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
Steve Block44f0eee2011-05-26 01:26:41 +01003784Address const Builtins::c_functions_[cfunction_count] = {
3785 BUILTIN_LIST_C(DEF_ENUM_C)
3786};
Steve Blocka7e24c12009-10-30 11:49:00 +00003787#undef DEF_ENUM_C
3788
Steve Blocka7e24c12009-10-30 11:49:00 +00003789
Steve Block44f0eee2011-05-26 01:26:41 +01003790struct BuiltinDesc {
3791 byte* generator;
3792 byte* c_code;
3793 const char* s_name; // name is only used for generating log information.
3794 int name;
3795 Code::Flags flags;
3796 BuiltinExtraArguments extra_args;
3797};
3798
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003799#define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
3800
Steve Block44f0eee2011-05-26 01:26:41 +01003801class BuiltinFunctionTable {
3802 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003803 BuiltinDesc* functions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003804 base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003805 return functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01003806 }
3807
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003808 base::OnceType once_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003809 BuiltinDesc functions_[Builtins::builtin_count + 1];
Steve Block44f0eee2011-05-26 01:26:41 +01003810
3811 friend class Builtins;
3812};
3813
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003814static BuiltinFunctionTable builtin_function_table =
3815 BUILTIN_FUNCTION_TABLE_INIT;
Steve Block44f0eee2011-05-26 01:26:41 +01003816
3817// Define array of pointers to generators and C builtin functions.
3818// We do this in a sort of roundabout way so that we can do the initialization
3819// within the lexical scope of Builtins:: and within a context where
3820// Code::Flags names a non-abstract type.
3821void Builtins::InitBuiltinFunctionTable() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003822 BuiltinDesc* functions = builtin_function_table.functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01003823 functions[builtin_count].generator = NULL;
3824 functions[builtin_count].c_code = NULL;
3825 functions[builtin_count].s_name = NULL;
3826 functions[builtin_count].name = builtin_count;
3827 functions[builtin_count].flags = static_cast<Code::Flags>(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003828 functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
Steve Block44f0eee2011-05-26 01:26:41 +01003829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003830#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
3831 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
3832 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
3833 functions->s_name = #aname; \
3834 functions->name = c_##aname; \
3835 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
3836 functions->extra_args = BuiltinExtraArguments::aextra_args; \
3837 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01003838
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003839#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
3840 functions->generator = FUNCTION_ADDR(Generate_##aname); \
3841 functions->c_code = NULL; \
3842 functions->s_name = #aname; \
3843 functions->name = k##aname; \
3844 functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
3845 functions->extra_args = BuiltinExtraArguments::kNone; \
3846 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01003847
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003848#define DEF_FUNCTION_PTR_H(aname, kind) \
3849 functions->generator = FUNCTION_ADDR(Generate_##aname); \
3850 functions->c_code = NULL; \
3851 functions->s_name = #aname; \
3852 functions->name = k##aname; \
3853 functions->flags = Code::ComputeHandlerFlags(Code::kind); \
3854 functions->extra_args = BuiltinExtraArguments::kNone; \
3855 ++functions;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003856
Steve Block44f0eee2011-05-26 01:26:41 +01003857 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
3858 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003859 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01003860 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
3861
3862#undef DEF_FUNCTION_PTR_C
3863#undef DEF_FUNCTION_PTR_A
3864}
3865
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003866
3867void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
3868 DCHECK(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003869
3870 // Create a scope for the handles in the builtins.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003871 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00003872
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003873 const BuiltinDesc* functions = builtin_function_table.functions();
Steve Blocka7e24c12009-10-30 11:49:00 +00003874
3875 // For now we generate builtin adaptor code into a stack-allocated
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003876 // buffer, before copying it into individual code objects. Be careful
3877 // with alignment, some platforms don't like unaligned code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003878#ifdef DEBUG
3879 // We can generate a lot of debug code on Arm64.
3880 const size_t buffer_size = 32*KB;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003881#elif V8_TARGET_ARCH_PPC64
3882 // 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
3883 const size_t buffer_size = 10 * KB;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003884#else
3885 const size_t buffer_size = 8*KB;
3886#endif
3887 union { int force_alignment; byte buffer[buffer_size]; } u;
Steve Blocka7e24c12009-10-30 11:49:00 +00003888
3889 // Traverse the list of builtins and generate an adaptor in a
3890 // separate code object for each one.
3891 for (int i = 0; i < builtin_count; i++) {
3892 if (create_heap_objects) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003893 MacroAssembler masm(isolate, u.buffer, sizeof u.buffer,
3894 CodeObjectRequired::kYes);
Steve Blocka7e24c12009-10-30 11:49:00 +00003895 // Generate the code/adaptor.
Leon Clarkee46be812010-01-19 14:06:41 +00003896 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00003897 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
3898 // We pass all arguments to the generator, but it may not use all of
3899 // them. This works because the first arguments are on top of the
3900 // stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003901 DCHECK(!masm.has_frame());
Leon Clarkee46be812010-01-19 14:06:41 +00003902 g(&masm, functions[i].name, functions[i].extra_args);
Steve Blocka7e24c12009-10-30 11:49:00 +00003903 // Move the code into the object heap.
3904 CodeDesc desc;
3905 masm.GetCode(&desc);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003906 Code::Flags flags = functions[i].flags;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003907 Handle<Code> code =
3908 isolate->factory()->NewCode(desc, flags, masm.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00003909 // Log the event and add the code to the builtins array.
Ben Murdoch8b112d22011-06-08 16:22:53 +01003910 PROFILE(isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003911 CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
3912 builtins_[i] = *code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003913 code->set_builtin_index(i);
Steve Blocka7e24c12009-10-30 11:49:00 +00003914#ifdef ENABLE_DISASSEMBLER
3915 if (FLAG_print_builtin_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003916 CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
3917 OFStream os(trace_scope.file());
3918 os << "Builtin: " << functions[i].s_name << "\n";
3919 code->Disassemble(functions[i].s_name, os);
3920 os << "\n";
Steve Blocka7e24c12009-10-30 11:49:00 +00003921 }
3922#endif
3923 } else {
3924 // Deserializing. The values will be filled in during IterateBuiltins.
3925 builtins_[i] = NULL;
3926 }
3927 names_[i] = functions[i].s_name;
3928 }
3929
3930 // Mark as initialized.
Steve Block44f0eee2011-05-26 01:26:41 +01003931 initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003932}
3933
3934
3935void Builtins::TearDown() {
Steve Block44f0eee2011-05-26 01:26:41 +01003936 initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003937}
3938
3939
3940void Builtins::IterateBuiltins(ObjectVisitor* v) {
3941 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
3942}
3943
3944
3945const char* Builtins::Lookup(byte* pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01003946 // may be called during initialization (disassembler!)
3947 if (initialized_) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003948 for (int i = 0; i < builtin_count; i++) {
3949 Code* entry = Code::cast(builtins_[i]);
3950 if (entry->contains(pc)) {
3951 return names_[i];
3952 }
3953 }
3954 }
3955 return NULL;
3956}
3957
Ben Murdochb0fe1622011-05-05 13:52:32 +01003958
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003959void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003960 masm->TailCallRuntime(Runtime::kInterrupt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003961}
3962
3963
3964void Builtins::Generate_StackCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003965 masm->TailCallRuntime(Runtime::kStackGuard);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003966}
3967
3968
Steve Block44f0eee2011-05-26 01:26:41 +01003969#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
3970Handle<Code> Builtins::name() { \
3971 Code** code_address = \
3972 reinterpret_cast<Code**>(builtin_address(k##name)); \
3973 return Handle<Code>(code_address); \
3974}
3975#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
3976Handle<Code> Builtins::name() { \
3977 Code** code_address = \
3978 reinterpret_cast<Code**>(builtin_address(k##name)); \
3979 return Handle<Code>(code_address); \
3980}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003981#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
3982Handle<Code> Builtins::name() { \
3983 Code** code_address = \
3984 reinterpret_cast<Code**>(builtin_address(k##name)); \
3985 return Handle<Code>(code_address); \
3986}
Steve Block44f0eee2011-05-26 01:26:41 +01003987BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
3988BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003989BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01003990BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
3991#undef DEFINE_BUILTIN_ACCESSOR_C
3992#undef DEFINE_BUILTIN_ACCESSOR_A
3993
3994
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003995} // namespace internal
3996} // namespace v8