blob: 23c41f706eb1c70d301639ef408b54cb2f69fa83 [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 Murdoch097c5b22016-05-18 11:27:45 +010062 template <class S>
63 Handle<S> target();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064 Handle<HeapObject> new_target();
Leon Clarkee46be812010-01-19 14:06:41 +000065
66 // Gets the total number of arguments including the receiver (but
67 // excluding extra arguments).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 int length() const;
Leon Clarkee46be812010-01-19 14:06:41 +000069};
70
71
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072// Specialize BuiltinArguments for the extra arguments.
Leon Clarkee46be812010-01-19 14:06:41 +000073
74template <>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
76 return Arguments::length();
77}
78
79template <>
80int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
Leon Clarkee46be812010-01-19 14:06:41 +000081 return Arguments::length() - 1;
82}
83
Leon Clarkee46be812010-01-19 14:06:41 +000084template <>
Ben Murdoch097c5b22016-05-18 11:27:45 +010085template <class S>
86Handle<S> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
87 return Arguments::at<S>(Arguments::length() - 1);
Leon Clarkee46be812010-01-19 14:06:41 +000088}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089
90template <>
91int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
92 return Arguments::length() - 1;
93}
94
95template <>
96Handle<HeapObject>
97BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
98 return Arguments::at<HeapObject>(Arguments::length() - 1);
99}
100
101template <>
102int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
103 const {
104 return Arguments::length() - 2;
105}
106
107template <>
Ben Murdoch097c5b22016-05-18 11:27:45 +0100108template <class S>
109Handle<S>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111 return Arguments::at<S>(Arguments::length() - 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112}
113
114template <>
115Handle<HeapObject>
116BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
117 return Arguments::at<HeapObject>(Arguments::length() - 1);
118}
Leon Clarkee46be812010-01-19 14:06:41 +0000119
120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121#define DEF_ARG_TYPE(name, spec) \
122 typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
Leon Clarkee46be812010-01-19 14:06:41 +0000123BUILTIN_LIST_C(DEF_ARG_TYPE)
124#undef DEF_ARG_TYPE
125
Leon Clarkee46be812010-01-19 14:06:41 +0000126
Steve Blocka7e24c12009-10-30 11:49:00 +0000127// ----------------------------------------------------------------------------
Leon Clarkee46be812010-01-19 14:06:41 +0000128// Support macro for defining builtins in C++.
Steve Blocka7e24c12009-10-30 11:49:00 +0000129// ----------------------------------------------------------------------------
130//
131// A builtin function is defined by writing:
132//
133// BUILTIN(name) {
134// ...
135// }
Steve Blocka7e24c12009-10-30 11:49:00 +0000136//
Leon Clarkee46be812010-01-19 14:06:41 +0000137// In the body of the builtin function the arguments can be accessed
138// through the BuiltinArguments object args.
Steve Blocka7e24c12009-10-30 11:49:00 +0000139
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140#define BUILTIN(name) \
141 MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
142 Isolate* isolate); \
143 MUST_USE_RESULT static Object* Builtin_##name( \
144 int args_length, Object** args_object, Isolate* isolate) { \
145 isolate->counters()->runtime_calls()->Increment(); \
146 RuntimeCallStats* stats = isolate->counters()->runtime_call_stats(); \
147 RuntimeCallTimerScope timer(isolate, &stats->Builtin_##name); \
148 name##ArgumentsType args(args_length, args_object); \
149 Object* value = Builtin_Impl_##name(args, isolate); \
150 return value; \
151 } \
152 \
153 MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
154 Isolate* isolate)
Steve Blocka7e24c12009-10-30 11:49:00 +0000155
156// ----------------------------------------------------------------------------
157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158
159#define CHECK_RECEIVER(Type, name, method) \
160 if (!args.receiver()->Is##Type()) { \
161 THROW_NEW_ERROR_RETURN_FAILURE( \
162 isolate, \
163 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
164 isolate->factory()->NewStringFromAsciiChecked(method), \
165 args.receiver())); \
166 } \
167 Handle<Type> name = Handle<Type>::cast(args.receiver())
168
169
170inline bool ClampedToInteger(Object* object, int* out) {
171 // This is an extended version of ECMA-262 7.1.11 handling signed values
172 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
173 if (object->IsSmi()) {
174 *out = Smi::cast(object)->value();
175 return true;
176 } else if (object->IsHeapNumber()) {
177 double value = HeapNumber::cast(object)->value();
178 if (std::isnan(value)) {
179 *out = 0;
180 } else if (value > kMaxInt) {
181 *out = kMaxInt;
182 } else if (value < kMinInt) {
183 *out = kMinInt;
184 } else {
185 *out = static_cast<int>(value);
186 }
187 return true;
188 } else if (object->IsUndefined() || object->IsNull()) {
189 *out = 0;
190 return true;
191 } else if (object->IsBoolean()) {
192 *out = object->IsTrue();
193 return true;
194 }
195 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000196}
Steve Blocka7e24c12009-10-30 11:49:00 +0000197
198
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
200 int* out) {
201 Map* arguments_map = isolate->native_context()->sloppy_arguments_map();
202 if (object->map() != arguments_map) return false;
203 DCHECK(object->HasFastElements());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100204 Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 if (!len_obj->IsSmi()) return false;
206 *out = Max(0, Smi::cast(len_obj)->value());
207 return *out <= object->elements()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000208}
Steve Blocka7e24c12009-10-30 11:49:00 +0000209
210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211inline bool PrototypeHasNoElements(PrototypeIterator* iter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 DisallowHeapAllocation no_gc;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 for (; !iter->IsAtEnd(); iter->Advance()) {
214 if (iter->GetCurrent()->IsJSProxy()) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 JSObject* current = iter->GetCurrent<JSObject>();
216 if (current->IsAccessCheckNeeded()) return false;
217 if (current->HasIndexedInterceptor()) return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100218 if (current->HasStringWrapperElements()) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219 if (current->elements()->length() != 0) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400221 return true;
222}
223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
225 JSArray* receiver) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400226 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 // If the array prototype chain is intact (and free of elements), and if the
228 // receiver's prototype is the array prototype, then we are done.
229 Object* prototype = receiver->map()->prototype();
230 if (prototype->IsJSArray() &&
231 isolate->is_initial_array_prototype(JSArray::cast(prototype)) &&
232 isolate->IsFastArrayConstructorPrototypeChainIntact()) {
233 return true;
234 }
235
236 // Slow case.
237 PrototypeIterator iter(isolate, receiver);
238 return PrototypeHasNoElements(&iter);
Steve Block6ded16b2010-05-10 14:33:55 +0100239}
240
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241inline bool HasSimpleElements(JSObject* current) {
242 if (current->IsAccessCheckNeeded()) return false;
243 if (current->HasIndexedInterceptor()) return false;
244 if (current->HasStringWrapperElements()) return false;
245 if (current->GetElementsAccessor()->HasAccessors(current)) return false;
246 return true;
247}
248
249inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
250 JSReceiver* receiver) {
251 // Check that we have no accessors on the receiver's elements.
252 JSObject* object = JSObject::cast(receiver);
253 if (!HasSimpleElements(object)) return false;
254 // Check that ther are not elements on the prototype.
255 DisallowHeapAllocation no_gc;
256 PrototypeIterator iter(isolate, receiver);
257 return PrototypeHasNoElements(&iter);
258}
259
260inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
261 // Check that ther are not elements on the prototype.
262 DisallowHeapAllocation no_gc;
263 PrototypeIterator iter(isolate, receiver,
264 PrototypeIterator::START_AT_RECEIVER);
265 for (; !iter.IsAtEnd(); iter.Advance()) {
266 if (iter.GetCurrent()->IsJSProxy()) return false;
267 JSObject* current = iter.GetCurrent<JSObject>();
268 if (!HasSimpleElements(current)) return false;
269 }
270 return true;
271}
Steve Block6ded16b2010-05-10 14:33:55 +0100272
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273// Returns empty handle if not applicable.
John Reck59135872010-11-02 12:39:01 -0700274MUST_USE_RESULT
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
276 Isolate* isolate, Handle<Object> receiver, Arguments* args,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 int first_added_arg) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100278 // We explicitly add a HandleScope to avoid creating several copies of the
279 // same handle which would otherwise cause issue when left-trimming later-on.
280 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
282 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
283 // If there may be elements accessors in the prototype chain, the fast path
284 // cannot be used if there arguments to add to the array.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400285 Heap* heap = isolate->heap();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 return MaybeHandle<FixedArrayBase>();
288 }
289 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
290 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
291 Handle<FixedArrayBase> elms(array->elements(), isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100292 Map* map = elms->map();
293 if (map == heap->fixed_array_map()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100294 if (args == NULL || array->HasFastObjectElements()) {
295 return scope.CloseAndEscape(elms);
296 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100297 } else if (map == heap->fixed_cow_array_map()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 elms = JSObject::EnsureWritableFastElements(array);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100299 if (args == NULL || array->HasFastObjectElements()) {
300 return scope.CloseAndEscape(elms);
301 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 } else if (map == heap->fixed_double_array_map()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100303 if (args == NULL) {
304 return scope.CloseAndEscape(elms);
305 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100306 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 return MaybeHandle<FixedArrayBase>();
Steve Block6ded16b2010-05-10 14:33:55 +0100308 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 // Adding elements to the array prototype would break code that makes sure
311 // it has no elements. Handle that elsewhere.
312 if (isolate->IsAnyInitialArrayPrototype(array)) {
313 return MaybeHandle<FixedArrayBase>();
314 }
315
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100316 // Need to ensure that the arguments passed in args can be contained in
317 // the array.
318 int args_length = args->length();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100319 if (first_added_arg >= args_length) {
320 return scope.CloseAndEscape(elms);
321 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100322
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 ElementsKind origin_kind = array->map()->elements_kind();
324 DCHECK(!IsFastObjectElementsKind(origin_kind));
325 ElementsKind target_kind = origin_kind;
326 {
327 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328 int arg_count = args_length - first_added_arg;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1);
330 for (int i = 0; i < arg_count; i++) {
331 Object* arg = arguments[i];
332 if (arg->IsHeapObject()) {
333 if (arg->IsHeapNumber()) {
334 target_kind = FAST_DOUBLE_ELEMENTS;
335 } else {
336 target_kind = FAST_ELEMENTS;
337 break;
338 }
339 }
340 }
341 }
342 if (target_kind != origin_kind) {
343 JSObject::TransitionElementsKind(array, target_kind);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100344 elms = handle(array->elements(), isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100346 return scope.CloseAndEscape(elms);
Steve Block6ded16b2010-05-10 14:33:55 +0100347}
348
349
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350MUST_USE_RESULT static Object* CallJsIntrinsic(
351 Isolate* isolate, Handle<JSFunction> function,
352 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100353 HandleScope handleScope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100354 int argc = args.length() - 1;
355 ScopedVector<Handle<Object> > argv(argc);
356 for (int i = 0; i < argc; ++i) {
357 argv[i] = args.at<Object>(i + 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100358 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 Handle<Object> result;
360 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
361 isolate, result,
362 Execution::Call(isolate,
363 function,
364 args.receiver(),
365 argc,
366 argv.start()));
Steve Block6ded16b2010-05-10 14:33:55 +0100367 return *result;
368}
369
370
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371} // namespace
372
373
374BUILTIN(Illegal) {
375 UNREACHABLE();
376 return isolate->heap()->undefined_value(); // Make compiler happy.
377}
378
379
380BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
381
382
Steve Blocka7e24c12009-10-30 11:49:00 +0000383BUILTIN(ArrayPush) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000384 HandleScope scope(isolate);
385 Handle<Object> receiver = args.receiver();
386 MaybeHandle<FixedArrayBase> maybe_elms_obj =
387 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
388 Handle<FixedArrayBase> elms_obj;
389 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000390 return CallJsIntrinsic(isolate, isolate->array_push(), args);
John Reck59135872010-11-02 12:39:01 -0700391 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 // Fast Elements Path
393 int push_size = args.length() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000395 int len = Smi::cast(array->length())->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 if (push_size == 0) {
397 return Smi::FromInt(len);
398 }
399 if (push_size > 0 &&
400 JSArray::WouldChangeReadOnlyLength(array, len + push_size)) {
401 return CallJsIntrinsic(isolate, isolate->array_push(), args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000402 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000403 DCHECK(!array->map()->is_observed());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 ElementsAccessor* accessor = array->GetElementsAccessor();
405 int new_length = accessor->Push(array, elms_obj, &args, push_size);
406 return Smi::FromInt(new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000407}
Steve Blocka7e24c12009-10-30 11:49:00 +0000408
409
410BUILTIN(ArrayPop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411 HandleScope scope(isolate);
412 Handle<Object> receiver = args.receiver();
413 MaybeHandle<FixedArrayBase> maybe_elms_obj =
414 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
415 Handle<FixedArrayBase> elms_obj;
416 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
John Reck59135872010-11-02 12:39:01 -0700418 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419
420 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
421 DCHECK(!array->map()->is_observed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000422
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 if (len == 0) return isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000425
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400426 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400428 }
429
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 Handle<Object> result;
431 if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
432 // Fast Elements Path
433 result = array->GetElementsAccessor()->Pop(array, elms_obj);
434 } else {
435 // Use Slow Lookup otherwise
436 uint32_t new_length = len - 1;
437 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
438 isolate, result, Object::GetElement(isolate, array, new_length));
439 JSArray::SetLength(array, new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000440 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 return *result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000442}
Steve Blocka7e24c12009-10-30 11:49:00 +0000443
444
Andrei Popescu402d9372010-02-26 13:31:12 +0000445BUILTIN(ArrayShift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100447 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 Handle<Object> receiver = args.receiver();
449 MaybeHandle<FixedArrayBase> maybe_elms_obj =
450 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
451 Handle<FixedArrayBase> elms_obj;
452 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
454 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100455 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
457 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000458
459 int len = Smi::cast(array->length())->value();
Steve Block44f0eee2011-05-26 01:26:41 +0100460 if (len == 0) return heap->undefined_value();
Andrei Popescu402d9372010-02-26 13:31:12 +0000461
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400462 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000463 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400464 }
465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 Handle<Object> first = array->GetElementsAccessor()->Shift(array, elms_obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000467 return *first;
Andrei Popescu402d9372010-02-26 13:31:12 +0000468}
469
470
471BUILTIN(ArrayUnshift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473 Handle<Object> receiver = args.receiver();
474 MaybeHandle<FixedArrayBase> maybe_elms_obj =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 Handle<FixedArrayBase> elms_obj;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400477 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100479 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
481 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000482 int to_add = args.length() - 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 if (to_add == 0) {
484 return array->length();
485 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000486 // Currently fixed arrays cannot grow too big, so
487 // we should never hit this case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 DCHECK(to_add <= (Smi::kMaxValue - Smi::cast(array->length())->value()));
Andrei Popescu402d9372010-02-26 13:31:12 +0000489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 if (to_add > 0 && JSArray::HasReadOnlyLength(array)) {
491 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000492 }
493
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 ElementsAccessor* accessor = array->GetElementsAccessor();
495 int new_length = accessor->Unshift(array, elms_obj, &args, to_add);
Andrei Popescu402d9372010-02-26 13:31:12 +0000496 return Smi::FromInt(new_length);
497}
498
499
Andrei Popescu402d9372010-02-26 13:31:12 +0000500BUILTIN(ArraySlice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502 Handle<Object> receiver = args.receiver();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503 Handle<JSObject> object;
504 Handle<FixedArrayBase> elms_obj;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100505 int len = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 int relative_start = 0;
507 int relative_end = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 bool is_sloppy_arguments = false;
509
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 if (receiver->IsJSArray()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 JSArray* array = JSArray::cast(*receiver);
513 if (!array->HasFastElements() ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100514 !IsJSArrayFastElementMovingAllowed(isolate, array) ||
515 !isolate->IsArraySpeciesLookupChainIntact() ||
516 // If this is a subclass of Array, then call out to JS
517 !array->map()->new_target_is_base()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 AllowHeapAllocation allow_allocation;
519 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Steve Block9fac8402011-05-12 15:51:54 +0100520 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000521 len = Smi::cast(array->length())->value();
522 object = Handle<JSObject>::cast(receiver);
523 elms_obj = handle(array->elements(), isolate);
524 } else if (receiver->IsJSObject() &&
525 GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
526 &len)) {
527 // Array.prototype.slice(arguments, ...) is quite a common idiom
528 // (notably more than 50% of invocations in Web apps).
529 // Treat it in C++ as well.
530 is_sloppy_arguments = true;
531 object = Handle<JSObject>::cast(receiver);
532 elms_obj = handle(object->elements(), isolate);
533 } else {
534 AllowHeapAllocation allow_allocation;
535 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
536 }
537 DCHECK(len >= 0);
538 int argument_count = args.length() - 1;
539 // Note carefully chosen defaults---if argument is missing,
540 // it's undefined which gets converted to 0 for relative_start
541 // and to len for relative_end.
542 relative_start = 0;
543 relative_end = len;
544 if (argument_count > 0) {
545 DisallowHeapAllocation no_gc;
546 if (!ClampedToInteger(args[1], &relative_start)) {
547 AllowHeapAllocation allow_allocation;
548 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
549 }
550 if (argument_count > 1) {
551 Object* end_arg = args[2];
552 // slice handles the end_arg specially
553 if (end_arg->IsUndefined()) {
554 relative_end = len;
555 } else if (!ClampedToInteger(end_arg, &relative_end)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000559 }
560 }
561
562 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
564 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000565
566 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 uint32_t actual_end =
568 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 if (actual_end <= actual_start) {
571 Handle<JSArray> result_array = isolate->factory()->NewJSArray(
572 GetPackedElementsKind(object->GetElementsKind()), 0, 0);
573 return *result_array;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000574 }
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100575
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 ElementsAccessor* accessor = object->GetElementsAccessor();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000577 if (is_sloppy_arguments &&
578 !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) {
579 // Don't deal with arguments with holes in C++
580 AllowHeapAllocation allow_allocation;
581 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
582 }
583 Handle<JSArray> result_array =
584 accessor->Slice(object, elms_obj, actual_start, actual_end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000585 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000586}
587
588
589BUILTIN(ArraySplice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591 Handle<Object> receiver = args.receiver();
592 MaybeHandle<FixedArrayBase> maybe_elms_obj =
593 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
594 Handle<FixedArrayBase> elms_obj;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100595 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
596 // If this is a subclass of Array, then call out to JS
597 !JSArray::cast(*receiver)->map()->new_target_is_base() ||
598 // If anything with @@species has been messed with, call out to JS
599 !isolate->IsArraySpeciesLookupChainIntact()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100601 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000602 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
603 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000604
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 int argument_count = args.length() - 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100606 int relative_start = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 if (argument_count > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000608 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 if (!ClampedToInteger(args[1], &relative_start)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100612 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000613 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614 int len = Smi::cast(array->length())->value();
615 // clip relative start to [0, len]
Steve Block6ded16b2010-05-10 14:33:55 +0100616 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
617 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000618
Steve Block1e0659c2011-05-24 12:43:12 +0100619 int actual_delete_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 if (argument_count == 1) {
621 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
622 // given as a request to delete all the elements from the start.
623 // And it differs from the case of undefined delete count.
624 // This does not follow ECMA-262, but we do the same for compatibility.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 DCHECK(len - actual_start >= 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100626 actual_delete_count = len - actual_start;
627 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 int delete_count = 0;
629 DisallowHeapAllocation no_gc;
630 if (argument_count > 1) {
631 if (!ClampedToInteger(args[2], &delete_count)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100634 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000635 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636 actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
Andrei Popescu402d9372010-02-26 13:31:12 +0000637 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000638
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
640 int new_length = len - actual_delete_count + add_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400642 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
643 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400645 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000646 ElementsAccessor* accessor = array->GetElementsAccessor();
647 Handle<JSArray> result_array = accessor->Splice(
648 array, elms_obj, actual_start, actual_delete_count, &args, add_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000650}
651
652
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653// Array Concat -------------------------------------------------------------
Steve Block6ded16b2010-05-10 14:33:55 +0100654
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655namespace {
656
657/**
658 * A simple visitor visits every element of Array's.
659 * The backend storage can be a fixed array for fast elements case,
660 * or a dictionary for sparse array. Since Dictionary is a subtype
661 * of FixedArray, the class can be used by both fast and slow cases.
662 * The second parameter of the constructor, fast_elements, specifies
663 * whether the storage is a FixedArray or Dictionary.
664 *
665 * An index limit is used to deal with the situation that a result array
666 * length overflows 32-bit non-negative integer.
667 */
668class ArrayConcatVisitor {
669 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100670 ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000671 bool fast_elements)
672 : isolate_(isolate),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100673 storage_(isolate->global_handles()->Create(*storage)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 index_offset_(0u),
675 bit_field_(FastElementsField::encode(fast_elements) |
Ben Murdoch097c5b22016-05-18 11:27:45 +0100676 ExceedsLimitField::encode(false) |
677 IsFixedArrayField::encode(storage->IsFixedArray())) {
678 DCHECK(!(this->fast_elements() && !is_fixed_array()));
679 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000680
681 ~ArrayConcatVisitor() { clear_storage(); }
682
Ben Murdoch097c5b22016-05-18 11:27:45 +0100683 bool visit(uint32_t i, Handle<Object> elm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684 uint32_t index = index_offset_ + i;
685
Ben Murdoch097c5b22016-05-18 11:27:45 +0100686 if (!is_fixed_array()) {
687 Handle<Object> element_value;
688 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
689 isolate_, element_value,
690 Object::SetElement(isolate_, storage_, index, elm, STRICT), false);
691 return true;
692 }
693
694 if (i >= JSObject::kMaxElementCount - index_offset_) {
695 set_exceeds_array_limit(true);
696 // Exception hasn't been thrown at this point. Return true to
697 // break out, and caller will throw. !visit would imply that
698 // there is already a pending exception.
699 return true;
700 }
701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 if (fast_elements()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100703 if (index < static_cast<uint32_t>(storage_fixed_array()->length())) {
704 storage_fixed_array()->set(index, *elm);
705 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 }
707 // Our initial estimate of length was foiled, possibly by
708 // getters on the arrays increasing the length of later arrays
709 // during iteration.
710 // This shouldn't happen in anything but pathological cases.
711 SetDictionaryMode();
712 // Fall-through to dictionary mode.
713 }
714 DCHECK(!fast_elements());
715 Handle<SeededNumberDictionary> dict(
716 SeededNumberDictionary::cast(*storage_));
717 // The object holding this backing store has just been allocated, so
718 // it cannot yet be used as a prototype.
719 Handle<SeededNumberDictionary> result =
720 SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
721 if (!result.is_identical_to(dict)) {
722 // Dictionary needed to grow.
723 clear_storage();
724 set_storage(*result);
725 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100726 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 }
728
729 void increase_index_offset(uint32_t delta) {
730 if (JSObject::kMaxElementCount - index_offset_ < delta) {
731 index_offset_ = JSObject::kMaxElementCount;
732 } else {
733 index_offset_ += delta;
734 }
735 // If the initial length estimate was off (see special case in visit()),
736 // but the array blowing the limit didn't contain elements beyond the
737 // provided-for index range, go to dictionary mode now.
738 if (fast_elements() &&
739 index_offset_ >
740 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
741 SetDictionaryMode();
742 }
743 }
744
745 bool exceeds_array_limit() const {
746 return ExceedsLimitField::decode(bit_field_);
747 }
748
749 Handle<JSArray> ToArray() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100750 DCHECK(is_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000751 Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
752 Handle<Object> length =
753 isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
754 Handle<Map> map = JSObject::GetElementsTransitionMap(
755 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
756 array->set_map(*map);
757 array->set_length(*length);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100758 array->set_elements(*storage_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 return array;
760 }
761
Ben Murdoch097c5b22016-05-18 11:27:45 +0100762 // Storage is either a FixedArray (if is_fixed_array()) or a JSReciever
763 // (otherwise)
764 Handle<FixedArray> storage_fixed_array() {
765 DCHECK(is_fixed_array());
766 return Handle<FixedArray>::cast(storage_);
767 }
768 Handle<JSReceiver> storage_jsreceiver() {
769 DCHECK(!is_fixed_array());
770 return Handle<JSReceiver>::cast(storage_);
771 }
772
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773 private:
774 // Convert storage to dictionary mode.
775 void SetDictionaryMode() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100776 DCHECK(fast_elements() && is_fixed_array());
777 Handle<FixedArray> current_storage = storage_fixed_array();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000778 Handle<SeededNumberDictionary> slow_storage(
779 SeededNumberDictionary::New(isolate_, current_storage->length()));
780 uint32_t current_length = static_cast<uint32_t>(current_storage->length());
781 for (uint32_t i = 0; i < current_length; i++) {
782 HandleScope loop_scope(isolate_);
783 Handle<Object> element(current_storage->get(i), isolate_);
784 if (!element->IsTheHole()) {
785 // The object holding this backing store has just been allocated, so
786 // it cannot yet be used as a prototype.
787 Handle<SeededNumberDictionary> new_storage =
788 SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
789 false);
790 if (!new_storage.is_identical_to(slow_storage)) {
791 slow_storage = loop_scope.CloseAndEscape(new_storage);
792 }
793 }
794 }
795 clear_storage();
796 set_storage(*slow_storage);
797 set_fast_elements(false);
798 }
799
800 inline void clear_storage() {
801 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
802 }
803
804 inline void set_storage(FixedArray* storage) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100805 DCHECK(is_fixed_array());
806 storage_ = isolate_->global_handles()->Create(storage);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 }
808
809 class FastElementsField : public BitField<bool, 0, 1> {};
810 class ExceedsLimitField : public BitField<bool, 1, 1> {};
Ben Murdoch097c5b22016-05-18 11:27:45 +0100811 class IsFixedArrayField : public BitField<bool, 2, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000812
813 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
814 void set_fast_elements(bool fast) {
815 bit_field_ = FastElementsField::update(bit_field_, fast);
816 }
817 void set_exceeds_array_limit(bool exceeds) {
818 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
819 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100820 bool is_fixed_array() const { return IsFixedArrayField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821
822 Isolate* isolate_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100823 Handle<Object> storage_; // Always a global handle.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 // Index after last seen index. Always less than or equal to
825 // JSObject::kMaxElementCount.
826 uint32_t index_offset_;
827 uint32_t bit_field_;
828};
829
830
831uint32_t EstimateElementCount(Handle<JSArray> array) {
832 uint32_t length = static_cast<uint32_t>(array->length()->Number());
833 int element_count = 0;
834 switch (array->GetElementsKind()) {
835 case FAST_SMI_ELEMENTS:
836 case FAST_HOLEY_SMI_ELEMENTS:
837 case FAST_ELEMENTS:
838 case FAST_HOLEY_ELEMENTS: {
839 // Fast elements can't have lengths that are not representable by
840 // a 32-bit signed integer.
841 DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
842 int fast_length = static_cast<int>(length);
843 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
844 for (int i = 0; i < fast_length; i++) {
845 if (!elements->get(i)->IsTheHole()) element_count++;
846 }
847 break;
848 }
849 case FAST_DOUBLE_ELEMENTS:
850 case FAST_HOLEY_DOUBLE_ELEMENTS: {
851 // Fast elements can't have lengths that are not representable by
852 // a 32-bit signed integer.
853 DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
854 int fast_length = static_cast<int>(length);
855 if (array->elements()->IsFixedArray()) {
856 DCHECK(FixedArray::cast(array->elements())->length() == 0);
857 break;
858 }
859 Handle<FixedDoubleArray> elements(
860 FixedDoubleArray::cast(array->elements()));
861 for (int i = 0; i < fast_length; i++) {
862 if (!elements->is_the_hole(i)) element_count++;
863 }
864 break;
865 }
866 case DICTIONARY_ELEMENTS: {
867 Handle<SeededNumberDictionary> dictionary(
868 SeededNumberDictionary::cast(array->elements()));
869 int capacity = dictionary->Capacity();
870 for (int i = 0; i < capacity; i++) {
871 Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
872 if (dictionary->IsKey(*key)) {
873 element_count++;
874 }
875 }
876 break;
877 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
879
880 TYPED_ARRAYS(TYPED_ARRAY_CASE)
881#undef TYPED_ARRAY_CASE
882 // External arrays are always dense.
883 return length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100884 case NO_ELEMENTS:
885 return 0;
886 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
887 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
888 case FAST_STRING_WRAPPER_ELEMENTS:
889 case SLOW_STRING_WRAPPER_ELEMENTS:
890 UNREACHABLE();
891 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 }
893 // As an estimate, we assume that the prototype doesn't contain any
894 // inherited elements.
895 return element_count;
896}
897
898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899// Used for sorting indices in a List<uint32_t>.
900int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
901 uint32_t a = *ap;
902 uint32_t b = *bp;
903 return (a == b) ? 0 : (a < b) ? -1 : 1;
904}
905
906
907void CollectElementIndices(Handle<JSObject> object, uint32_t range,
908 List<uint32_t>* indices) {
909 Isolate* isolate = object->GetIsolate();
910 ElementsKind kind = object->GetElementsKind();
911 switch (kind) {
912 case FAST_SMI_ELEMENTS:
913 case FAST_ELEMENTS:
914 case FAST_HOLEY_SMI_ELEMENTS:
915 case FAST_HOLEY_ELEMENTS: {
916 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
917 uint32_t length = static_cast<uint32_t>(elements->length());
918 if (range < length) length = range;
919 for (uint32_t i = 0; i < length; i++) {
920 if (!elements->get(i)->IsTheHole()) {
921 indices->Add(i);
922 }
923 }
924 break;
925 }
926 case FAST_HOLEY_DOUBLE_ELEMENTS:
927 case FAST_DOUBLE_ELEMENTS: {
928 if (object->elements()->IsFixedArray()) {
929 DCHECK(object->elements()->length() == 0);
930 break;
931 }
932 Handle<FixedDoubleArray> elements(
933 FixedDoubleArray::cast(object->elements()));
934 uint32_t length = static_cast<uint32_t>(elements->length());
935 if (range < length) length = range;
936 for (uint32_t i = 0; i < length; i++) {
937 if (!elements->is_the_hole(i)) {
938 indices->Add(i);
939 }
940 }
941 break;
942 }
943 case DICTIONARY_ELEMENTS: {
944 Handle<SeededNumberDictionary> dict(
945 SeededNumberDictionary::cast(object->elements()));
946 uint32_t capacity = dict->Capacity();
947 for (uint32_t j = 0; j < capacity; j++) {
948 HandleScope loop_scope(isolate);
949 Handle<Object> k(dict->KeyAt(j), isolate);
950 if (dict->IsKey(*k)) {
951 DCHECK(k->IsNumber());
952 uint32_t index = static_cast<uint32_t>(k->Number());
953 if (index < range) {
954 indices->Add(index);
955 }
956 }
957 }
958 break;
959 }
960#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
961
962 TYPED_ARRAYS(TYPED_ARRAY_CASE)
963#undef TYPED_ARRAY_CASE
964 {
965 uint32_t length = static_cast<uint32_t>(
966 FixedArrayBase::cast(object->elements())->length());
967 if (range <= length) {
968 length = range;
969 // We will add all indices, so we might as well clear it first
970 // and avoid duplicates.
971 indices->Clear();
972 }
973 for (uint32_t i = 0; i < length; i++) {
974 indices->Add(i);
975 }
976 if (length == range) return; // All indices accounted for already.
977 break;
978 }
979 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
980 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
981 ElementsAccessor* accessor = object->GetElementsAccessor();
982 for (uint32_t i = 0; i < range; i++) {
983 if (accessor->HasElement(object, i)) {
984 indices->Add(i);
985 }
986 }
987 break;
988 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100989 case FAST_STRING_WRAPPER_ELEMENTS:
990 case SLOW_STRING_WRAPPER_ELEMENTS: {
991 DCHECK(object->IsJSValue());
992 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
993 DCHECK(js_value->value()->IsString());
994 Handle<String> string(String::cast(js_value->value()), isolate);
995 uint32_t length = static_cast<uint32_t>(string->length());
996 uint32_t i = 0;
997 uint32_t limit = Min(length, range);
998 for (; i < limit; i++) {
999 indices->Add(i);
1000 }
1001 ElementsAccessor* accessor = object->GetElementsAccessor();
1002 for (; i < range; i++) {
1003 if (accessor->HasElement(object, i)) {
1004 indices->Add(i);
1005 }
1006 }
1007 break;
1008 }
1009 case NO_ELEMENTS:
1010 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 }
1012
1013 PrototypeIterator iter(isolate, object);
1014 if (!iter.IsAtEnd()) {
1015 // The prototype will usually have no inherited element indices,
1016 // but we have to check.
1017 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
1018 indices);
1019 }
1020}
1021
1022
1023bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
1024 uint32_t length, ArrayConcatVisitor* visitor) {
1025 for (uint32_t i = 0; i < length; ++i) {
1026 HandleScope loop_scope(isolate);
1027 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
1028 if (!maybe.IsJust()) return false;
1029 if (maybe.FromJust()) {
1030 Handle<Object> element_value;
1031 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value,
1032 Object::GetElement(isolate, receiver, i),
1033 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001034 if (!visitor->visit(i, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 }
1036 }
1037 visitor->increase_index_offset(length);
1038 return true;
1039}
1040
1041
1042/**
1043 * A helper function that visits "array" elements of a JSReceiver in numerical
1044 * order.
1045 *
1046 * The visitor argument called for each existing element in the array
1047 * with the element index and the element's value.
1048 * Afterwards it increments the base-index of the visitor by the array
1049 * length.
1050 * Returns false if any access threw an exception, otherwise true.
1051 */
1052bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1053 ArrayConcatVisitor* visitor) {
1054 uint32_t length = 0;
1055
1056 if (receiver->IsJSArray()) {
1057 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
1058 length = static_cast<uint32_t>(array->length()->Number());
1059 } else {
1060 Handle<Object> val;
1061 Handle<Object> key = isolate->factory()->length_string();
1062 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1063 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
1064 false);
1065 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
1066 Object::ToLength(isolate, val), false);
1067 // TODO(caitp): Support larger element indexes (up to 2^53-1).
1068 if (!val->ToUint32(&length)) {
1069 length = 0;
1070 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001071 // TODO(cbruni): handle other element kind as well
1072 return IterateElementsSlow(isolate, receiver, length, visitor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 }
1074
Ben Murdoch097c5b22016-05-18 11:27:45 +01001075 if (!HasOnlySimpleElements(isolate, *receiver)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001076 return IterateElementsSlow(isolate, receiver, length, visitor);
1077 }
1078 Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1079
1080 switch (array->GetElementsKind()) {
1081 case FAST_SMI_ELEMENTS:
1082 case FAST_ELEMENTS:
1083 case FAST_HOLEY_SMI_ELEMENTS:
1084 case FAST_HOLEY_ELEMENTS: {
1085 // Run through the elements FixedArray and use HasElement and GetElement
1086 // to check the prototype for missing elements.
1087 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1088 int fast_length = static_cast<int>(length);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001089 DCHECK_LE(fast_length, elements->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001090 for (int j = 0; j < fast_length; j++) {
1091 HandleScope loop_scope(isolate);
1092 Handle<Object> element_value(elements->get(j), isolate);
1093 if (!element_value->IsTheHole()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001094 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001095 } else {
1096 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1097 if (!maybe.IsJust()) return false;
1098 if (maybe.FromJust()) {
1099 // Call GetElement on array, not its prototype, or getters won't
1100 // have the correct receiver.
1101 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1102 isolate, element_value, Object::GetElement(isolate, array, j),
1103 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001104 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105 }
1106 }
1107 }
1108 break;
1109 }
1110 case FAST_HOLEY_DOUBLE_ELEMENTS:
1111 case FAST_DOUBLE_ELEMENTS: {
1112 // Empty array is FixedArray but not FixedDoubleArray.
1113 if (length == 0) break;
1114 // Run through the elements FixedArray and use HasElement and GetElement
1115 // to check the prototype for missing elements.
1116 if (array->elements()->IsFixedArray()) {
1117 DCHECK(array->elements()->length() == 0);
1118 break;
1119 }
1120 Handle<FixedDoubleArray> elements(
1121 FixedDoubleArray::cast(array->elements()));
1122 int fast_length = static_cast<int>(length);
1123 DCHECK(fast_length <= elements->length());
1124 for (int j = 0; j < fast_length; j++) {
1125 HandleScope loop_scope(isolate);
1126 if (!elements->is_the_hole(j)) {
1127 double double_value = elements->get_scalar(j);
1128 Handle<Object> element_value =
1129 isolate->factory()->NewNumber(double_value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001130 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 } else {
1132 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1133 if (!maybe.IsJust()) return false;
1134 if (maybe.FromJust()) {
1135 // Call GetElement on array, not its prototype, or getters won't
1136 // have the correct receiver.
1137 Handle<Object> element_value;
1138 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1139 isolate, element_value, Object::GetElement(isolate, array, j),
1140 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001141 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142 }
1143 }
1144 }
1145 break;
1146 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001147
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 case DICTIONARY_ELEMENTS: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001149 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1150 List<uint32_t> indices(dict->Capacity() / 2);
1151 // Collect all indices in the object and the prototypes less
1152 // than length. This might introduce duplicates in the indices list.
1153 CollectElementIndices(array, length, &indices);
1154 indices.Sort(&compareUInt32);
1155 int j = 0;
1156 int n = indices.length();
1157 while (j < n) {
1158 HandleScope loop_scope(isolate);
1159 uint32_t index = indices[j];
1160 Handle<Object> element;
1161 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1162 isolate, element, Object::GetElement(isolate, array, index), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001163 if (!visitor->visit(index, element)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 // Skip to next different index (i.e., omit duplicates).
1165 do {
1166 j++;
1167 } while (j < n && indices[j] == index);
1168 }
1169 break;
1170 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1172 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1173 for (uint32_t index = 0; index < length; index++) {
1174 HandleScope loop_scope(isolate);
1175 Handle<Object> element;
1176 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1177 isolate, element, Object::GetElement(isolate, array, index), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001178 if (!visitor->visit(index, element)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 }
1180 break;
1181 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001182 case NO_ELEMENTS:
1183 break;
1184#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1185 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1186#undef TYPED_ARRAY_CASE
1187 return IterateElementsSlow(isolate, receiver, length, visitor);
1188 case FAST_STRING_WRAPPER_ELEMENTS:
1189 case SLOW_STRING_WRAPPER_ELEMENTS:
1190 // |array| is guaranteed to be an array or typed array.
1191 UNREACHABLE();
1192 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001193 }
1194 visitor->increase_index_offset(length);
1195 return true;
1196}
1197
1198
1199bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001200 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1201 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1202 return maybe.FromMaybe(false);
1203}
1204
1205
1206static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1207 HandleScope handle_scope(isolate);
1208 if (!obj->IsJSReceiver()) return Just(false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001209 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1210 Handle<Object> value;
1211 MaybeHandle<Object> maybeValue =
1212 i::Runtime::GetObjectProperty(isolate, obj, key);
1213 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1214 if (!value->IsUndefined()) return Just(value->BooleanValue());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 return Object::IsArray(obj);
1216}
1217
1218
Ben Murdoch097c5b22016-05-18 11:27:45 +01001219Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
1220 Isolate* isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 int argument_count = args->length();
1222
Ben Murdoch097c5b22016-05-18 11:27:45 +01001223 bool is_array_species = *species == isolate->context()->array_function();
1224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001225 // Pass 1: estimate the length and number of elements of the result.
1226 // The actual length can be larger if any of the arguments have getters
1227 // that mutate other arguments (but will otherwise be precise).
1228 // The number of elements is precise if there are no inherited elements.
1229
1230 ElementsKind kind = FAST_SMI_ELEMENTS;
1231
1232 uint32_t estimate_result_length = 0;
1233 uint32_t estimate_nof_elements = 0;
1234 for (int i = 0; i < argument_count; i++) {
1235 HandleScope loop_scope(isolate);
1236 Handle<Object> obj((*args)[i], isolate);
1237 uint32_t length_estimate;
1238 uint32_t element_estimate;
1239 if (obj->IsJSArray()) {
1240 Handle<JSArray> array(Handle<JSArray>::cast(obj));
1241 length_estimate = static_cast<uint32_t>(array->length()->Number());
1242 if (length_estimate != 0) {
1243 ElementsKind array_kind =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001244 GetPackedElementsKind(array->GetElementsKind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 kind = GetMoreGeneralElementsKind(kind, array_kind);
1246 }
1247 element_estimate = EstimateElementCount(array);
1248 } else {
1249 if (obj->IsHeapObject()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001250 kind = GetMoreGeneralElementsKind(
1251 kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001252 }
1253 length_estimate = 1;
1254 element_estimate = 1;
1255 }
1256 // Avoid overflows by capping at kMaxElementCount.
1257 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1258 estimate_result_length = JSObject::kMaxElementCount;
1259 } else {
1260 estimate_result_length += length_estimate;
1261 }
1262 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1263 estimate_nof_elements = JSObject::kMaxElementCount;
1264 } else {
1265 estimate_nof_elements += element_estimate;
1266 }
1267 }
1268
1269 // If estimated number of elements is more than half of length, a
1270 // fixed array (fast case) is more time and space-efficient than a
1271 // dictionary.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001272 bool fast_case =
1273 is_array_species && (estimate_nof_elements * 2) >= estimate_result_length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274
1275 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1276 Handle<FixedArrayBase> storage =
1277 isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1278 int j = 0;
1279 bool failure = false;
1280 if (estimate_result_length > 0) {
1281 Handle<FixedDoubleArray> double_storage =
1282 Handle<FixedDoubleArray>::cast(storage);
1283 for (int i = 0; i < argument_count; i++) {
1284 Handle<Object> obj((*args)[i], isolate);
1285 if (obj->IsSmi()) {
1286 double_storage->set(j, Smi::cast(*obj)->value());
1287 j++;
1288 } else if (obj->IsNumber()) {
1289 double_storage->set(j, obj->Number());
1290 j++;
1291 } else {
1292 JSArray* array = JSArray::cast(*obj);
1293 uint32_t length = static_cast<uint32_t>(array->length()->Number());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001294 switch (array->GetElementsKind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001295 case FAST_HOLEY_DOUBLE_ELEMENTS:
1296 case FAST_DOUBLE_ELEMENTS: {
1297 // Empty array is FixedArray but not FixedDoubleArray.
1298 if (length == 0) break;
1299 FixedDoubleArray* elements =
1300 FixedDoubleArray::cast(array->elements());
1301 for (uint32_t i = 0; i < length; i++) {
1302 if (elements->is_the_hole(i)) {
1303 // TODO(jkummerow/verwaest): We could be a bit more clever
1304 // here: Check if there are no elements/getters on the
1305 // prototype chain, and if so, allow creation of a holey
1306 // result array.
1307 // Same thing below (holey smi case).
1308 failure = true;
1309 break;
1310 }
1311 double double_value = elements->get_scalar(i);
1312 double_storage->set(j, double_value);
1313 j++;
1314 }
1315 break;
1316 }
1317 case FAST_HOLEY_SMI_ELEMENTS:
1318 case FAST_SMI_ELEMENTS: {
1319 FixedArray* elements(FixedArray::cast(array->elements()));
1320 for (uint32_t i = 0; i < length; i++) {
1321 Object* element = elements->get(i);
1322 if (element->IsTheHole()) {
1323 failure = true;
1324 break;
1325 }
1326 int32_t int_value = Smi::cast(element)->value();
1327 double_storage->set(j, int_value);
1328 j++;
1329 }
1330 break;
1331 }
1332 case FAST_HOLEY_ELEMENTS:
1333 case FAST_ELEMENTS:
1334 case DICTIONARY_ELEMENTS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001335 case NO_ELEMENTS:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 DCHECK_EQ(0u, length);
1337 break;
1338 default:
1339 UNREACHABLE();
1340 }
1341 }
1342 if (failure) break;
1343 }
1344 }
1345 if (!failure) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001346 return *isolate->factory()->NewJSArrayWithElements(storage, kind, j);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001347 }
1348 // In case of failure, fall through.
1349 }
1350
Ben Murdoch097c5b22016-05-18 11:27:45 +01001351 Handle<Object> storage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001352 if (fast_case) {
1353 // The backing storage array must have non-existing elements to preserve
1354 // holes across concat operations.
1355 storage =
1356 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001357 } else if (is_array_species) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001358 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1359 uint32_t at_least_space_for =
1360 estimate_nof_elements + (estimate_nof_elements >> 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001361 storage = SeededNumberDictionary::New(isolate, at_least_space_for);
1362 } else {
1363 DCHECK(species->IsConstructor());
1364 Handle<Object> length(Smi::FromInt(0), isolate);
1365 Handle<Object> storage_object;
1366 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1367 isolate, storage_object,
1368 Execution::New(isolate, species, species, 1, &length));
1369 storage = storage_object;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001370 }
1371
1372 ArrayConcatVisitor visitor(isolate, storage, fast_case);
1373
1374 for (int i = 0; i < argument_count; i++) {
1375 Handle<Object> obj((*args)[i], isolate);
1376 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1377 MAYBE_RETURN(spreadable, isolate->heap()->exception());
1378 if (spreadable.FromJust()) {
1379 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1380 if (!IterateElements(isolate, object, &visitor)) {
1381 return isolate->heap()->exception();
1382 }
1383 } else {
1384 visitor.visit(0, obj);
1385 visitor.increase_index_offset(1);
1386 }
1387 }
1388
1389 if (visitor.exceeds_array_limit()) {
1390 THROW_NEW_ERROR_RETURN_FAILURE(
1391 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1392 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001393
1394 if (is_array_species) {
1395 return *visitor.ToArray();
1396 } else {
1397 return *visitor.storage_jsreceiver();
1398 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399}
1400
1401
1402MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001403 int n_arguments = args->length();
Steve Block6ded16b2010-05-10 14:33:55 +01001404 int result_len = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001405 {
1406 DisallowHeapAllocation no_gc;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407 // Iterate through all the arguments performing checks
1408 // and calculating total length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409 for (int i = 0; i < n_arguments; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001410 Object* arg = (*args)[i];
1411 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001412 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
1413 return MaybeHandle<JSArray>();
1414 }
1415 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1416 if (!JSObject::cast(arg)->HasFastElements()) {
1417 return MaybeHandle<JSArray>();
1418 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001419 Handle<JSArray> array(JSArray::cast(arg), isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001420 if (HasConcatSpreadableModifier(isolate, array)) {
1421 return MaybeHandle<JSArray>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001423 int len = Smi::cast(array->length())->value();
Steve Block6ded16b2010-05-10 14:33:55 +01001424
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001425 // We shouldn't overflow when adding another len.
1426 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1427 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1428 USE(kHalfOfMaxInt);
1429 result_len += len;
1430 DCHECK(result_len >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001431 // Throw an Error if we overflow the FixedArray limits
1432 if (FixedArray::kMaxLength < result_len) {
1433 THROW_NEW_ERROR(isolate,
1434 NewRangeError(MessageTemplate::kInvalidArrayLength),
1435 JSArray);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436 }
Steve Block6ded16b2010-05-10 14:33:55 +01001437 }
Steve Block6ded16b2010-05-10 14:33:55 +01001438 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001439 return ElementsAccessor::Concat(isolate, args, n_arguments);
1440}
Steve Block6ded16b2010-05-10 14:33:55 +01001441
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001442} // namespace
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001443
Ben Murdoch097c5b22016-05-18 11:27:45 +01001444
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001445// ES6 22.1.3.1 Array.prototype.concat
1446BUILTIN(ArrayConcat) {
1447 HandleScope scope(isolate);
1448
Ben Murdoch097c5b22016-05-18 11:27:45 +01001449 Handle<Object> receiver = args.receiver();
1450 // TODO(bmeurer): Do we really care about the exact exception message here?
1451 if (receiver->IsNull() || receiver->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452 THROW_NEW_ERROR_RETURN_FAILURE(
1453 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1454 isolate->factory()->NewStringFromAsciiChecked(
1455 "Array.prototype.concat")));
1456 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001457 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1458 isolate, receiver, Object::ToObject(isolate, args.receiver()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001459 args[0] = *receiver;
1460
1461 Handle<JSArray> result_array;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001462
1463 // Reading @@species happens before anything else with a side effect, so
1464 // we can do it here to determine whether to take the fast path.
1465 Handle<Object> species;
1466 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1467 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
1468 if (*species == isolate->context()->native_context()->array_function()) {
1469 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1470 return *result_array;
1471 }
1472 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001473 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001474 return Slow_ArrayConcat(&args, species, isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475}
1476
1477
1478// ES6 22.1.2.2 Array.isArray
1479BUILTIN(ArrayIsArray) {
1480 HandleScope scope(isolate);
1481 DCHECK_EQ(2, args.length());
1482 Handle<Object> object = args.at<Object>(1);
1483 Maybe<bool> result = Object::IsArray(object);
1484 MAYBE_RETURN(result, isolate->heap()->exception());
1485 return *isolate->factory()->ToBoolean(result.FromJust());
1486}
1487
Ben Murdoch097c5b22016-05-18 11:27:45 +01001488namespace {
1489
1490MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
1491 Handle<Object> next_source) {
1492 // Non-empty strings are the only non-JSReceivers that need to be handled
1493 // explicitly by Object.assign.
1494 if (!next_source->IsJSReceiver()) {
1495 return Just(!next_source->IsString() ||
1496 String::cast(*next_source)->length() == 0);
1497 }
1498
1499 Isolate* isolate = to->GetIsolate();
1500 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
1501
1502 if (!map->IsJSObjectMap()) return Just(false);
1503 if (!map->OnlyHasSimpleProperties()) return Just(false);
1504
1505 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
1506 if (from->elements() != isolate->heap()->empty_fixed_array()) {
1507 return Just(false);
1508 }
1509
1510 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
1511 int length = map->NumberOfOwnDescriptors();
1512
1513 bool stable = true;
1514
1515 for (int i = 0; i < length; i++) {
1516 Handle<Name> next_key(descriptors->GetKey(i), isolate);
1517 Handle<Object> prop_value;
1518 // Directly decode from the descriptor array if |from| did not change shape.
1519 if (stable) {
1520 PropertyDetails details = descriptors->GetDetails(i);
1521 if (!details.IsEnumerable()) continue;
1522 if (details.kind() == kData) {
1523 if (details.location() == kDescriptor) {
1524 prop_value = handle(descriptors->GetValue(i), isolate);
1525 } else {
1526 Representation representation = details.representation();
1527 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
1528 prop_value = JSObject::FastPropertyAt(from, representation, index);
1529 }
1530 } else {
1531 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, prop_value,
1532 Object::GetProperty(from, next_key),
1533 Nothing<bool>());
1534 stable = from->map() == *map;
1535 }
1536 } else {
1537 // If the map did change, do a slower lookup. We are still guaranteed that
1538 // the object has a simple shape, and that the key is a name.
1539 LookupIterator it(from, next_key, LookupIterator::OWN_SKIP_INTERCEPTOR);
1540 if (!it.IsFound()) continue;
1541 DCHECK(it.state() == LookupIterator::DATA ||
1542 it.state() == LookupIterator::ACCESSOR);
1543 if (!it.IsEnumerable()) continue;
1544 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1545 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
1546 }
1547 LookupIterator it(to, next_key);
1548 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
1549 Maybe<bool> result = Object::SetProperty(
1550 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
1551 if (result.IsNothing()) return result;
1552 if (stable && call_to_js) stable = from->map() == *map;
1553 }
1554
1555 return Just(true);
1556}
1557
1558} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001559
1560// ES6 19.1.2.1 Object.assign
1561BUILTIN(ObjectAssign) {
1562 HandleScope scope(isolate);
1563 Handle<Object> target = args.atOrUndefined(isolate, 1);
1564
1565 // 1. Let to be ? ToObject(target).
1566 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001567 Object::ToObject(isolate, target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001568 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
1569 // 2. If only one argument was passed, return to.
1570 if (args.length() == 2) return *to;
1571 // 3. Let sources be the List of argument values starting with the
1572 // second argument.
1573 // 4. For each element nextSource of sources, in ascending index order,
1574 for (int i = 2; i < args.length(); ++i) {
1575 Handle<Object> next_source = args.at<Object>(i);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001576 Maybe<bool> fast_assign = FastAssign(to, next_source);
1577 if (fast_assign.IsNothing()) return isolate->heap()->exception();
1578 if (fast_assign.FromJust()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001579 // 4a. If nextSource is undefined or null, let keys be an empty List.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001580 // 4b. Else,
1581 // 4b i. Let from be ToObject(nextSource).
Ben Murdoch097c5b22016-05-18 11:27:45 +01001582 // Only non-empty strings and JSReceivers have enumerable properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 Handle<JSReceiver> from =
1584 Object::ToObject(isolate, next_source).ToHandleChecked();
1585 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
1586 Handle<FixedArray> keys;
1587 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001588 isolate, keys,
1589 JSReceiver::GetKeys(from, OWN_ONLY, ALL_PROPERTIES, KEEP_NUMBERS));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001590 // 4c. Repeat for each element nextKey of keys in List order,
1591 for (int j = 0; j < keys->length(); ++j) {
1592 Handle<Object> next_key(keys->get(j), isolate);
1593 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
1594 PropertyDescriptor desc;
1595 Maybe<bool> found =
1596 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
1597 if (found.IsNothing()) return isolate->heap()->exception();
1598 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
1599 if (found.FromJust() && desc.enumerable()) {
1600 // 4c ii 1. Let propValue be ? Get(from, nextKey).
1601 Handle<Object> prop_value;
1602 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1603 isolate, prop_value,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001604 Runtime::GetObjectProperty(isolate, from, next_key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001605 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
1606 Handle<Object> status;
1607 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1608 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
1609 prop_value, STRICT));
1610 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001611 }
Steve Block6ded16b2010-05-10 14:33:55 +01001612 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613 // 5. Return to.
1614 return *to;
1615}
Steve Block6ded16b2010-05-10 14:33:55 +01001616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
1619BUILTIN(ObjectCreate) {
1620 HandleScope scope(isolate);
1621 Handle<Object> prototype = args.atOrUndefined(isolate, 1);
1622 if (!prototype->IsNull() && !prototype->IsJSReceiver()) {
1623 THROW_NEW_ERROR_RETURN_FAILURE(
1624 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
1625 }
1626
1627 // Generate the map with the specified {prototype} based on the Object
1628 // function's initial map from the current native context.
1629 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1630 // slack tracking for Object.create.
1631 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
1632 isolate);
1633 if (map->prototype() != *prototype) {
1634 map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
1635 }
1636
1637 // Actually allocate the object.
1638 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
1639
1640 // Define the properties if properties was specified and is not undefined.
1641 Handle<Object> properties = args.atOrUndefined(isolate, 2);
1642 if (!properties->IsUndefined()) {
1643 RETURN_FAILURE_ON_EXCEPTION(
1644 isolate, JSReceiver::DefineProperties(isolate, object, properties));
1645 }
1646
1647 return *object;
1648}
1649
1650
1651// ES6 section 19.1.2.5 Object.freeze ( O )
1652BUILTIN(ObjectFreeze) {
1653 HandleScope scope(isolate);
1654 Handle<Object> object = args.atOrUndefined(isolate, 1);
1655 if (object->IsJSReceiver()) {
1656 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1657 FROZEN, Object::THROW_ON_ERROR),
1658 isolate->heap()->exception());
1659 }
1660 return *object;
1661}
1662
1663
Ben Murdoch097c5b22016-05-18 11:27:45 +01001664// ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
1665BUILTIN(ObjectGetOwnPropertyDescriptor) {
1666 HandleScope scope(isolate);
1667 // 1. Let obj be ? ToObject(O).
1668 Handle<Object> object = args.atOrUndefined(isolate, 1);
1669 Handle<JSReceiver> receiver;
1670 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1671 Object::ToObject(isolate, object));
1672 // 2. Let key be ? ToPropertyKey(P).
1673 Handle<Object> property = args.atOrUndefined(isolate, 2);
1674 Handle<Name> key;
1675 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1676 Object::ToName(isolate, property));
1677 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
1678 PropertyDescriptor desc;
1679 Maybe<bool> found =
1680 JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
1681 MAYBE_RETURN(found, isolate->heap()->exception());
1682 // 4. Return FromPropertyDescriptor(desc).
1683 if (!found.FromJust()) return isolate->heap()->undefined_value();
1684 return *desc.ToObject(isolate);
1685}
1686
1687
1688namespace {
1689
1690Object* GetOwnPropertyKeys(Isolate* isolate,
1691 BuiltinArguments<BuiltinExtraArguments::kNone> args,
1692 PropertyFilter filter) {
1693 HandleScope scope(isolate);
1694 Handle<Object> object = args.atOrUndefined(isolate, 1);
1695 Handle<JSReceiver> receiver;
1696 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1697 Object::ToObject(isolate, object));
1698 Handle<FixedArray> keys;
1699 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1700 isolate, keys,
1701 JSReceiver::GetKeys(receiver, OWN_ONLY, filter, CONVERT_TO_STRING));
1702 return *isolate->factory()->NewJSArrayWithElements(keys);
1703}
1704
1705} // namespace
1706
1707
1708// ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
1709BUILTIN(ObjectGetOwnPropertyNames) {
1710 return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
1711}
1712
1713
1714// ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
1715BUILTIN(ObjectGetOwnPropertySymbols) {
1716 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
1717}
1718
1719
1720// ES#sec-object.is Object.is ( value1, value2 )
1721BUILTIN(ObjectIs) {
1722 SealHandleScope shs(isolate);
1723 DCHECK_EQ(3, args.length());
1724 Handle<Object> value1 = args.at<Object>(1);
1725 Handle<Object> value2 = args.at<Object>(2);
1726 return isolate->heap()->ToBoolean(value1->SameValue(*value2));
1727}
1728
1729
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001730// ES6 section 19.1.2.11 Object.isExtensible ( O )
1731BUILTIN(ObjectIsExtensible) {
1732 HandleScope scope(isolate);
1733 Handle<Object> object = args.atOrUndefined(isolate, 1);
1734 Maybe<bool> result =
1735 object->IsJSReceiver()
1736 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
1737 : Just(false);
1738 MAYBE_RETURN(result, isolate->heap()->exception());
1739 return isolate->heap()->ToBoolean(result.FromJust());
1740}
1741
1742
1743// ES6 section 19.1.2.12 Object.isFrozen ( O )
1744BUILTIN(ObjectIsFrozen) {
1745 HandleScope scope(isolate);
1746 Handle<Object> object = args.atOrUndefined(isolate, 1);
1747 Maybe<bool> result = object->IsJSReceiver()
1748 ? JSReceiver::TestIntegrityLevel(
1749 Handle<JSReceiver>::cast(object), FROZEN)
1750 : Just(true);
1751 MAYBE_RETURN(result, isolate->heap()->exception());
1752 return isolate->heap()->ToBoolean(result.FromJust());
1753}
1754
1755
1756// ES6 section 19.1.2.13 Object.isSealed ( O )
1757BUILTIN(ObjectIsSealed) {
1758 HandleScope scope(isolate);
1759 Handle<Object> object = args.atOrUndefined(isolate, 1);
1760 Maybe<bool> result = object->IsJSReceiver()
1761 ? JSReceiver::TestIntegrityLevel(
1762 Handle<JSReceiver>::cast(object), SEALED)
1763 : Just(true);
1764 MAYBE_RETURN(result, isolate->heap()->exception());
1765 return isolate->heap()->ToBoolean(result.FromJust());
1766}
1767
1768
1769// ES6 section 19.1.2.14 Object.keys ( O )
1770BUILTIN(ObjectKeys) {
1771 HandleScope scope(isolate);
1772 Handle<Object> object = args.atOrUndefined(isolate, 1);
1773 Handle<JSReceiver> receiver;
1774 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001775 Object::ToObject(isolate, object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001776
Ben Murdoch097c5b22016-05-18 11:27:45 +01001777 Handle<FixedArray> keys;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001778 int enum_length = receiver->map()->EnumLength();
1779 if (enum_length != kInvalidEnumCacheSentinel &&
1780 JSObject::cast(*receiver)->elements() ==
1781 isolate->heap()->empty_fixed_array()) {
1782 DCHECK(receiver->IsJSObject());
1783 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
1784 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001785 DCHECK(!receiver->map()->has_hidden_prototype());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001786 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
1787 if (enum_length == 0) {
1788 keys = isolate->factory()->empty_fixed_array();
1789 } else {
1790 Handle<FixedArray> cache(
1791 receiver->map()->instance_descriptors()->GetEnumCache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001792 keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001793 }
1794 } else {
1795 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1796 isolate, keys,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001797 JSReceiver::GetKeys(receiver, OWN_ONLY, ENUMERABLE_STRINGS,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001798 CONVERT_TO_STRING));
1799 }
1800 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
1801}
1802
Ben Murdoch097c5b22016-05-18 11:27:45 +01001803BUILTIN(ObjectValues) {
1804 HandleScope scope(isolate);
1805 Handle<Object> object = args.atOrUndefined(isolate, 1);
1806 Handle<JSReceiver> receiver;
1807 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1808 Object::ToObject(isolate, object));
1809 Handle<FixedArray> values;
1810 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1811 isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
1812 return *isolate->factory()->NewJSArrayWithElements(values);
1813}
1814
1815
1816BUILTIN(ObjectEntries) {
1817 HandleScope scope(isolate);
1818 Handle<Object> object = args.atOrUndefined(isolate, 1);
1819 Handle<JSReceiver> receiver;
1820 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1821 Object::ToObject(isolate, object));
1822 Handle<FixedArray> entries;
1823 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1824 isolate, entries,
1825 JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
1826 return *isolate->factory()->NewJSArrayWithElements(entries);
1827}
1828
1829BUILTIN(ObjectGetOwnPropertyDescriptors) {
1830 HandleScope scope(isolate);
1831 Handle<Object> object = args.atOrUndefined(isolate, 1);
1832 Handle<Object> undefined = isolate->factory()->undefined_value();
1833
1834 Handle<JSReceiver> receiver;
1835 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1836 Object::ToObject(isolate, object));
1837
1838 Handle<FixedArray> keys;
1839 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1840 isolate, keys, JSReceiver::GetKeys(receiver, OWN_ONLY, ALL_PROPERTIES,
1841 CONVERT_TO_STRING));
1842
1843 Handle<Object> descriptors =
1844 isolate->factory()->NewJSObject(isolate->object_function());
1845
1846 for (int i = 0; i < keys->length(); ++i) {
1847 Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
1848 PropertyDescriptor descriptor;
1849 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
1850 isolate, receiver, key, &descriptor);
1851 MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
1852
1853 Handle<Object> from_descriptor = did_get_descriptor.FromJust()
1854 ? descriptor.ToObject(isolate)
1855 : undefined;
1856
1857 LookupIterator it = LookupIterator::PropertyOrElement(
1858 isolate, descriptors, key, LookupIterator::OWN);
1859 Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
1860 Object::DONT_THROW);
1861 CHECK(success.FromJust());
1862 }
1863
1864 return *descriptors;
1865}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001866
1867// ES6 section 19.1.2.15 Object.preventExtensions ( O )
1868BUILTIN(ObjectPreventExtensions) {
1869 HandleScope scope(isolate);
1870 Handle<Object> object = args.atOrUndefined(isolate, 1);
1871 if (object->IsJSReceiver()) {
1872 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
1873 Object::THROW_ON_ERROR),
1874 isolate->heap()->exception());
1875 }
1876 return *object;
1877}
1878
1879
1880// ES6 section 19.1.2.17 Object.seal ( O )
1881BUILTIN(ObjectSeal) {
1882 HandleScope scope(isolate);
1883 Handle<Object> object = args.atOrUndefined(isolate, 1);
1884 if (object->IsJSReceiver()) {
1885 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1886 SEALED, Object::THROW_ON_ERROR),
1887 isolate->heap()->exception());
1888 }
1889 return *object;
1890}
1891
1892
1893namespace {
1894
1895bool CodeGenerationFromStringsAllowed(Isolate* isolate,
1896 Handle<Context> context) {
1897 DCHECK(context->allow_code_gen_from_strings()->IsFalse());
1898 // Check with callback if set.
1899 AllowCodeGenerationFromStringsCallback callback =
1900 isolate->allow_code_gen_callback();
1901 if (callback == NULL) {
1902 // No callback set and code generation disallowed.
1903 return false;
1904 } else {
1905 // Callback set. Let it decide if code generation is allowed.
1906 VMState<EXTERNAL> state(isolate);
1907 return callback(v8::Utils::ToLocal(context));
1908 }
1909}
1910
1911
1912MaybeHandle<JSFunction> CompileString(Handle<Context> context,
1913 Handle<String> source,
1914 ParseRestriction restriction) {
1915 Isolate* const isolate = context->GetIsolate();
1916 Handle<Context> native_context(context->native_context(), isolate);
1917
1918 // Check if native context allows code generation from
1919 // strings. Throw an exception if it doesn't.
1920 if (native_context->allow_code_gen_from_strings()->IsFalse() &&
1921 !CodeGenerationFromStringsAllowed(isolate, native_context)) {
1922 Handle<Object> error_message =
1923 native_context->ErrorMessageForCodeGenerationFromStrings();
1924 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1925 error_message),
1926 JSFunction);
1927 }
1928
1929 // Compile source string in the native context.
1930 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared(),
1931 isolate);
1932 return Compiler::GetFunctionFromEval(source, outer_info, native_context,
1933 SLOPPY, restriction,
1934 RelocInfo::kNoPosition);
1935}
1936
1937} // namespace
1938
1939
1940// ES6 section 18.2.1 eval (x)
1941BUILTIN(GlobalEval) {
1942 HandleScope scope(isolate);
1943 Handle<Object> x = args.atOrUndefined(isolate, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001944 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001945 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
1946 if (!x->IsString()) return *x;
1947 Handle<JSFunction> function;
1948 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1949 isolate, function,
1950 CompileString(handle(target->native_context(), isolate),
1951 Handle<String>::cast(x), NO_PARSE_RESTRICTION));
1952 Handle<Object> result;
1953 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1954 isolate, result,
1955 Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
1956 return *result;
1957}
1958
1959
1960// ES6 section 26.1.3 Reflect.defineProperty
1961BUILTIN(ReflectDefineProperty) {
1962 HandleScope scope(isolate);
1963 DCHECK_EQ(4, args.length());
1964 Handle<Object> target = args.at<Object>(1);
1965 Handle<Object> key = args.at<Object>(2);
1966 Handle<Object> attributes = args.at<Object>(3);
1967
1968 if (!target->IsJSReceiver()) {
1969 THROW_NEW_ERROR_RETURN_FAILURE(
1970 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1971 isolate->factory()->NewStringFromAsciiChecked(
1972 "Reflect.defineProperty")));
1973 }
1974
1975 Handle<Name> name;
1976 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1977 Object::ToName(isolate, key));
1978
1979 PropertyDescriptor desc;
1980 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
1981 return isolate->heap()->exception();
1982 }
1983
1984 Maybe<bool> result =
1985 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
1986 name, &desc, Object::DONT_THROW);
1987 MAYBE_RETURN(result, isolate->heap()->exception());
1988 return *isolate->factory()->ToBoolean(result.FromJust());
1989}
1990
1991
1992// ES6 section 26.1.4 Reflect.deleteProperty
1993BUILTIN(ReflectDeleteProperty) {
1994 HandleScope scope(isolate);
1995 DCHECK_EQ(3, args.length());
1996 Handle<Object> target = args.at<Object>(1);
1997 Handle<Object> key = args.at<Object>(2);
1998
1999 if (!target->IsJSReceiver()) {
2000 THROW_NEW_ERROR_RETURN_FAILURE(
2001 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2002 isolate->factory()->NewStringFromAsciiChecked(
2003 "Reflect.deleteProperty")));
2004 }
2005
2006 Handle<Name> name;
2007 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2008 Object::ToName(isolate, key));
2009
2010 Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
2011 Handle<JSReceiver>::cast(target), name, SLOPPY);
2012 MAYBE_RETURN(result, isolate->heap()->exception());
2013 return *isolate->factory()->ToBoolean(result.FromJust());
2014}
2015
2016
2017// ES6 section 26.1.6 Reflect.get
2018BUILTIN(ReflectGet) {
2019 HandleScope scope(isolate);
2020 Handle<Object> target = args.atOrUndefined(isolate, 1);
2021 Handle<Object> key = args.atOrUndefined(isolate, 2);
2022 Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
2023
2024 if (!target->IsJSReceiver()) {
2025 THROW_NEW_ERROR_RETURN_FAILURE(
2026 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2027 isolate->factory()->NewStringFromAsciiChecked(
2028 "Reflect.get")));
2029 }
2030
2031 Handle<Name> name;
2032 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2033 Object::ToName(isolate, key));
2034
2035 Handle<Object> result;
2036 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2037 isolate, result, Object::GetPropertyOrElement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002038 receiver, name, Handle<JSReceiver>::cast(target)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002039
2040 return *result;
2041}
2042
2043
2044// ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
2045BUILTIN(ReflectGetOwnPropertyDescriptor) {
2046 HandleScope scope(isolate);
2047 DCHECK_EQ(3, args.length());
2048 Handle<Object> target = args.at<Object>(1);
2049 Handle<Object> key = args.at<Object>(2);
2050
2051 if (!target->IsJSReceiver()) {
2052 THROW_NEW_ERROR_RETURN_FAILURE(
2053 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2054 isolate->factory()->NewStringFromAsciiChecked(
2055 "Reflect.getOwnPropertyDescriptor")));
2056 }
2057
2058 Handle<Name> name;
2059 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2060 Object::ToName(isolate, key));
2061
2062 PropertyDescriptor desc;
2063 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
2064 isolate, Handle<JSReceiver>::cast(target), name, &desc);
2065 MAYBE_RETURN(found, isolate->heap()->exception());
2066 if (!found.FromJust()) return isolate->heap()->undefined_value();
2067 return *desc.ToObject(isolate);
2068}
2069
2070
2071// ES6 section 26.1.8 Reflect.getPrototypeOf
2072BUILTIN(ReflectGetPrototypeOf) {
2073 HandleScope scope(isolate);
2074 DCHECK_EQ(2, args.length());
2075 Handle<Object> target = args.at<Object>(1);
2076
2077 if (!target->IsJSReceiver()) {
2078 THROW_NEW_ERROR_RETURN_FAILURE(
2079 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2080 isolate->factory()->NewStringFromAsciiChecked(
2081 "Reflect.getPrototypeOf")));
2082 }
2083 Handle<Object> prototype;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002084 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
2085 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2086 isolate, prototype, JSReceiver::GetPrototype(isolate, receiver));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002087 return *prototype;
2088}
2089
2090
2091// ES6 section 26.1.9 Reflect.has
2092BUILTIN(ReflectHas) {
2093 HandleScope scope(isolate);
2094 DCHECK_EQ(3, args.length());
2095 Handle<Object> target = args.at<Object>(1);
2096 Handle<Object> key = args.at<Object>(2);
2097
2098 if (!target->IsJSReceiver()) {
2099 THROW_NEW_ERROR_RETURN_FAILURE(
2100 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2101 isolate->factory()->NewStringFromAsciiChecked(
2102 "Reflect.has")));
2103 }
2104
2105 Handle<Name> name;
2106 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2107 Object::ToName(isolate, key));
2108
2109 Maybe<bool> result =
2110 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
2111 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
2112 : isolate->heap()->exception();
2113}
2114
2115
2116// ES6 section 26.1.10 Reflect.isExtensible
2117BUILTIN(ReflectIsExtensible) {
2118 HandleScope scope(isolate);
2119 DCHECK_EQ(2, args.length());
2120 Handle<Object> target = args.at<Object>(1);
2121
2122 if (!target->IsJSReceiver()) {
2123 THROW_NEW_ERROR_RETURN_FAILURE(
2124 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2125 isolate->factory()->NewStringFromAsciiChecked(
2126 "Reflect.isExtensible")));
2127 }
2128
2129 Maybe<bool> result =
2130 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
2131 MAYBE_RETURN(result, isolate->heap()->exception());
2132 return *isolate->factory()->ToBoolean(result.FromJust());
2133}
2134
2135
2136// ES6 section 26.1.11 Reflect.ownKeys
2137BUILTIN(ReflectOwnKeys) {
2138 HandleScope scope(isolate);
2139 DCHECK_EQ(2, args.length());
2140 Handle<Object> target = args.at<Object>(1);
2141
2142 if (!target->IsJSReceiver()) {
2143 THROW_NEW_ERROR_RETURN_FAILURE(
2144 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2145 isolate->factory()->NewStringFromAsciiChecked(
2146 "Reflect.ownKeys")));
2147 }
2148
2149 Handle<FixedArray> keys;
2150 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002151 isolate, keys,
2152 JSReceiver::GetKeys(Handle<JSReceiver>::cast(target), OWN_ONLY,
2153 ALL_PROPERTIES, CONVERT_TO_STRING));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002154 return *isolate->factory()->NewJSArrayWithElements(keys);
2155}
2156
2157
2158// ES6 section 26.1.12 Reflect.preventExtensions
2159BUILTIN(ReflectPreventExtensions) {
2160 HandleScope scope(isolate);
2161 DCHECK_EQ(2, args.length());
2162 Handle<Object> target = args.at<Object>(1);
2163
2164 if (!target->IsJSReceiver()) {
2165 THROW_NEW_ERROR_RETURN_FAILURE(
2166 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2167 isolate->factory()->NewStringFromAsciiChecked(
2168 "Reflect.preventExtensions")));
2169 }
2170
2171 Maybe<bool> result = JSReceiver::PreventExtensions(
2172 Handle<JSReceiver>::cast(target), Object::DONT_THROW);
2173 MAYBE_RETURN(result, isolate->heap()->exception());
2174 return *isolate->factory()->ToBoolean(result.FromJust());
2175}
2176
2177
2178// ES6 section 26.1.13 Reflect.set
2179BUILTIN(ReflectSet) {
2180 HandleScope scope(isolate);
2181 Handle<Object> target = args.atOrUndefined(isolate, 1);
2182 Handle<Object> key = args.atOrUndefined(isolate, 2);
2183 Handle<Object> value = args.atOrUndefined(isolate, 3);
2184 Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
2185
2186 if (!target->IsJSReceiver()) {
2187 THROW_NEW_ERROR_RETURN_FAILURE(
2188 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2189 isolate->factory()->NewStringFromAsciiChecked(
2190 "Reflect.set")));
2191 }
2192
2193 Handle<Name> name;
2194 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2195 Object::ToName(isolate, key));
2196
2197 LookupIterator it = LookupIterator::PropertyOrElement(
2198 isolate, receiver, name, Handle<JSReceiver>::cast(target));
2199 Maybe<bool> result = Object::SetSuperProperty(
2200 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
2201 MAYBE_RETURN(result, isolate->heap()->exception());
2202 return *isolate->factory()->ToBoolean(result.FromJust());
2203}
2204
2205
2206// ES6 section 26.1.14 Reflect.setPrototypeOf
2207BUILTIN(ReflectSetPrototypeOf) {
2208 HandleScope scope(isolate);
2209 DCHECK_EQ(3, args.length());
2210 Handle<Object> target = args.at<Object>(1);
2211 Handle<Object> proto = args.at<Object>(2);
2212
2213 if (!target->IsJSReceiver()) {
2214 THROW_NEW_ERROR_RETURN_FAILURE(
2215 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2216 isolate->factory()->NewStringFromAsciiChecked(
2217 "Reflect.setPrototypeOf")));
2218 }
2219
2220 if (!proto->IsJSReceiver() && !proto->IsNull()) {
2221 THROW_NEW_ERROR_RETURN_FAILURE(
2222 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2223 }
2224
2225 Maybe<bool> result = JSReceiver::SetPrototype(
2226 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2227 MAYBE_RETURN(result, isolate->heap()->exception());
2228 return *isolate->factory()->ToBoolean(result.FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002229}
2230
2231
Steve Blocka7e24c12009-10-30 11:49:00 +00002232// -----------------------------------------------------------------------------
Ben Murdoch097c5b22016-05-18 11:27:45 +01002233// ES6 section 19.3 Boolean Objects
2234
2235
2236// ES6 section 19.3.1.1 Boolean ( value ) for the [[Call]] case.
2237BUILTIN(BooleanConstructor) {
2238 HandleScope scope(isolate);
2239 Handle<Object> value = args.atOrUndefined(isolate, 1);
2240 return isolate->heap()->ToBoolean(value->BooleanValue());
2241}
2242
2243
2244// ES6 section 19.3.1.1 Boolean ( value ) for the [[Construct]] case.
2245BUILTIN(BooleanConstructor_ConstructStub) {
2246 HandleScope scope(isolate);
2247 Handle<Object> value = args.atOrUndefined(isolate, 1);
2248 Handle<JSFunction> target = args.target<JSFunction>();
2249 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2250 DCHECK(*target == target->native_context()->boolean_function());
2251 Handle<JSObject> result;
2252 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2253 JSObject::New(target, new_target));
2254 Handle<JSValue>::cast(result)->set_value(
2255 isolate->heap()->ToBoolean(value->BooleanValue()));
2256 return *result;
2257}
2258
2259
2260// ES6 section 19.3.3.2 Boolean.prototype.toString ( )
2261BUILTIN(BooleanPrototypeToString) {
2262 HandleScope scope(isolate);
2263 Handle<Object> receiver = args.receiver();
2264 if (receiver->IsJSValue()) {
2265 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
2266 }
2267 if (!receiver->IsBoolean()) {
2268 THROW_NEW_ERROR_RETURN_FAILURE(
2269 isolate, NewTypeError(MessageTemplate::kNotGeneric,
2270 isolate->factory()->NewStringFromAsciiChecked(
2271 "Boolean.prototype.toString")));
2272 }
2273 return Handle<Oddball>::cast(receiver)->to_string();
2274}
2275
2276
2277// ES6 section 19.3.3.3 Boolean.prototype.valueOf ( )
2278BUILTIN(BooleanPrototypeValueOf) {
2279 HandleScope scope(isolate);
2280 Handle<Object> receiver = args.receiver();
2281 if (receiver->IsJSValue()) {
2282 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
2283 }
2284 if (!receiver->IsBoolean()) {
2285 THROW_NEW_ERROR_RETURN_FAILURE(
2286 isolate, NewTypeError(MessageTemplate::kNotGeneric,
2287 isolate->factory()->NewStringFromAsciiChecked(
2288 "Boolean.prototype.valueOf")));
2289 }
2290 return *receiver;
2291}
2292
2293
2294// -----------------------------------------------------------------------------
2295// ES6 section 24.2 DataView Objects
2296
2297
2298// ES6 section 24.2.2 The DataView Constructor for the [[Call]] case.
2299BUILTIN(DataViewConstructor) {
2300 HandleScope scope(isolate);
2301 THROW_NEW_ERROR_RETURN_FAILURE(
2302 isolate,
2303 NewTypeError(MessageTemplate::kConstructorNotFunction,
2304 isolate->factory()->NewStringFromAsciiChecked("DataView")));
2305}
2306
2307
2308// ES6 section 24.2.2 The DataView Constructor for the [[Construct]] case.
2309BUILTIN(DataViewConstructor_ConstructStub) {
2310 HandleScope scope(isolate);
2311 Handle<JSFunction> target = args.target<JSFunction>();
2312 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2313 Handle<Object> buffer = args.atOrUndefined(isolate, 1);
2314 Handle<Object> byte_offset = args.atOrUndefined(isolate, 2);
2315 Handle<Object> byte_length = args.atOrUndefined(isolate, 3);
2316
2317 // 2. If Type(buffer) is not Object, throw a TypeError exception.
2318 // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a
2319 // TypeError exception.
2320 if (!buffer->IsJSArrayBuffer()) {
2321 THROW_NEW_ERROR_RETURN_FAILURE(
2322 isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
2323 }
2324 Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
2325
2326 // 4. Let numberOffset be ? ToNumber(byteOffset).
2327 Handle<Object> number_offset;
2328 if (byte_offset->IsUndefined()) {
2329 // We intentionally violate the specification at this point to allow
2330 // for new DataView(buffer) invocations to be equivalent to the full
2331 // new DataView(buffer, 0) invocation.
2332 number_offset = handle(Smi::FromInt(0), isolate);
2333 } else {
2334 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_offset,
2335 Object::ToNumber(byte_offset));
2336 }
2337
2338 // 5. Let offset be ToInteger(numberOffset).
2339 Handle<Object> offset;
2340 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, offset,
2341 Object::ToInteger(isolate, number_offset));
2342
2343 // 6. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
2344 if (number_offset->Number() != offset->Number() || offset->Number() < 0.0) {
2345 THROW_NEW_ERROR_RETURN_FAILURE(
2346 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2347 }
2348
2349 // 7. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
2350 // We currently violate the specification at this point.
2351
2352 // 8. Let bufferByteLength be the value of buffer's [[ArrayBufferByteLength]]
2353 // internal slot.
2354 double const buffer_byte_length = array_buffer->byte_length()->Number();
2355
2356 // 9. If offset > bufferByteLength, throw a RangeError exception
2357 if (offset->Number() > buffer_byte_length) {
2358 THROW_NEW_ERROR_RETURN_FAILURE(
2359 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2360 }
2361
2362 Handle<Object> view_byte_length;
2363 if (byte_length->IsUndefined()) {
2364 // 10. If byteLength is undefined, then
2365 // a. Let viewByteLength be bufferByteLength - offset.
2366 view_byte_length =
2367 isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
2368 } else {
2369 // 11. Else,
2370 // a. Let viewByteLength be ? ToLength(byteLength).
2371 // b. If offset+viewByteLength > bufferByteLength, throw a RangeError
2372 // exception
2373 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2374 isolate, view_byte_length, Object::ToLength(isolate, byte_length));
2375 if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
2376 THROW_NEW_ERROR_RETURN_FAILURE(
2377 isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
2378 }
2379 }
2380
2381 // 12. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
2382 // "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
2383 // [[ByteLength]], [[ByteOffset]]»).
2384 // 13. Set O's [[DataView]] internal slot to true.
2385 Handle<JSObject> result;
2386 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2387 JSObject::New(target, new_target));
2388 for (int i = 0; i < ArrayBufferView::kInternalFieldCount; ++i) {
2389 Handle<JSDataView>::cast(result)->SetInternalField(i, Smi::FromInt(0));
2390 }
2391
2392 // 14. Set O's [[ViewedArrayBuffer]] internal slot to buffer.
2393 Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
2394
2395 // 15. Set O's [[ByteLength]] internal slot to viewByteLength.
2396 Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
2397
2398 // 16. Set O's [[ByteOffset]] internal slot to offset.
2399 Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
2400
2401 // 17. Return O.
2402 return *result;
2403}
2404
2405
2406// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002407// ES6 section 20.3 Date Objects
Steve Block44f0eee2011-05-26 01:26:41 +01002408
2409
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002410namespace {
2411
2412// ES6 section 20.3.1.1 Time Values and Time Range
2413const double kMinYear = -1000000.0;
2414const double kMaxYear = -kMinYear;
2415const double kMinMonth = -10000000.0;
2416const double kMaxMonth = -kMinMonth;
2417
2418
2419// 20.3.1.2 Day Number and Time within Day
2420const double kMsPerDay = 86400000.0;
2421
2422
2423// ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
2424const double kMsPerSecond = 1000.0;
2425const double kMsPerMinute = 60000.0;
2426const double kMsPerHour = 3600000.0;
2427
2428
2429// ES6 section 20.3.1.14 MakeDate (day, time)
2430double MakeDate(double day, double time) {
2431 if (std::isfinite(day) && std::isfinite(time)) {
2432 return time + day * kMsPerDay;
2433 }
2434 return std::numeric_limits<double>::quiet_NaN();
Steve Block44f0eee2011-05-26 01:26:41 +01002435}
2436
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002438// ES6 section 20.3.1.13 MakeDay (year, month, date)
2439double MakeDay(double year, double month, double date) {
2440 if ((kMinYear <= year && year <= kMaxYear) &&
2441 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
2442 int y = FastD2I(year);
2443 int m = FastD2I(month);
2444 y += m / 12;
2445 m %= 12;
2446 if (m < 0) {
2447 m += 12;
2448 y -= 1;
2449 }
2450 DCHECK_LE(0, m);
2451 DCHECK_LT(m, 12);
2452
2453 // kYearDelta is an arbitrary number such that:
2454 // a) kYearDelta = -1 (mod 400)
2455 // b) year + kYearDelta > 0 for years in the range defined by
2456 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
2457 // Jan 1 1970. This is required so that we don't run into integer
2458 // division of negative numbers.
2459 // c) there shouldn't be an overflow for 32-bit integers in the following
2460 // operations.
2461 static const int kYearDelta = 399999;
2462 static const int kBaseDay =
2463 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
2464 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
2465 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
2466 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
2467 kBaseDay;
2468 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
2469 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151,
2470 181, 212, 243, 273, 304, 334};
2471 day_from_year += kDayFromMonth[m];
2472 } else {
2473 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152,
2474 182, 213, 244, 274, 305, 335};
2475 day_from_year += kDayFromMonth[m];
2476 }
2477 return static_cast<double>(day_from_year - 1) + date;
2478 }
2479 return std::numeric_limits<double>::quiet_NaN();
2480}
2481
2482
2483// ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
2484double MakeTime(double hour, double min, double sec, double ms) {
2485 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
2486 std::isfinite(ms)) {
2487 double const h = DoubleToInteger(hour);
2488 double const m = DoubleToInteger(min);
2489 double const s = DoubleToInteger(sec);
2490 double const milli = DoubleToInteger(ms);
2491 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
2492 }
2493 return std::numeric_limits<double>::quiet_NaN();
2494}
2495
2496
2497// ES6 section 20.3.1.15 TimeClip (time)
2498double TimeClip(double time) {
2499 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
2500 return DoubleToInteger(time) + 0.0;
2501 }
2502 return std::numeric_limits<double>::quiet_NaN();
2503}
2504
2505
2506const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
2507 "Thu", "Fri", "Sat"};
2508const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
2509 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
2510
2511
2512// ES6 section 20.3.1.16 Date Time String Format
2513double ParseDateTimeString(Handle<String> str) {
2514 Isolate* const isolate = str->GetIsolate();
2515 str = String::Flatten(str);
2516 // TODO(bmeurer): Change DateParser to not use the FixedArray.
2517 Handle<FixedArray> tmp =
2518 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
2519 DisallowHeapAllocation no_gc;
2520 String::FlatContent str_content = str->GetFlatContent();
2521 bool result;
2522 if (str_content.IsOneByte()) {
2523 result = DateParser::Parse(str_content.ToOneByteVector(), *tmp,
2524 isolate->unicode_cache());
2525 } else {
2526 result = DateParser::Parse(str_content.ToUC16Vector(), *tmp,
2527 isolate->unicode_cache());
2528 }
2529 if (!result) return std::numeric_limits<double>::quiet_NaN();
2530 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
2531 tmp->get(2)->Number());
2532 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
2533 tmp->get(5)->Number(), tmp->get(6)->Number());
2534 double date = MakeDate(day, time);
2535 if (tmp->get(7)->IsNull()) {
2536 if (!std::isnan(date)) {
2537 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
2538 }
2539 } else {
2540 date -= tmp->get(7)->Number() * 1000.0;
2541 }
2542 return date;
2543}
2544
2545
2546enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
2547
2548
2549// ES6 section 20.3.4.41.1 ToDateString(tv)
2550void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
2551 ToDateStringMode mode = kDateAndTime) {
2552 if (std::isnan(time_val)) {
2553 SNPrintF(str, "Invalid Date");
2554 return;
2555 }
2556 int64_t time_ms = static_cast<int64_t>(time_val);
2557 int64_t local_time_ms = date_cache->ToLocal(time_ms);
2558 int year, month, day, weekday, hour, min, sec, ms;
2559 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
2560 &min, &sec, &ms);
2561 int timezone_offset = -date_cache->TimezoneOffset(time_ms);
2562 int timezone_hour = std::abs(timezone_offset) / 60;
2563 int timezone_min = std::abs(timezone_offset) % 60;
2564 const char* local_timezone = date_cache->LocalTimezone(time_ms);
2565 switch (mode) {
2566 case kDateOnly:
2567 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
2568 kShortMonths[month], day, year);
2569 return;
2570 case kTimeOnly:
2571 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
2572 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
2573 local_timezone);
2574 return;
2575 case kDateAndTime:
2576 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
2577 kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
2578 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
2579 timezone_min, local_timezone);
2580 return;
2581 }
2582 UNREACHABLE();
2583}
2584
2585
2586Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
2587 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2588 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2589 Isolate* const isolate = date->GetIsolate();
2590 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2591 } else {
2592 time_val = std::numeric_limits<double>::quiet_NaN();
2593 }
2594 return *JSDate::SetValue(date, TimeClip(time_val));
2595}
2596
2597} // namespace
2598
2599
2600// ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
2601BUILTIN(DateConstructor) {
2602 HandleScope scope(isolate);
2603 double const time_val = JSDate::CurrentTimeValue(isolate);
2604 char buffer[128];
2605 Vector<char> str(buffer, arraysize(buffer));
2606 ToDateString(time_val, str, isolate->date_cache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002607 Handle<String> result;
2608 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2609 isolate, result,
2610 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
2611 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002612}
2613
2614
2615// ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
2616BUILTIN(DateConstructor_ConstructStub) {
2617 HandleScope scope(isolate);
2618 int const argc = args.length() - 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002619 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002620 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2621 double time_val;
2622 if (argc == 0) {
2623 time_val = JSDate::CurrentTimeValue(isolate);
2624 } else if (argc == 1) {
2625 Handle<Object> value = args.at<Object>(1);
2626 if (value->IsJSDate()) {
2627 time_val = Handle<JSDate>::cast(value)->value()->Number();
2628 } else {
2629 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2630 Object::ToPrimitive(value));
2631 if (value->IsString()) {
2632 time_val = ParseDateTimeString(Handle<String>::cast(value));
2633 } else {
2634 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2635 Object::ToNumber(value));
2636 time_val = value->Number();
2637 }
2638 }
2639 } else {
2640 Handle<Object> year_object;
2641 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2642 Object::ToNumber(args.at<Object>(1)));
2643 Handle<Object> month_object;
2644 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2645 Object::ToNumber(args.at<Object>(2)));
2646 double year = year_object->Number();
2647 double month = month_object->Number();
2648 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2649 if (argc >= 3) {
2650 Handle<Object> date_object;
2651 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
2652 Object::ToNumber(args.at<Object>(3)));
2653 date = date_object->Number();
2654 if (argc >= 4) {
2655 Handle<Object> hours_object;
2656 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2657 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2658 hours = hours_object->Number();
2659 if (argc >= 5) {
2660 Handle<Object> minutes_object;
2661 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2662 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2663 minutes = minutes_object->Number();
2664 if (argc >= 6) {
2665 Handle<Object> seconds_object;
2666 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2667 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
2668 seconds = seconds_object->Number();
2669 if (argc >= 7) {
2670 Handle<Object> ms_object;
2671 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2672 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2673 ms = ms_object->Number();
2674 }
2675 }
2676 }
2677 }
2678 }
2679 if (!std::isnan(year)) {
2680 double const y = DoubleToInteger(year);
2681 if (0.0 <= y && y <= 99) year = 1900 + y;
2682 }
2683 double const day = MakeDay(year, month, date);
2684 double const time = MakeTime(hours, minutes, seconds, ms);
2685 time_val = MakeDate(day, time);
2686 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2687 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2688 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2689 } else {
2690 time_val = std::numeric_limits<double>::quiet_NaN();
2691 }
2692 }
2693 Handle<JSDate> result;
2694 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2695 JSDate::New(target, new_target, time_val));
2696 return *result;
2697}
2698
2699
2700// ES6 section 20.3.3.1 Date.now ( )
2701BUILTIN(DateNow) {
2702 HandleScope scope(isolate);
2703 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
2704}
2705
2706
2707// ES6 section 20.3.3.2 Date.parse ( string )
2708BUILTIN(DateParse) {
2709 HandleScope scope(isolate);
2710 Handle<String> string;
2711 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2712 isolate, string,
2713 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2714 return *isolate->factory()->NewNumber(ParseDateTimeString(string));
2715}
2716
2717
2718// ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
2719BUILTIN(DateUTC) {
2720 HandleScope scope(isolate);
2721 int const argc = args.length() - 1;
2722 double year = std::numeric_limits<double>::quiet_NaN();
2723 double month = std::numeric_limits<double>::quiet_NaN();
2724 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2725 if (argc >= 1) {
2726 Handle<Object> year_object;
2727 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2728 Object::ToNumber(args.at<Object>(1)));
2729 year = year_object->Number();
2730 if (argc >= 2) {
2731 Handle<Object> month_object;
2732 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2733 Object::ToNumber(args.at<Object>(2)));
2734 month = month_object->Number();
2735 if (argc >= 3) {
2736 Handle<Object> date_object;
2737 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2738 isolate, date_object, Object::ToNumber(args.at<Object>(3)));
2739 date = date_object->Number();
2740 if (argc >= 4) {
2741 Handle<Object> hours_object;
2742 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2743 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2744 hours = hours_object->Number();
2745 if (argc >= 5) {
2746 Handle<Object> minutes_object;
2747 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2748 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2749 minutes = minutes_object->Number();
2750 if (argc >= 6) {
2751 Handle<Object> seconds_object;
2752 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2753 isolate, seconds_object,
2754 Object::ToNumber(args.at<Object>(6)));
2755 seconds = seconds_object->Number();
2756 if (argc >= 7) {
2757 Handle<Object> ms_object;
2758 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2759 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2760 ms = ms_object->Number();
2761 }
2762 }
2763 }
2764 }
2765 }
2766 }
2767 }
2768 if (!std::isnan(year)) {
2769 double const y = DoubleToInteger(year);
2770 if (0.0 <= y && y <= 99) year = 1900 + y;
2771 }
2772 double const day = MakeDay(year, month, date);
2773 double const time = MakeTime(hours, minutes, seconds, ms);
2774 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
2775}
2776
2777
2778// ES6 section 20.3.4.20 Date.prototype.setDate ( date )
2779BUILTIN(DatePrototypeSetDate) {
2780 HandleScope scope(isolate);
2781 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
2782 Handle<Object> value = args.atOrUndefined(isolate, 1);
2783 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2784 double time_val = date->value()->Number();
2785 if (!std::isnan(time_val)) {
2786 int64_t const time_ms = static_cast<int64_t>(time_val);
2787 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2788 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2789 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2790 int year, month, day;
2791 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2792 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
2793 }
2794 return SetLocalDateValue(date, time_val);
2795}
2796
2797
2798// ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
2799BUILTIN(DatePrototypeSetFullYear) {
2800 HandleScope scope(isolate);
2801 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
2802 int const argc = args.length() - 1;
2803 Handle<Object> year = args.atOrUndefined(isolate, 1);
2804 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2805 double y = year->Number(), m = 0.0, dt = 1.0;
2806 int time_within_day = 0;
2807 if (!std::isnan(date->value()->Number())) {
2808 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2809 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2810 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2811 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2812 int year, month, day;
2813 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2814 m = month;
2815 dt = day;
2816 }
2817 if (argc >= 2) {
2818 Handle<Object> month = args.at<Object>(2);
2819 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2820 m = month->Number();
2821 if (argc >= 3) {
2822 Handle<Object> date = args.at<Object>(3);
2823 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2824 dt = date->Number();
2825 }
2826 }
2827 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2828 return SetLocalDateValue(date, time_val);
2829}
2830
2831
2832// ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
2833BUILTIN(DatePrototypeSetHours) {
2834 HandleScope scope(isolate);
2835 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
2836 int const argc = args.length() - 1;
2837 Handle<Object> hour = args.atOrUndefined(isolate, 1);
2838 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
2839 double h = hour->Number();
2840 double time_val = date->value()->Number();
2841 if (!std::isnan(time_val)) {
2842 int64_t const time_ms = static_cast<int64_t>(time_val);
2843 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2844 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2845 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2846 double m = (time_within_day / (60 * 1000)) % 60;
2847 double s = (time_within_day / 1000) % 60;
2848 double milli = time_within_day % 1000;
2849 if (argc >= 2) {
2850 Handle<Object> min = args.at<Object>(2);
2851 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2852 m = min->Number();
2853 if (argc >= 3) {
2854 Handle<Object> sec = args.at<Object>(3);
2855 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2856 s = sec->Number();
2857 if (argc >= 4) {
2858 Handle<Object> ms = args.at<Object>(4);
2859 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2860 milli = ms->Number();
2861 }
2862 }
2863 }
2864 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2865 }
2866 return SetLocalDateValue(date, time_val);
2867}
2868
2869
2870// ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
2871BUILTIN(DatePrototypeSetMilliseconds) {
2872 HandleScope scope(isolate);
2873 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
2874 Handle<Object> ms = args.atOrUndefined(isolate, 1);
2875 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2876 double time_val = date->value()->Number();
2877 if (!std::isnan(time_val)) {
2878 int64_t const time_ms = static_cast<int64_t>(time_val);
2879 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2880 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2881 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2882 int h = time_within_day / (60 * 60 * 1000);
2883 int m = (time_within_day / (60 * 1000)) % 60;
2884 int s = (time_within_day / 1000) % 60;
2885 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
2886 }
2887 return SetLocalDateValue(date, time_val);
2888}
2889
2890
2891// ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
2892BUILTIN(DatePrototypeSetMinutes) {
2893 HandleScope scope(isolate);
2894 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
2895 int const argc = args.length() - 1;
2896 Handle<Object> min = args.atOrUndefined(isolate, 1);
2897 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2898 double time_val = date->value()->Number();
2899 if (!std::isnan(time_val)) {
2900 int64_t const time_ms = static_cast<int64_t>(time_val);
2901 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2902 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2903 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2904 int h = time_within_day / (60 * 60 * 1000);
2905 double m = min->Number();
2906 double s = (time_within_day / 1000) % 60;
2907 double milli = time_within_day % 1000;
2908 if (argc >= 2) {
2909 Handle<Object> sec = args.at<Object>(2);
2910 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2911 s = sec->Number();
2912 if (argc >= 3) {
2913 Handle<Object> ms = args.at<Object>(3);
2914 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2915 milli = ms->Number();
2916 }
2917 }
2918 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2919 }
2920 return SetLocalDateValue(date, time_val);
2921}
2922
2923
2924// ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
2925BUILTIN(DatePrototypeSetMonth) {
2926 HandleScope scope(isolate);
2927 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
2928 int const argc = args.length() - 1;
2929 Handle<Object> month = args.atOrUndefined(isolate, 1);
2930 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2931 double time_val = date->value()->Number();
2932 if (!std::isnan(time_val)) {
2933 int64_t const time_ms = static_cast<int64_t>(time_val);
2934 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2935 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
2936 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2937 int year, unused, day;
2938 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
2939 double m = month->Number();
2940 double dt = day;
2941 if (argc >= 2) {
2942 Handle<Object> date = args.at<Object>(2);
2943 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2944 dt = date->Number();
2945 }
2946 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
2947 }
2948 return SetLocalDateValue(date, time_val);
2949}
2950
2951
2952// ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
2953BUILTIN(DatePrototypeSetSeconds) {
2954 HandleScope scope(isolate);
2955 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
2956 int const argc = args.length() - 1;
2957 Handle<Object> sec = args.atOrUndefined(isolate, 1);
2958 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2959 double time_val = date->value()->Number();
2960 if (!std::isnan(time_val)) {
2961 int64_t const time_ms = static_cast<int64_t>(time_val);
2962 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2963 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2964 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2965 int h = time_within_day / (60 * 60 * 1000);
2966 double m = (time_within_day / (60 * 1000)) % 60;
2967 double s = sec->Number();
2968 double milli = time_within_day % 1000;
2969 if (argc >= 2) {
2970 Handle<Object> ms = args.at<Object>(2);
2971 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2972 milli = ms->Number();
2973 }
2974 time_val = MakeDate(day, MakeTime(h, m, s, milli));
2975 }
2976 return SetLocalDateValue(date, time_val);
2977}
2978
2979
2980// ES6 section 20.3.4.27 Date.prototype.setTime ( time )
2981BUILTIN(DatePrototypeSetTime) {
2982 HandleScope scope(isolate);
2983 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
2984 Handle<Object> value = args.atOrUndefined(isolate, 1);
2985 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2986 return *JSDate::SetValue(date, TimeClip(value->Number()));
2987}
2988
2989
2990// ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
2991BUILTIN(DatePrototypeSetUTCDate) {
2992 HandleScope scope(isolate);
2993 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
2994 Handle<Object> value = args.atOrUndefined(isolate, 1);
2995 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2996 if (std::isnan(date->value()->Number())) return date->value();
2997 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2998 int const days = isolate->date_cache()->DaysFromTime(time_ms);
2999 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3000 int year, month, day;
3001 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3002 double const time_val =
3003 MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3004 return *JSDate::SetValue(date, TimeClip(time_val));
3005}
3006
3007
3008// ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
3009BUILTIN(DatePrototypeSetUTCFullYear) {
3010 HandleScope scope(isolate);
3011 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
3012 int const argc = args.length() - 1;
3013 Handle<Object> year = args.atOrUndefined(isolate, 1);
3014 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3015 double y = year->Number(), m = 0.0, dt = 1.0;
3016 int time_within_day = 0;
3017 if (!std::isnan(date->value()->Number())) {
3018 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3019 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3020 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3021 int year, month, day;
3022 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3023 m = month;
3024 dt = day;
3025 }
3026 if (argc >= 2) {
3027 Handle<Object> month = args.at<Object>(2);
3028 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3029 m = month->Number();
3030 if (argc >= 3) {
3031 Handle<Object> date = args.at<Object>(3);
3032 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3033 dt = date->Number();
3034 }
3035 }
3036 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3037 return *JSDate::SetValue(date, TimeClip(time_val));
3038}
3039
3040
3041// ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
3042BUILTIN(DatePrototypeSetUTCHours) {
3043 HandleScope scope(isolate);
3044 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
3045 int const argc = args.length() - 1;
3046 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3047 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3048 double h = hour->Number();
3049 double time_val = date->value()->Number();
3050 if (!std::isnan(time_val)) {
3051 int64_t const time_ms = static_cast<int64_t>(time_val);
3052 int day = isolate->date_cache()->DaysFromTime(time_ms);
3053 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3054 double m = (time_within_day / (60 * 1000)) % 60;
3055 double s = (time_within_day / 1000) % 60;
3056 double milli = time_within_day % 1000;
3057 if (argc >= 2) {
3058 Handle<Object> min = args.at<Object>(2);
3059 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3060 m = min->Number();
3061 if (argc >= 3) {
3062 Handle<Object> sec = args.at<Object>(3);
3063 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3064 s = sec->Number();
3065 if (argc >= 4) {
3066 Handle<Object> ms = args.at<Object>(4);
3067 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3068 milli = ms->Number();
3069 }
3070 }
3071 }
3072 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3073 }
3074 return *JSDate::SetValue(date, TimeClip(time_val));
3075}
3076
3077
3078// ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
3079BUILTIN(DatePrototypeSetUTCMilliseconds) {
3080 HandleScope scope(isolate);
3081 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
3082 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3083 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3084 double time_val = date->value()->Number();
3085 if (!std::isnan(time_val)) {
3086 int64_t const time_ms = static_cast<int64_t>(time_val);
3087 int day = isolate->date_cache()->DaysFromTime(time_ms);
3088 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3089 int h = time_within_day / (60 * 60 * 1000);
3090 int m = (time_within_day / (60 * 1000)) % 60;
3091 int s = (time_within_day / 1000) % 60;
3092 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3093 }
3094 return *JSDate::SetValue(date, TimeClip(time_val));
3095}
3096
3097
3098// ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
3099BUILTIN(DatePrototypeSetUTCMinutes) {
3100 HandleScope scope(isolate);
3101 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
3102 int const argc = args.length() - 1;
3103 Handle<Object> min = args.atOrUndefined(isolate, 1);
3104 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3105 double time_val = date->value()->Number();
3106 if (!std::isnan(time_val)) {
3107 int64_t const time_ms = static_cast<int64_t>(time_val);
3108 int day = isolate->date_cache()->DaysFromTime(time_ms);
3109 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3110 int h = time_within_day / (60 * 60 * 1000);
3111 double m = min->Number();
3112 double s = (time_within_day / 1000) % 60;
3113 double milli = time_within_day % 1000;
3114 if (argc >= 2) {
3115 Handle<Object> sec = args.at<Object>(2);
3116 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3117 s = sec->Number();
3118 if (argc >= 3) {
3119 Handle<Object> ms = args.at<Object>(3);
3120 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3121 milli = ms->Number();
3122 }
3123 }
3124 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3125 }
3126 return *JSDate::SetValue(date, TimeClip(time_val));
3127}
3128
3129
3130// ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
3131BUILTIN(DatePrototypeSetUTCMonth) {
3132 HandleScope scope(isolate);
3133 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
3134 int const argc = args.length() - 1;
3135 Handle<Object> month = args.atOrUndefined(isolate, 1);
3136 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3137 double time_val = date->value()->Number();
3138 if (!std::isnan(time_val)) {
3139 int64_t const time_ms = static_cast<int64_t>(time_val);
3140 int days = isolate->date_cache()->DaysFromTime(time_ms);
3141 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3142 int year, unused, day;
3143 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3144 double m = month->Number();
3145 double dt = day;
3146 if (argc >= 2) {
3147 Handle<Object> date = args.at<Object>(2);
3148 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3149 dt = date->Number();
3150 }
3151 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3152 }
3153 return *JSDate::SetValue(date, TimeClip(time_val));
3154}
3155
3156
3157// ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
3158BUILTIN(DatePrototypeSetUTCSeconds) {
3159 HandleScope scope(isolate);
3160 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
3161 int const argc = args.length() - 1;
3162 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3163 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3164 double time_val = date->value()->Number();
3165 if (!std::isnan(time_val)) {
3166 int64_t const time_ms = static_cast<int64_t>(time_val);
3167 int day = isolate->date_cache()->DaysFromTime(time_ms);
3168 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3169 int h = time_within_day / (60 * 60 * 1000);
3170 double m = (time_within_day / (60 * 1000)) % 60;
3171 double s = sec->Number();
3172 double milli = time_within_day % 1000;
3173 if (argc >= 2) {
3174 Handle<Object> ms = args.at<Object>(2);
3175 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3176 milli = ms->Number();
3177 }
3178 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3179 }
3180 return *JSDate::SetValue(date, TimeClip(time_val));
3181}
3182
3183
3184// ES6 section 20.3.4.35 Date.prototype.toDateString ( )
3185BUILTIN(DatePrototypeToDateString) {
3186 HandleScope scope(isolate);
3187 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
3188 char buffer[128];
3189 Vector<char> str(buffer, arraysize(buffer));
3190 ToDateString(date->value()->Number(), str, isolate->date_cache(), kDateOnly);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003191 Handle<String> result;
3192 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3193 isolate, result,
3194 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3195 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003196}
3197
3198
3199// ES6 section 20.3.4.36 Date.prototype.toISOString ( )
3200BUILTIN(DatePrototypeToISOString) {
3201 HandleScope scope(isolate);
3202 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
3203 double const time_val = date->value()->Number();
3204 if (std::isnan(time_val)) {
3205 THROW_NEW_ERROR_RETURN_FAILURE(
3206 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
3207 }
3208 int64_t const time_ms = static_cast<int64_t>(time_val);
3209 int year, month, day, weekday, hour, min, sec, ms;
3210 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3211 &hour, &min, &sec, &ms);
3212 char buffer[128];
3213 Vector<char> str(buffer, arraysize(buffer));
3214 if (year >= 0 && year <= 9999) {
3215 SNPrintF(str, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
3216 hour, min, sec, ms);
3217 } else if (year < 0) {
3218 SNPrintF(str, "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, month + 1, day,
3219 hour, min, sec, ms);
3220 } else {
3221 SNPrintF(str, "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
3222 hour, min, sec, ms);
3223 }
3224 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
3225}
3226
3227
3228// ES6 section 20.3.4.41 Date.prototype.toString ( )
3229BUILTIN(DatePrototypeToString) {
3230 HandleScope scope(isolate);
3231 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
3232 char buffer[128];
3233 Vector<char> str(buffer, arraysize(buffer));
3234 ToDateString(date->value()->Number(), str, isolate->date_cache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003235 Handle<String> result;
3236 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3237 isolate, result,
3238 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3239 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003240}
3241
3242
3243// ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
3244BUILTIN(DatePrototypeToTimeString) {
3245 HandleScope scope(isolate);
3246 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
3247 char buffer[128];
3248 Vector<char> str(buffer, arraysize(buffer));
3249 ToDateString(date->value()->Number(), str, isolate->date_cache(), kTimeOnly);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003250 Handle<String> result;
3251 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3252 isolate, result,
3253 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3254 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003255}
3256
3257
3258// ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
3259BUILTIN(DatePrototypeToUTCString) {
3260 HandleScope scope(isolate);
3261 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
3262 double const time_val = date->value()->Number();
3263 if (std::isnan(time_val)) {
3264 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
3265 }
3266 char buffer[128];
3267 Vector<char> str(buffer, arraysize(buffer));
3268 int64_t time_ms = static_cast<int64_t>(time_val);
3269 int year, month, day, weekday, hour, min, sec, ms;
3270 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3271 &hour, &min, &sec, &ms);
3272 SNPrintF(str, "%s, %02d %s %4d %02d:%02d:%02d GMT", kShortWeekDays[weekday],
3273 day, kShortMonths[month], year, hour, min, sec);
3274 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
3275}
3276
3277
3278// ES6 section 20.3.4.44 Date.prototype.valueOf ( )
3279BUILTIN(DatePrototypeValueOf) {
3280 HandleScope scope(isolate);
3281 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
3282 return date->value();
3283}
3284
3285
3286// ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
3287BUILTIN(DatePrototypeToPrimitive) {
3288 HandleScope scope(isolate);
3289 DCHECK_EQ(2, args.length());
3290 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
3291 Handle<Object> hint = args.at<Object>(1);
3292 Handle<Object> result;
3293 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3294 JSDate::ToPrimitive(receiver, hint));
3295 return *result;
3296}
3297
3298
3299// ES6 section B.2.4.1 Date.prototype.getYear ( )
3300BUILTIN(DatePrototypeGetYear) {
3301 HandleScope scope(isolate);
3302 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
3303 double time_val = date->value()->Number();
3304 if (std::isnan(time_val)) return date->value();
3305 int64_t time_ms = static_cast<int64_t>(time_val);
3306 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3307 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3308 int year, month, day;
3309 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3310 return Smi::FromInt(year - 1900);
3311}
3312
3313
3314// ES6 section B.2.4.2 Date.prototype.setYear ( year )
3315BUILTIN(DatePrototypeSetYear) {
3316 HandleScope scope(isolate);
3317 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
3318 Handle<Object> year = args.atOrUndefined(isolate, 1);
3319 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3320 double m = 0.0, dt = 1.0, y = year->Number();
3321 if (0.0 <= y && y <= 99.0) {
3322 y = 1900.0 + DoubleToInteger(y);
3323 }
3324 int time_within_day = 0;
3325 if (!std::isnan(date->value()->Number())) {
3326 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3327 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3328 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3329 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3330 int year, month, day;
3331 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3332 m = month;
3333 dt = day;
3334 }
3335 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3336 return SetLocalDateValue(date, time_val);
3337}
3338
3339
3340// static
3341void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
3342 Generate_DatePrototype_GetField(masm, JSDate::kDay);
3343}
3344
3345
3346// static
3347void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
3348 Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
3349}
3350
3351
3352// static
3353void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
3354 Generate_DatePrototype_GetField(masm, JSDate::kYear);
3355}
3356
3357
3358// static
3359void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
3360 Generate_DatePrototype_GetField(masm, JSDate::kHour);
3361}
3362
3363
3364// static
3365void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
3366 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
3367}
3368
3369
3370// static
3371void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
3372 Generate_DatePrototype_GetField(masm, JSDate::kMinute);
3373}
3374
3375
3376// static
3377void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
3378 Generate_DatePrototype_GetField(masm, JSDate::kMonth);
3379}
3380
3381
3382// static
3383void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
3384 Generate_DatePrototype_GetField(masm, JSDate::kSecond);
3385}
3386
3387
3388// static
3389void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
3390 Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
3391}
3392
3393
3394// static
3395void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
3396 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
3397}
3398
3399
3400// static
3401void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
3402 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
3403}
3404
3405
3406// static
3407void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
3408 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
3409}
3410
3411
3412// static
3413void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
3414 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
3415}
3416
3417
3418// static
3419void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
3420 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
3421}
3422
3423
3424// static
3425void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
3426 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
3427}
3428
3429
3430// static
3431void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
3432 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
3433}
3434
3435
3436// static
3437void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
3438 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
3439}
3440
3441
3442// static
3443void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
3444 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
3445}
3446
3447
3448namespace {
3449
3450// ES6 section 19.2.1.1.1 CreateDynamicFunction
3451MaybeHandle<JSFunction> CreateDynamicFunction(
3452 Isolate* isolate,
3453 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,
3454 const char* token) {
3455 // Compute number of arguments, ignoring the receiver.
3456 DCHECK_LE(1, args.length());
3457 int const argc = args.length() - 1;
3458
3459 // Build the source string.
3460 Handle<String> source;
3461 {
3462 IncrementalStringBuilder builder(isolate);
3463 builder.AppendCharacter('(');
3464 builder.AppendCString(token);
3465 builder.AppendCharacter('(');
3466 bool parenthesis_in_arg_string = false;
3467 if (argc > 1) {
3468 for (int i = 1; i < argc; ++i) {
3469 if (i > 1) builder.AppendCharacter(',');
3470 Handle<String> param;
3471 ASSIGN_RETURN_ON_EXCEPTION(
3472 isolate, param, Object::ToString(isolate, args.at<Object>(i)),
3473 JSFunction);
3474 param = String::Flatten(param);
3475 builder.AppendString(param);
3476 // If the formal parameters string include ) - an illegal
3477 // character - it may make the combined function expression
3478 // compile. We avoid this problem by checking for this early on.
3479 DisallowHeapAllocation no_gc; // Ensure vectors stay valid.
3480 String::FlatContent param_content = param->GetFlatContent();
3481 for (int i = 0, length = param->length(); i < length; ++i) {
3482 if (param_content.Get(i) == ')') {
3483 parenthesis_in_arg_string = true;
3484 break;
3485 }
3486 }
3487 }
3488 // If the formal parameters include an unbalanced block comment, the
3489 // function must be rejected. Since JavaScript does not allow nested
3490 // comments we can include a trailing block comment to catch this.
3491 builder.AppendCString("\n/**/");
3492 }
3493 builder.AppendCString(") {\n");
3494 if (argc > 0) {
3495 Handle<String> body;
3496 ASSIGN_RETURN_ON_EXCEPTION(
3497 isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
3498 JSFunction);
3499 builder.AppendString(body);
3500 }
3501 builder.AppendCString("\n})");
3502 ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction);
3503
3504 // The SyntaxError must be thrown after all the (observable) ToString
3505 // conversions are done.
3506 if (parenthesis_in_arg_string) {
3507 THROW_NEW_ERROR(isolate,
3508 NewSyntaxError(MessageTemplate::kParenthesisInArgString),
3509 JSFunction);
3510 }
3511 }
3512
3513 // Compile the string in the constructor and not a helper so that errors to
3514 // come from here.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003515 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003516 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
3517 Handle<JSFunction> function;
3518 {
3519 ASSIGN_RETURN_ON_EXCEPTION(
3520 isolate, function,
3521 CompileString(handle(target->native_context(), isolate), source,
3522 ONLY_SINGLE_FUNCTION_LITERAL),
3523 JSFunction);
3524 Handle<Object> result;
3525 ASSIGN_RETURN_ON_EXCEPTION(
3526 isolate, result,
3527 Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
3528 JSFunction);
3529 function = Handle<JSFunction>::cast(result);
3530 function->shared()->set_name_should_print_as_anonymous(true);
3531 }
3532
3533 // If new.target is equal to target then the function created
3534 // is already correctly setup and nothing else should be done
3535 // here. But if new.target is not equal to target then we are
3536 // have a Function builtin subclassing case and therefore the
3537 // function has wrong initial map. To fix that we create a new
3538 // function object with correct initial map.
3539 Handle<Object> unchecked_new_target = args.new_target();
3540 if (!unchecked_new_target->IsUndefined() &&
3541 !unchecked_new_target.is_identical_to(target)) {
3542 Handle<JSReceiver> new_target =
3543 Handle<JSReceiver>::cast(unchecked_new_target);
3544 Handle<Map> initial_map;
3545 ASSIGN_RETURN_ON_EXCEPTION(
3546 isolate, initial_map,
3547 JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction);
3548
3549 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
3550 Handle<Map> map = Map::AsLanguageMode(
3551 initial_map, shared_info->language_mode(), shared_info->kind());
3552
3553 Handle<Context> context(function->context(), isolate);
3554 function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
3555 map, shared_info, context, NOT_TENURED);
3556 }
3557 return function;
3558}
3559
3560} // namespace
3561
3562
3563// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
3564BUILTIN(FunctionConstructor) {
3565 HandleScope scope(isolate);
3566 Handle<JSFunction> result;
3567 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3568 isolate, result, CreateDynamicFunction(isolate, args, "function"));
3569 return *result;
3570}
3571
3572
3573// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
3574BUILTIN(FunctionPrototypeBind) {
3575 HandleScope scope(isolate);
3576 DCHECK_LE(1, args.length());
3577 if (!args.receiver()->IsCallable()) {
3578 THROW_NEW_ERROR_RETURN_FAILURE(
3579 isolate, NewTypeError(MessageTemplate::kFunctionBind));
3580 }
3581
3582 // Allocate the bound function with the given {this_arg} and {args}.
3583 Handle<JSReceiver> target = args.at<JSReceiver>(0);
3584 Handle<Object> this_arg = isolate->factory()->undefined_value();
3585 ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
3586 if (args.length() > 1) {
3587 this_arg = args.at<Object>(1);
3588 for (int i = 2; i < args.length(); ++i) {
3589 argv[i - 2] = args.at<Object>(i);
3590 }
3591 }
3592 Handle<JSBoundFunction> function;
3593 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3594 isolate, function,
3595 isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
3596
3597 // TODO(bmeurer): Optimize the rest for the common cases where {target} is
3598 // a function with some initial map or even a bound function.
3599 // Setup the "length" property based on the "length" of the {target}.
3600 Handle<Object> length(Smi::FromInt(0), isolate);
3601 Maybe<bool> target_has_length =
3602 JSReceiver::HasOwnProperty(target, isolate->factory()->length_string());
3603 if (!target_has_length.IsJust()) {
3604 return isolate->heap()->exception();
3605 } else if (target_has_length.FromJust()) {
3606 Handle<Object> target_length;
3607 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3608 isolate, target_length,
3609 JSReceiver::GetProperty(target, isolate->factory()->length_string()));
3610 if (target_length->IsNumber()) {
3611 length = isolate->factory()->NewNumber(std::max(
3612 0.0, DoubleToInteger(target_length->Number()) - argv.length()));
3613 }
3614 }
3615 function->set_length(*length);
3616
3617 // Setup the "name" property based on the "name" of the {target}.
3618 Handle<Object> target_name;
3619 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3620 isolate, target_name,
3621 JSReceiver::GetProperty(target, isolate->factory()->name_string()));
3622 Handle<String> name;
3623 if (!target_name->IsString()) {
3624 name = isolate->factory()->bound__string();
3625 } else {
3626 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3627 isolate, name, Name::ToFunctionName(Handle<String>::cast(target_name)));
3628 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3629 isolate, name, isolate->factory()->NewConsString(
3630 isolate->factory()->bound__string(), name));
3631 }
3632 function->set_name(*name);
3633 return *function;
3634}
3635
3636
3637// ES6 section 19.2.3.5 Function.prototype.toString ( )
3638BUILTIN(FunctionPrototypeToString) {
3639 HandleScope scope(isolate);
3640 Handle<Object> receiver = args.receiver();
3641 if (receiver->IsJSBoundFunction()) {
3642 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
3643 } else if (receiver->IsJSFunction()) {
3644 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
3645 }
3646 THROW_NEW_ERROR_RETURN_FAILURE(
3647 isolate, NewTypeError(MessageTemplate::kNotGeneric,
3648 isolate->factory()->NewStringFromAsciiChecked(
3649 "Function.prototype.toString")));
3650}
3651
3652
3653// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
3654BUILTIN(GeneratorFunctionConstructor) {
3655 HandleScope scope(isolate);
3656 Handle<JSFunction> result;
3657 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3658 isolate, result, CreateDynamicFunction(isolate, args, "function*"));
3659 return *result;
3660}
3661
Ben Murdoch097c5b22016-05-18 11:27:45 +01003662// ES6 section 19.2.3.6 Function.prototype[@@hasInstance](V)
3663BUILTIN(FunctionHasInstance) {
3664 HandleScope scope(isolate);
3665 Handle<Object> callable = args.receiver();
3666 Handle<Object> object = args.atOrUndefined(isolate, 1);
3667
3668 // {callable} must have a [[Call]] internal method.
3669 if (!callable->IsCallable()) {
3670 return isolate->heap()->false_value();
3671 }
3672 // If {object} is not a receiver, return false.
3673 if (!object->IsJSReceiver()) {
3674 return isolate->heap()->false_value();
3675 }
3676 // Check if {callable} is bound, if so, get [[BoundTargetFunction]] from it
3677 // and use that instead of {callable}.
3678 while (callable->IsJSBoundFunction()) {
3679 callable =
3680 handle(Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
3681 isolate);
3682 }
3683 DCHECK(callable->IsCallable());
3684 // Get the "prototype" of {callable}; raise an error if it's not a receiver.
3685 Handle<Object> prototype;
3686 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3687 isolate, prototype,
3688 Object::GetProperty(callable, isolate->factory()->prototype_string()));
3689 if (!prototype->IsJSReceiver()) {
3690 THROW_NEW_ERROR_RETURN_FAILURE(
3691 isolate,
3692 NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype));
3693 }
3694 // Return whether or not {prototype} is in the prototype chain of {object}.
3695 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
3696 Maybe<bool> result =
3697 JSReceiver::HasInPrototypeChain(isolate, receiver, prototype);
3698 MAYBE_RETURN(result, isolate->heap()->exception());
3699 return isolate->heap()->ToBoolean(result.FromJust());
3700}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003701
3702// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
3703BUILTIN(SymbolConstructor) {
3704 HandleScope scope(isolate);
3705 Handle<Symbol> result = isolate->factory()->NewSymbol();
3706 Handle<Object> description = args.atOrUndefined(isolate, 1);
3707 if (!description->IsUndefined()) {
3708 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
3709 Object::ToString(isolate, description));
3710 result->set_name(*description);
3711 }
3712 return *result;
3713}
3714
3715
3716// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
3717BUILTIN(SymbolConstructor_ConstructStub) {
3718 HandleScope scope(isolate);
3719 THROW_NEW_ERROR_RETURN_FAILURE(
3720 isolate, NewTypeError(MessageTemplate::kNotConstructor,
3721 isolate->factory()->Symbol_string()));
3722}
3723
3724
3725// ES6 19.1.3.6 Object.prototype.toString
3726BUILTIN(ObjectProtoToString) {
3727 HandleScope scope(isolate);
3728 Handle<Object> object = args.at<Object>(0);
3729 Handle<String> result;
3730 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3731 isolate, result, JSObject::ObjectProtoToString(isolate, object));
3732 return *result;
3733}
3734
3735
3736// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
3737BUILTIN(ArrayBufferConstructor) {
3738 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003739 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003740 DCHECK(*target == target->native_context()->array_buffer_fun() ||
3741 *target == target->native_context()->shared_array_buffer_fun());
3742 THROW_NEW_ERROR_RETURN_FAILURE(
3743 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
3744 handle(target->shared()->name(), isolate)));
3745}
3746
3747
3748// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
3749BUILTIN(ArrayBufferConstructor_ConstructStub) {
3750 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003751 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003752 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3753 Handle<Object> length = args.atOrUndefined(isolate, 1);
3754 DCHECK(*target == target->native_context()->array_buffer_fun() ||
3755 *target == target->native_context()->shared_array_buffer_fun());
3756 Handle<Object> number_length;
3757 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
3758 Object::ToInteger(isolate, length));
3759 if (number_length->Number() < 0.0) {
3760 THROW_NEW_ERROR_RETURN_FAILURE(
3761 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
3762 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01003763 Handle<JSObject> result;
3764 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3765 JSObject::New(target, new_target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003766 size_t byte_length;
3767 if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
3768 THROW_NEW_ERROR_RETURN_FAILURE(
3769 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
3770 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003771 SharedFlag shared_flag =
3772 (*target == target->native_context()->array_buffer_fun())
3773 ? SharedFlag::kNotShared
3774 : SharedFlag::kShared;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003775 if (!JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer>::cast(result),
3776 isolate, byte_length, true,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003777 shared_flag)) {
3778 THROW_NEW_ERROR_RETURN_FAILURE(
3779 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
3780 }
3781 return *result;
3782}
3783
3784
3785// ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
3786BUILTIN(ArrayBufferIsView) {
3787 SealHandleScope shs(isolate);
3788 DCHECK_EQ(2, args.length());
3789 Object* arg = args[1];
3790 return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
3791}
3792
3793
3794// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
3795BUILTIN(ProxyConstructor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003796 HandleScope scope(isolate);
3797 THROW_NEW_ERROR_RETURN_FAILURE(
3798 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003799 NewTypeError(MessageTemplate::kConstructorNotFunction,
3800 isolate->factory()->NewStringFromAsciiChecked("Proxy")));
3801}
3802
3803
3804// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
3805BUILTIN(ProxyConstructor_ConstructStub) {
3806 HandleScope scope(isolate);
3807 DCHECK(isolate->proxy_function()->IsConstructor());
3808 Handle<Object> target = args.atOrUndefined(isolate, 1);
3809 Handle<Object> handler = args.atOrUndefined(isolate, 2);
3810 Handle<JSProxy> result;
3811 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3812 JSProxy::New(isolate, target, handler));
3813 return *result;
3814}
3815
3816
3817// -----------------------------------------------------------------------------
3818// Throwers for restricted function properties and strict arguments object
3819// properties
3820
3821
3822BUILTIN(RestrictedFunctionPropertiesThrower) {
3823 HandleScope scope(isolate);
3824 THROW_NEW_ERROR_RETURN_FAILURE(
3825 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
3826}
3827
3828
3829BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
3830 HandleScope scope(isolate);
3831 THROW_NEW_ERROR_RETURN_FAILURE(
3832 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003833}
3834
3835
Steve Block44f0eee2011-05-26 01:26:41 +01003836// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00003837//
3838
3839
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003840namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +00003841
Leon Clarkee46be812010-01-19 14:06:41 +00003842template <bool is_construct>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003843MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
3844 Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
Steve Block44f0eee2011-05-26 01:26:41 +01003845 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003846 Handle<HeapObject> function = args.target<HeapObject>();
3847 Handle<JSReceiver> receiver;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003848 // TODO(ishell): turn this back to a DCHECK.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003849 CHECK(function->IsFunctionTemplateInfo() ||
3850 Handle<JSFunction>::cast(function)->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00003851
Ben Murdoch097c5b22016-05-18 11:27:45 +01003852 Handle<FunctionTemplateInfo> fun_data =
3853 function->IsFunctionTemplateInfo()
3854 ? Handle<FunctionTemplateInfo>::cast(function)
3855 : handle(JSFunction::cast(*function)->shared()->get_api_func_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00003856 if (is_construct) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01003857 DCHECK(args.receiver()->IsTheHole());
3858 if (fun_data->instance_template()->IsUndefined()) {
3859 v8::Local<ObjectTemplate> templ =
3860 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
3861 ToApiHandle<v8::FunctionTemplate>(fun_data));
3862 fun_data->set_instance_template(*Utils::OpenHandle(*templ));
3863 }
3864 Handle<ObjectTemplateInfo> instance_template(
3865 ObjectTemplateInfo::cast(fun_data->instance_template()), isolate);
3866 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
3867 ApiNatives::InstantiateObject(instance_template),
3868 Object);
3869 args[0] = *receiver;
3870 DCHECK_EQ(*receiver, *args.receiver());
3871 } else {
3872 DCHECK(args.receiver()->IsJSReceiver());
3873 receiver = args.at<JSReceiver>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00003874 }
3875
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003876 if (!is_construct && !fun_data->accept_any_receiver()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003877 if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
3878 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
3879 if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
3880 isolate->ReportFailedAccessCheck(js_receiver);
3881 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3882 }
3883 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003884 }
3885
Ben Murdoch097c5b22016-05-18 11:27:45 +01003886 Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, *receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00003887
3888 if (raw_holder->IsNull()) {
3889 // This function cannot be called with the given receiver. Abort!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003890 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
3891 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +00003892 }
3893
3894 Object* raw_call_data = fun_data->call_code();
3895 if (!raw_call_data->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003896 // TODO(ishell): remove this debugging code.
3897 CHECK(raw_call_data->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00003898 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
3899 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003900 v8::FunctionCallback callback =
3901 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003902 Object* data_obj = call_data->data();
Steve Blocka7e24c12009-10-30 11:49:00 +00003903
Steve Block44f0eee2011-05-26 01:26:41 +01003904 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003905 DCHECK(raw_holder->IsJSObject());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003906
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003907 FunctionCallbackArguments custom(isolate,
3908 data_obj,
3909 *function,
3910 raw_holder,
3911 &args[0] - 1,
3912 args.length() - 1,
3913 is_construct);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08003914
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003915 v8::Local<v8::Value> value = custom.Call(callback);
3916 Handle<Object> result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003917 if (value.IsEmpty()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003918 result = isolate->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003919 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003920 result = v8::Utils::OpenHandle(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003921 result->VerifyApiCallResultType();
Steve Blocka7e24c12009-10-30 11:49:00 +00003922 }
3923
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003924 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3925 if (!is_construct || result->IsJSObject()) {
3926 return scope.CloseAndEscape(result);
3927 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003928 }
3929
Ben Murdoch097c5b22016-05-18 11:27:45 +01003930 return scope.CloseAndEscape(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00003931}
Leon Clarkee46be812010-01-19 14:06:41 +00003932
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003933} // namespace
3934
Leon Clarkee46be812010-01-19 14:06:41 +00003935
3936BUILTIN(HandleApiCall) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003937 HandleScope scope(isolate);
3938 Handle<Object> result;
3939 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3940 HandleApiCallHelper<false>(isolate, args));
3941 return *result;
Leon Clarkee46be812010-01-19 14:06:41 +00003942}
3943
3944
3945BUILTIN(HandleApiCallConstruct) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003946 HandleScope scope(isolate);
3947 Handle<Object> result;
3948 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3949 HandleApiCallHelper<true>(isolate, args));
3950 return *result;
3951}
3952
Ben Murdoch097c5b22016-05-18 11:27:45 +01003953Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode,
3954 TailCallMode tail_call_mode) {
3955 switch (tail_call_mode) {
3956 case TailCallMode::kDisallow:
3957 switch (mode) {
3958 case ConvertReceiverMode::kNullOrUndefined:
3959 return CallFunction_ReceiverIsNullOrUndefined();
3960 case ConvertReceiverMode::kNotNullOrUndefined:
3961 return CallFunction_ReceiverIsNotNullOrUndefined();
3962 case ConvertReceiverMode::kAny:
3963 return CallFunction_ReceiverIsAny();
3964 }
3965 break;
3966 case TailCallMode::kAllow:
3967 switch (mode) {
3968 case ConvertReceiverMode::kNullOrUndefined:
3969 return TailCallFunction_ReceiverIsNullOrUndefined();
3970 case ConvertReceiverMode::kNotNullOrUndefined:
3971 return TailCallFunction_ReceiverIsNotNullOrUndefined();
3972 case ConvertReceiverMode::kAny:
3973 return TailCallFunction_ReceiverIsAny();
3974 }
3975 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003976 }
3977 UNREACHABLE();
3978 return Handle<Code>::null();
3979}
3980
Ben Murdoch097c5b22016-05-18 11:27:45 +01003981Handle<Code> Builtins::Call(ConvertReceiverMode mode,
3982 TailCallMode tail_call_mode) {
3983 switch (tail_call_mode) {
3984 case TailCallMode::kDisallow:
3985 switch (mode) {
3986 case ConvertReceiverMode::kNullOrUndefined:
3987 return Call_ReceiverIsNullOrUndefined();
3988 case ConvertReceiverMode::kNotNullOrUndefined:
3989 return Call_ReceiverIsNotNullOrUndefined();
3990 case ConvertReceiverMode::kAny:
3991 return Call_ReceiverIsAny();
3992 }
3993 break;
3994 case TailCallMode::kAllow:
3995 switch (mode) {
3996 case ConvertReceiverMode::kNullOrUndefined:
3997 return TailCall_ReceiverIsNullOrUndefined();
3998 case ConvertReceiverMode::kNotNullOrUndefined:
3999 return TailCall_ReceiverIsNotNullOrUndefined();
4000 case ConvertReceiverMode::kAny:
4001 return TailCall_ReceiverIsAny();
4002 }
4003 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004004 }
4005 UNREACHABLE();
4006 return Handle<Code>::null();
4007}
4008
Ben Murdoch097c5b22016-05-18 11:27:45 +01004009Handle<Code> Builtins::CallBoundFunction(TailCallMode tail_call_mode) {
4010 switch (tail_call_mode) {
4011 case TailCallMode::kDisallow:
4012 return CallBoundFunction();
4013 case TailCallMode::kAllow:
4014 return TailCallBoundFunction();
4015 }
4016 UNREACHABLE();
4017 return Handle<Code>::null();
4018}
4019
4020Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode) {
4021 switch (tail_call_mode) {
4022 case TailCallMode::kDisallow:
4023 return InterpreterPushArgsAndCall();
4024 case TailCallMode::kAllow:
4025 return InterpreterPushArgsAndTailCall();
4026 }
4027 UNREACHABLE();
4028 return Handle<Code>::null();
4029}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004030
4031namespace {
4032
4033class RelocatableArguments
4034 : public BuiltinArguments<BuiltinExtraArguments::kTarget>,
4035 public Relocatable {
4036 public:
4037 RelocatableArguments(Isolate* isolate, int length, Object** arguments)
4038 : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
4039 Relocatable(isolate) {}
4040
4041 virtual inline void IterateInstance(ObjectVisitor* v) {
4042 if (length() == 0) return;
4043 v->VisitPointers(lowest_address(), highest_address() + 1);
4044 }
4045
4046 private:
4047 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
4048};
4049
4050} // namespace
4051
Ben Murdoch097c5b22016-05-18 11:27:45 +01004052MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004053 Handle<Object> receiver,
4054 int argc,
4055 Handle<Object> args[]) {
4056 // Construct BuiltinArguments object: function, arguments reversed, receiver.
4057 const int kBufferSize = 32;
4058 Object* small_argv[kBufferSize];
4059 Object** argv;
4060 if (argc + 2 <= kBufferSize) {
4061 argv = small_argv;
4062 } else {
4063 argv = new Object* [argc + 2];
4064 }
4065 argv[argc + 1] = *receiver;
4066 for (int i = 0; i < argc; ++i) {
4067 argv[argc - i] = *args[i];
4068 }
4069 argv[0] = *function;
4070 MaybeHandle<Object> result;
4071 {
4072 auto isolate = function->GetIsolate();
4073 RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
4074 result = HandleApiCallHelper<false>(isolate, arguments);
4075 }
4076 if (argv != small_argv) {
4077 delete[] argv;
4078 }
4079 return result;
Leon Clarkee46be812010-01-19 14:06:41 +00004080}
Steve Blocka7e24c12009-10-30 11:49:00 +00004081
4082
4083// Helper function to handle calls to non-function objects created through the
4084// API. The object can be called as either a constructor (using new) or just as
4085// a function (without new).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004086MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004087 Isolate* isolate, bool is_construct_call,
4088 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Steve Block44f0eee2011-05-26 01:26:41 +01004089 Heap* heap = isolate->heap();
Steve Blocka7e24c12009-10-30 11:49:00 +00004090
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004091 Handle<Object> receiver = args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00004092
4093 // Get the object called.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004094 JSObject* obj = JSObject::cast(*receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00004095
4096 // Get the invocation callback from the function descriptor that was
4097 // used to create the called object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004098 DCHECK(obj->map()->is_callable());
4099 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
4100 // TODO(ishell): turn this back to a DCHECK.
4101 CHECK(constructor->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00004102 Object* handler =
Steve Block6ded16b2010-05-10 14:33:55 +01004103 constructor->shared()->get_api_func_data()->instance_call_handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004104 DCHECK(!handler->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004105 // TODO(ishell): remove this debugging code.
4106 CHECK(handler->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00004107 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
4108 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004109 v8::FunctionCallback callback =
4110 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00004111
4112 // Get the data for the call and perform the callback.
Steve Blocka7e24c12009-10-30 11:49:00 +00004113 Object* result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004114 {
Steve Block44f0eee2011-05-26 01:26:41 +01004115 HandleScope scope(isolate);
4116 LOG(isolate, ApiObjectAccess("call non-function", obj));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004117
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004118 FunctionCallbackArguments custom(isolate,
4119 call_data->data(),
4120 constructor,
4121 obj,
4122 &args[0] - 1,
4123 args.length() - 1,
4124 is_construct_call);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004125 v8::Local<v8::Value> value = custom.Call(callback);
Steve Blocka7e24c12009-10-30 11:49:00 +00004126 if (value.IsEmpty()) {
Steve Block44f0eee2011-05-26 01:26:41 +01004127 result = heap->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00004128 } else {
4129 result = *reinterpret_cast<Object**>(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004130 result->VerifyApiCallResultType();
Steve Blocka7e24c12009-10-30 11:49:00 +00004131 }
4132 }
4133 // Check for exceptions and return result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004134 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004135 return result;
4136}
4137
4138
4139// Handle calls to non-function objects created through the API. This delegate
4140// function is used when the call is a normal function call.
4141BUILTIN(HandleApiCallAsFunction) {
Steve Block44f0eee2011-05-26 01:26:41 +01004142 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004143}
Steve Blocka7e24c12009-10-30 11:49:00 +00004144
4145
4146// Handle calls to non-function objects created through the API. This delegate
4147// function is used when the call is a construct call.
4148BUILTIN(HandleApiCallAsConstructor) {
Steve Block44f0eee2011-05-26 01:26:41 +01004149 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004150}
Steve Blocka7e24c12009-10-30 11:49:00 +00004151
4152
Steve Blocka7e24c12009-10-30 11:49:00 +00004153static void Generate_LoadIC_Miss(MacroAssembler* masm) {
4154 LoadIC::GenerateMiss(masm);
4155}
4156
4157
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004158static void Generate_LoadIC_Normal(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004159 LoadIC::GenerateNormal(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004160}
4161
4162
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004163static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
4164 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
4165}
4166
4167
4168static void Generate_LoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004169 LoadIC::GenerateRuntimeGetProperty(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004170}
4171
4172
Ben Murdoch257744e2011-11-30 15:57:28 +00004173static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004174 KeyedLoadIC::GenerateRuntimeGetProperty(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00004175}
4176
4177
Steve Blocka7e24c12009-10-30 11:49:00 +00004178static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004179 KeyedLoadIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004180}
4181
4182
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004183static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004184 KeyedLoadIC::GenerateMegamorphic(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004185}
4186
Steve Block1e0659c2011-05-24 12:43:12 +01004187
Steve Blocka7e24c12009-10-30 11:49:00 +00004188static void Generate_StoreIC_Miss(MacroAssembler* masm) {
4189 StoreIC::GenerateMiss(masm);
4190}
4191
4192
Steve Block8defd9f2010-07-08 12:39:36 +01004193static void Generate_StoreIC_Normal(MacroAssembler* masm) {
4194 StoreIC::GenerateNormal(masm);
4195}
4196
4197
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004198static void Generate_StoreIC_Slow(MacroAssembler* masm) {
4199 NamedStoreHandlerCompiler::GenerateSlow(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00004200}
4201
4202
4203static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004204 ElementHandlerCompiler::GenerateStoreSlow(masm);
4205}
4206
4207
4208static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
4209 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
4210}
4211
4212
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004213static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
4214 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
4215}
4216
4217
4218static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
4219 KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
4220}
4221
4222
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004223static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
4224 KeyedStoreIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004225}
4226
4227
4228static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
4229 KeyedStoreIC::GenerateInitialize(masm);
4230}
4231
4232
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004233static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
4234 KeyedStoreIC::GenerateInitialize(masm);
4235}
4236
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004237
4238static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
4239 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004240}
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004241
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004242
4243static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
4244 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004245}
4246
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004247
Steve Blocka7e24c12009-10-30 11:49:00 +00004248static void Generate_Return_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004249 DebugCodegen::GenerateDebugBreakStub(masm,
4250 DebugCodegen::SAVE_RESULT_REGISTER);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01004251}
4252
4253
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004254static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004255 DebugCodegen::GenerateDebugBreakStub(masm,
4256 DebugCodegen::IGNORE_RESULT_REGISTER);
Steve Block6ded16b2010-05-10 14:33:55 +01004257}
4258
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004259
Steve Block6ded16b2010-05-10 14:33:55 +01004260static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004261 DebugCodegen::GenerateFrameDropperLiveEdit(masm);
Steve Block6ded16b2010-05-10 14:33:55 +01004262}
Steve Blocka7e24c12009-10-30 11:49:00 +00004263
Steve Block44f0eee2011-05-26 01:26:41 +01004264
4265Builtins::Builtins() : initialized_(false) {
4266 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
4267 memset(names_, 0, sizeof(names_[0]) * builtin_count);
4268}
4269
4270
4271Builtins::~Builtins() {
4272}
4273
Steve Blocka7e24c12009-10-30 11:49:00 +00004274
Leon Clarkee46be812010-01-19 14:06:41 +00004275#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
Steve Block44f0eee2011-05-26 01:26:41 +01004276Address const Builtins::c_functions_[cfunction_count] = {
4277 BUILTIN_LIST_C(DEF_ENUM_C)
4278};
Steve Blocka7e24c12009-10-30 11:49:00 +00004279#undef DEF_ENUM_C
4280
Steve Blocka7e24c12009-10-30 11:49:00 +00004281
Steve Block44f0eee2011-05-26 01:26:41 +01004282struct BuiltinDesc {
4283 byte* generator;
4284 byte* c_code;
4285 const char* s_name; // name is only used for generating log information.
4286 int name;
4287 Code::Flags flags;
4288 BuiltinExtraArguments extra_args;
4289};
4290
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004291#define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
4292
Steve Block44f0eee2011-05-26 01:26:41 +01004293class BuiltinFunctionTable {
4294 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004295 BuiltinDesc* functions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004296 base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004297 return functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01004298 }
4299
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004300 base::OnceType once_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004301 BuiltinDesc functions_[Builtins::builtin_count + 1];
Steve Block44f0eee2011-05-26 01:26:41 +01004302
4303 friend class Builtins;
4304};
4305
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004306static BuiltinFunctionTable builtin_function_table =
4307 BUILTIN_FUNCTION_TABLE_INIT;
Steve Block44f0eee2011-05-26 01:26:41 +01004308
4309// Define array of pointers to generators and C builtin functions.
4310// We do this in a sort of roundabout way so that we can do the initialization
4311// within the lexical scope of Builtins:: and within a context where
4312// Code::Flags names a non-abstract type.
4313void Builtins::InitBuiltinFunctionTable() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004314 BuiltinDesc* functions = builtin_function_table.functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01004315 functions[builtin_count].generator = NULL;
4316 functions[builtin_count].c_code = NULL;
4317 functions[builtin_count].s_name = NULL;
4318 functions[builtin_count].name = builtin_count;
4319 functions[builtin_count].flags = static_cast<Code::Flags>(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004320 functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
Steve Block44f0eee2011-05-26 01:26:41 +01004321
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004322#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
4323 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
4324 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
4325 functions->s_name = #aname; \
4326 functions->name = c_##aname; \
4327 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
4328 functions->extra_args = BuiltinExtraArguments::aextra_args; \
4329 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01004330
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004331#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
4332 functions->generator = FUNCTION_ADDR(Generate_##aname); \
4333 functions->c_code = NULL; \
4334 functions->s_name = #aname; \
4335 functions->name = k##aname; \
4336 functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
4337 functions->extra_args = BuiltinExtraArguments::kNone; \
4338 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01004339
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004340#define DEF_FUNCTION_PTR_H(aname, kind) \
4341 functions->generator = FUNCTION_ADDR(Generate_##aname); \
4342 functions->c_code = NULL; \
4343 functions->s_name = #aname; \
4344 functions->name = k##aname; \
4345 functions->flags = Code::ComputeHandlerFlags(Code::kind); \
4346 functions->extra_args = BuiltinExtraArguments::kNone; \
4347 ++functions;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004348
Steve Block44f0eee2011-05-26 01:26:41 +01004349 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
4350 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004351 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01004352 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
4353
4354#undef DEF_FUNCTION_PTR_C
4355#undef DEF_FUNCTION_PTR_A
4356}
4357
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004358
4359void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
4360 DCHECK(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +00004361
4362 // Create a scope for the handles in the builtins.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004363 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004364
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004365 const BuiltinDesc* functions = builtin_function_table.functions();
Steve Blocka7e24c12009-10-30 11:49:00 +00004366
4367 // For now we generate builtin adaptor code into a stack-allocated
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004368 // buffer, before copying it into individual code objects. Be careful
4369 // with alignment, some platforms don't like unaligned code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004370#ifdef DEBUG
4371 // We can generate a lot of debug code on Arm64.
4372 const size_t buffer_size = 32*KB;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004373#elif V8_TARGET_ARCH_PPC64
4374 // 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
4375 const size_t buffer_size = 10 * KB;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004376#else
4377 const size_t buffer_size = 8*KB;
4378#endif
4379 union { int force_alignment; byte buffer[buffer_size]; } u;
Steve Blocka7e24c12009-10-30 11:49:00 +00004380
4381 // Traverse the list of builtins and generate an adaptor in a
4382 // separate code object for each one.
4383 for (int i = 0; i < builtin_count; i++) {
4384 if (create_heap_objects) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004385 MacroAssembler masm(isolate, u.buffer, sizeof u.buffer,
4386 CodeObjectRequired::kYes);
Steve Blocka7e24c12009-10-30 11:49:00 +00004387 // Generate the code/adaptor.
Leon Clarkee46be812010-01-19 14:06:41 +00004388 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00004389 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
4390 // We pass all arguments to the generator, but it may not use all of
4391 // them. This works because the first arguments are on top of the
4392 // stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004393 DCHECK(!masm.has_frame());
Leon Clarkee46be812010-01-19 14:06:41 +00004394 g(&masm, functions[i].name, functions[i].extra_args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004395 // Move the code into the object heap.
4396 CodeDesc desc;
4397 masm.GetCode(&desc);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004398 Code::Flags flags = functions[i].flags;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004399 Handle<Code> code =
4400 isolate->factory()->NewCode(desc, flags, masm.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00004401 // Log the event and add the code to the builtins array.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004402 PROFILE(isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004403 CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
4404 builtins_[i] = *code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004405 code->set_builtin_index(i);
Steve Blocka7e24c12009-10-30 11:49:00 +00004406#ifdef ENABLE_DISASSEMBLER
4407 if (FLAG_print_builtin_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004408 CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
4409 OFStream os(trace_scope.file());
4410 os << "Builtin: " << functions[i].s_name << "\n";
4411 code->Disassemble(functions[i].s_name, os);
4412 os << "\n";
Steve Blocka7e24c12009-10-30 11:49:00 +00004413 }
4414#endif
4415 } else {
4416 // Deserializing. The values will be filled in during IterateBuiltins.
4417 builtins_[i] = NULL;
4418 }
4419 names_[i] = functions[i].s_name;
4420 }
4421
4422 // Mark as initialized.
Steve Block44f0eee2011-05-26 01:26:41 +01004423 initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00004424}
4425
4426
4427void Builtins::TearDown() {
Steve Block44f0eee2011-05-26 01:26:41 +01004428 initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00004429}
4430
4431
4432void Builtins::IterateBuiltins(ObjectVisitor* v) {
4433 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
4434}
4435
4436
4437const char* Builtins::Lookup(byte* pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01004438 // may be called during initialization (disassembler!)
4439 if (initialized_) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004440 for (int i = 0; i < builtin_count; i++) {
4441 Code* entry = Code::cast(builtins_[i]);
4442 if (entry->contains(pc)) {
4443 return names_[i];
4444 }
4445 }
4446 }
4447 return NULL;
4448}
4449
Ben Murdochb0fe1622011-05-05 13:52:32 +01004450
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004451void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004452 masm->TailCallRuntime(Runtime::kInterrupt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004453}
4454
4455
4456void Builtins::Generate_StackCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004457 masm->TailCallRuntime(Runtime::kStackGuard);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004458}
4459
4460
Steve Block44f0eee2011-05-26 01:26:41 +01004461#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
4462Handle<Code> Builtins::name() { \
4463 Code** code_address = \
4464 reinterpret_cast<Code**>(builtin_address(k##name)); \
4465 return Handle<Code>(code_address); \
4466}
4467#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
4468Handle<Code> Builtins::name() { \
4469 Code** code_address = \
4470 reinterpret_cast<Code**>(builtin_address(k##name)); \
4471 return Handle<Code>(code_address); \
4472}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004473#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
4474Handle<Code> Builtins::name() { \
4475 Code** code_address = \
4476 reinterpret_cast<Code**>(builtin_address(k##name)); \
4477 return Handle<Code>(code_address); \
4478}
Steve Block44f0eee2011-05-26 01:26:41 +01004479BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
4480BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004481BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01004482BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4483#undef DEFINE_BUILTIN_ACCESSOR_C
4484#undef DEFINE_BUILTIN_ACCESSOR_A
4485
4486
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004487} // namespace internal
4488} // namespace v8