blob: 9c3ff5956b29d737e957dd65a0768f88a98243fc [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 Murdochda12d292016-06-02 14:46:10 +01008#include "src/api-arguments.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/api-natives.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/base/once.h"
11#include "src/bootstrapper.h"
Ben Murdochda12d292016-06-02 14:46:10 +010012#include "src/code-factory.h"
13#include "src/compiler/code-stub-assembler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/dateparser-inl.h"
15#include "src/elements.h"
16#include "src/frames-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/gdb-jit.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/ic/handler-compiler.h"
19#include "src/ic/ic.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020#include "src/isolate-inl.h"
21#include "src/messages.h"
22#include "src/profiler/cpu-profiler.h"
23#include "src/property-descriptor.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/prototype.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025#include "src/string-builder.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000027
28namespace v8 {
29namespace internal {
30
Leon Clarkee46be812010-01-19 14:06:41 +000031namespace {
32
33// Arguments object passed to C++ builtins.
34template <BuiltinExtraArguments extra_args>
35class BuiltinArguments : public Arguments {
36 public:
37 BuiltinArguments(int length, Object** arguments)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038 : Arguments(length, arguments) {
39 // Check we have at least the receiver.
40 DCHECK_LE(1, this->length());
41 }
Leon Clarkee46be812010-01-19 14:06:41 +000042
43 Object*& operator[] (int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044 DCHECK(index < length());
Leon Clarkee46be812010-01-19 14:06:41 +000045 return Arguments::operator[](index);
46 }
47
48 template <class S> Handle<S> at(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 DCHECK(index < length());
Leon Clarkee46be812010-01-19 14:06:41 +000050 return Arguments::at<S>(index);
51 }
52
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 Handle<Object> atOrUndefined(Isolate* isolate, int index) {
54 if (index >= length()) {
55 return isolate->factory()->undefined_value();
56 }
57 return at<Object>(index);
58 }
59
Leon Clarkee46be812010-01-19 14:06:41 +000060 Handle<Object> receiver() {
61 return Arguments::at<Object>(0);
62 }
63
Ben Murdoch097c5b22016-05-18 11:27:45 +010064 template <class S>
65 Handle<S> target();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 Handle<HeapObject> new_target();
Leon Clarkee46be812010-01-19 14:06:41 +000067
68 // Gets the total number of arguments including the receiver (but
69 // excluding extra arguments).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 int length() const;
Leon Clarkee46be812010-01-19 14:06:41 +000071};
72
73
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074// Specialize BuiltinArguments for the extra arguments.
Leon Clarkee46be812010-01-19 14:06:41 +000075
76template <>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
78 return Arguments::length();
79}
80
81template <>
82int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
Leon Clarkee46be812010-01-19 14:06:41 +000083 return Arguments::length() - 1;
84}
85
Leon Clarkee46be812010-01-19 14:06:41 +000086template <>
Ben Murdoch097c5b22016-05-18 11:27:45 +010087template <class S>
88Handle<S> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
89 return Arguments::at<S>(Arguments::length() - 1);
Leon Clarkee46be812010-01-19 14:06:41 +000090}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091
92template <>
93int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
94 return Arguments::length() - 1;
95}
96
97template <>
98Handle<HeapObject>
99BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
100 return Arguments::at<HeapObject>(Arguments::length() - 1);
101}
102
103template <>
104int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
105 const {
106 return Arguments::length() - 2;
107}
108
109template <>
Ben Murdoch097c5b22016-05-18 11:27:45 +0100110template <class S>
111Handle<S>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100113 return Arguments::at<S>(Arguments::length() - 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114}
115
116template <>
117Handle<HeapObject>
118BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
119 return Arguments::at<HeapObject>(Arguments::length() - 1);
120}
Leon Clarkee46be812010-01-19 14:06:41 +0000121
122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123#define DEF_ARG_TYPE(name, spec) \
124 typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
Leon Clarkee46be812010-01-19 14:06:41 +0000125BUILTIN_LIST_C(DEF_ARG_TYPE)
126#undef DEF_ARG_TYPE
127
Leon Clarkee46be812010-01-19 14:06:41 +0000128
Steve Blocka7e24c12009-10-30 11:49:00 +0000129// ----------------------------------------------------------------------------
Leon Clarkee46be812010-01-19 14:06:41 +0000130// Support macro for defining builtins in C++.
Steve Blocka7e24c12009-10-30 11:49:00 +0000131// ----------------------------------------------------------------------------
132//
133// A builtin function is defined by writing:
134//
135// BUILTIN(name) {
136// ...
137// }
Steve Blocka7e24c12009-10-30 11:49:00 +0000138//
Leon Clarkee46be812010-01-19 14:06:41 +0000139// In the body of the builtin function the arguments can be accessed
140// through the BuiltinArguments object args.
Steve Blocka7e24c12009-10-30 11:49:00 +0000141
Ben Murdoch097c5b22016-05-18 11:27:45 +0100142#define BUILTIN(name) \
143 MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
144 Isolate* isolate); \
145 MUST_USE_RESULT static Object* Builtin_##name( \
146 int args_length, Object** args_object, Isolate* isolate) { \
Ben Murdochda12d292016-06-02 14:46:10 +0100147 Object* value; \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100148 isolate->counters()->runtime_calls()->Increment(); \
Ben Murdochda12d292016-06-02 14:46:10 +0100149 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
150 "V8.Builtin_" #name); \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100151 name##ArgumentsType args(args_length, args_object); \
Ben Murdochda12d292016-06-02 14:46:10 +0100152 if (FLAG_runtime_call_stats) { \
153 RuntimeCallStats* stats = isolate->counters()->runtime_call_stats(); \
154 RuntimeCallTimerScope timer(isolate, &stats->Builtin_##name); \
155 value = Builtin_Impl_##name(args, isolate); \
156 } else { \
157 value = Builtin_Impl_##name(args, isolate); \
158 } \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100159 return value; \
160 } \
161 \
162 MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
163 Isolate* isolate)
Steve Blocka7e24c12009-10-30 11:49:00 +0000164
165// ----------------------------------------------------------------------------
166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167
168#define CHECK_RECEIVER(Type, name, method) \
169 if (!args.receiver()->Is##Type()) { \
170 THROW_NEW_ERROR_RETURN_FAILURE( \
171 isolate, \
172 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
173 isolate->factory()->NewStringFromAsciiChecked(method), \
174 args.receiver())); \
175 } \
176 Handle<Type> name = Handle<Type>::cast(args.receiver())
177
178
179inline bool ClampedToInteger(Object* object, int* out) {
180 // This is an extended version of ECMA-262 7.1.11 handling signed values
181 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
182 if (object->IsSmi()) {
183 *out = Smi::cast(object)->value();
184 return true;
185 } else if (object->IsHeapNumber()) {
186 double value = HeapNumber::cast(object)->value();
187 if (std::isnan(value)) {
188 *out = 0;
189 } else if (value > kMaxInt) {
190 *out = kMaxInt;
191 } else if (value < kMinInt) {
192 *out = kMinInt;
193 } else {
194 *out = static_cast<int>(value);
195 }
196 return true;
197 } else if (object->IsUndefined() || object->IsNull()) {
198 *out = 0;
199 return true;
200 } else if (object->IsBoolean()) {
201 *out = object->IsTrue();
202 return true;
203 }
204 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000205}
Steve Blocka7e24c12009-10-30 11:49:00 +0000206
207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
209 int* out) {
210 Map* arguments_map = isolate->native_context()->sloppy_arguments_map();
211 if (object->map() != arguments_map) return false;
212 DCHECK(object->HasFastElements());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100213 Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 if (!len_obj->IsSmi()) return false;
215 *out = Max(0, Smi::cast(len_obj)->value());
216 return *out <= object->elements()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000217}
Steve Blocka7e24c12009-10-30 11:49:00 +0000218
Ben Murdochda12d292016-06-02 14:46:10 +0100219inline bool PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 DisallowHeapAllocation no_gc;
Ben Murdochda12d292016-06-02 14:46:10 +0100221 HeapObject* prototype = HeapObject::cast(object->map()->prototype());
222 HeapObject* null = isolate->heap()->null_value();
223 HeapObject* empty = isolate->heap()->empty_fixed_array();
224 while (prototype != null) {
225 Map* map = prototype->map();
226 if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false;
227 if (JSObject::cast(prototype)->elements() != empty) return false;
228 prototype = HeapObject::cast(map->prototype());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230 return true;
231}
232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
234 JSArray* receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100235 return PrototypeHasNoElements(isolate, receiver);
Steve Block6ded16b2010-05-10 14:33:55 +0100236}
237
Ben Murdoch097c5b22016-05-18 11:27:45 +0100238inline bool HasSimpleElements(JSObject* current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100239 return current->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
240 !current->GetElementsAccessor()->HasAccessors(current);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100241}
242
243inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
Ben Murdochda12d292016-06-02 14:46:10 +0100244 JSObject* receiver) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100245 // Check that we have no accessors on the receiver's elements.
Ben Murdochda12d292016-06-02 14:46:10 +0100246 if (!HasSimpleElements(receiver)) return false;
247 return PrototypeHasNoElements(isolate, receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100248}
249
250inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100251 DisallowHeapAllocation no_gc;
252 PrototypeIterator iter(isolate, receiver,
253 PrototypeIterator::START_AT_RECEIVER);
254 for (; !iter.IsAtEnd(); iter.Advance()) {
255 if (iter.GetCurrent()->IsJSProxy()) return false;
256 JSObject* current = iter.GetCurrent<JSObject>();
257 if (!HasSimpleElements(current)) return false;
258 }
259 return true;
260}
Steve Block6ded16b2010-05-10 14:33:55 +0100261
Ben Murdochda12d292016-06-02 14:46:10 +0100262// Returns |false| if not applicable.
John Reck59135872010-11-02 12:39:01 -0700263MUST_USE_RESULT
Ben Murdochda12d292016-06-02 14:46:10 +0100264inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
265 Handle<Object> receiver,
266 Arguments* args,
267 int first_added_arg) {
268 if (!receiver->IsJSArray()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Ben Murdochda12d292016-06-02 14:46:10 +0100270 ElementsKind origin_kind = array->GetElementsKind();
271 if (IsDictionaryElementsKind(origin_kind)) return false;
272 if (array->map()->is_observed()) return false;
273 if (!array->map()->is_extensible()) return false;
274 if (args == nullptr) return true;
275
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 // If there may be elements accessors in the prototype chain, the fast path
277 // cannot be used if there arguments to add to the array.
Ben Murdochda12d292016-06-02 14:46:10 +0100278 if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100279
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 // Adding elements to the array prototype would break code that makes sure
281 // it has no elements. Handle that elsewhere.
Ben Murdochda12d292016-06-02 14:46:10 +0100282 if (isolate->IsAnyInitialArrayPrototype(array)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100284 // Need to ensure that the arguments passed in args can be contained in
285 // the array.
286 int args_length = args->length();
Ben Murdochda12d292016-06-02 14:46:10 +0100287 if (first_added_arg >= args_length) return true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100288
Ben Murdochda12d292016-06-02 14:46:10 +0100289 if (IsFastObjectElementsKind(origin_kind)) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000290 ElementsKind target_kind = origin_kind;
291 {
292 DisallowHeapAllocation no_gc;
Ben Murdochda12d292016-06-02 14:46:10 +0100293 for (int i = first_added_arg; i < args_length; i++) {
294 Object* arg = (*args)[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 if (arg->IsHeapObject()) {
296 if (arg->IsHeapNumber()) {
297 target_kind = FAST_DOUBLE_ELEMENTS;
298 } else {
299 target_kind = FAST_ELEMENTS;
300 break;
301 }
302 }
303 }
304 }
305 if (target_kind != origin_kind) {
Ben Murdochda12d292016-06-02 14:46:10 +0100306 // Use a short-lived HandleScope to avoid creating several copies of the
307 // elements handle which would cause issues when left-trimming later-on.
308 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 JSObject::TransitionElementsKind(array, target_kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 }
Ben Murdochda12d292016-06-02 14:46:10 +0100311 return true;
Steve Block6ded16b2010-05-10 14:33:55 +0100312}
313
314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315MUST_USE_RESULT static Object* CallJsIntrinsic(
316 Isolate* isolate, Handle<JSFunction> function,
317 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100318 HandleScope handleScope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100319 int argc = args.length() - 1;
320 ScopedVector<Handle<Object> > argv(argc);
321 for (int i = 0; i < argc; ++i) {
322 argv[i] = args.at<Object>(i + 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100323 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324 Handle<Object> result;
325 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
326 isolate, result,
327 Execution::Call(isolate,
328 function,
329 args.receiver(),
330 argc,
331 argv.start()));
Steve Block6ded16b2010-05-10 14:33:55 +0100332 return *result;
333}
334
335
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336} // namespace
337
338
339BUILTIN(Illegal) {
340 UNREACHABLE();
341 return isolate->heap()->undefined_value(); // Make compiler happy.
342}
343
344
345BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
346
Ben Murdochda12d292016-06-02 14:46:10 +0100347void Builtins::Generate_ObjectHasOwnProperty(
348 compiler::CodeStubAssembler* assembler) {
349 typedef compiler::Node Node;
350 typedef compiler::CodeStubAssembler::Label Label;
351 typedef compiler::CodeStubAssembler::Variable Variable;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352
Ben Murdochda12d292016-06-02 14:46:10 +0100353 Node* object = assembler->Parameter(0);
354 Node* key = assembler->Parameter(1);
355 Node* context = assembler->Parameter(4);
356
357 Label call_runtime(assembler), return_true(assembler),
358 return_false(assembler);
359
360 // Smi receivers do not have own properties.
361 Label if_objectisnotsmi(assembler);
362 assembler->Branch(assembler->WordIsSmi(object), &return_false,
363 &if_objectisnotsmi);
364 assembler->Bind(&if_objectisnotsmi);
365
366 Node* map = assembler->LoadMap(object);
367 Node* instance_type = assembler->LoadMapInstanceType(map);
368
369 Variable var_index(assembler, MachineRepresentation::kWord32);
370
371 Label if_keyissmi(assembler), if_keyisnotsmi(assembler),
372 keyisindex(assembler);
373 assembler->Branch(assembler->WordIsSmi(key), &if_keyissmi, &if_keyisnotsmi);
374 assembler->Bind(&if_keyissmi);
375 {
376 // Negative smi keys are named properties. Handle in the runtime.
377 Label if_keyispositive(assembler);
378 assembler->Branch(assembler->WordIsPositiveSmi(key), &if_keyispositive,
379 &call_runtime);
380 assembler->Bind(&if_keyispositive);
381
382 var_index.Bind(assembler->SmiUntag(key));
383 assembler->Goto(&keyisindex);
384 }
385
386 assembler->Bind(&if_keyisnotsmi);
387
388 Node* key_instance_type = assembler->LoadInstanceType(key);
389 Label if_iskeyunique(assembler), if_iskeynotsymbol(assembler);
390 assembler->Branch(
391 assembler->Word32Equal(key_instance_type,
392 assembler->Int32Constant(SYMBOL_TYPE)),
393 &if_iskeyunique, &if_iskeynotsymbol);
394 assembler->Bind(&if_iskeynotsymbol);
395 {
396 Label if_iskeyinternalized(assembler);
397 Node* bits = assembler->WordAnd(
398 key_instance_type,
399 assembler->Int32Constant(kIsNotStringMask | kIsNotInternalizedMask));
400 assembler->Branch(
401 assembler->Word32Equal(
402 bits, assembler->Int32Constant(kStringTag | kInternalizedTag)),
403 &if_iskeyinternalized, &call_runtime);
404 assembler->Bind(&if_iskeyinternalized);
405
406 // Check whether the key is an array index passed in as string. Handle
407 // uniform with smi keys if so.
408 // TODO(verwaest): Also support non-internalized strings.
409 Node* hash = assembler->LoadNameHash(key);
410 Node* bit = assembler->Word32And(
411 hash, assembler->Int32Constant(internal::Name::kIsNotArrayIndexMask));
412 Label if_isarrayindex(assembler);
413 assembler->Branch(assembler->Word32Equal(bit, assembler->Int32Constant(0)),
414 &if_isarrayindex, &if_iskeyunique);
415 assembler->Bind(&if_isarrayindex);
416 var_index.Bind(
417 assembler->BitFieldDecode<internal::Name::ArrayIndexValueBits>(hash));
418 assembler->Goto(&keyisindex);
419 }
420 assembler->Bind(&if_iskeyunique);
421
422 {
423 Label if_objectissimple(assembler);
424 assembler->Branch(assembler->Int32LessThanOrEqual(
425 instance_type,
426 assembler->Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
427 &call_runtime, &if_objectissimple);
428 assembler->Bind(&if_objectissimple);
429 }
430
431 // TODO(verwaest): Perform a dictonary lookup on slow-mode receivers.
432 Node* bit_field3 = assembler->LoadMapBitField3(map);
433 Node* bit = assembler->BitFieldDecode<Map::DictionaryMap>(bit_field3);
434 Label if_isfastmap(assembler);
435 assembler->Branch(assembler->Word32Equal(bit, assembler->Int32Constant(0)),
436 &if_isfastmap, &call_runtime);
437 assembler->Bind(&if_isfastmap);
438 Node* nof =
439 assembler->BitFieldDecode<Map::NumberOfOwnDescriptorsBits>(bit_field3);
440 // Bail out to the runtime for large numbers of own descriptors. The stub only
441 // does linear search, which becomes too expensive in that case.
442 {
443 static const int32_t kMaxLinear = 256;
444 Label above_max(assembler), below_max(assembler);
445 assembler->Branch(assembler->Int32LessThanOrEqual(
446 nof, assembler->Int32Constant(kMaxLinear)),
447 &below_max, &call_runtime);
448 assembler->Bind(&below_max);
449 }
450 Node* descriptors = assembler->LoadMapDescriptors(map);
451
452 Variable var_descriptor(assembler, MachineRepresentation::kWord32);
453 Label loop(assembler, &var_descriptor);
454 var_descriptor.Bind(assembler->Int32Constant(0));
455 assembler->Goto(&loop);
456 assembler->Bind(&loop);
457 {
458 Node* index = var_descriptor.value();
459 Node* offset = assembler->Int32Constant(DescriptorArray::ToKeyIndex(0));
460 Node* factor = assembler->Int32Constant(DescriptorArray::kDescriptorSize);
461 Label if_notdone(assembler);
462 assembler->Branch(assembler->Word32Equal(index, nof), &return_false,
463 &if_notdone);
464 assembler->Bind(&if_notdone);
465 {
466 Node* array_index =
467 assembler->Int32Add(offset, assembler->Int32Mul(index, factor));
468 Node* current =
469 assembler->LoadFixedArrayElementInt32Index(descriptors, array_index);
470 Label if_unequal(assembler);
471 assembler->Branch(assembler->WordEqual(current, key), &return_true,
472 &if_unequal);
473 assembler->Bind(&if_unequal);
474
475 var_descriptor.Bind(
476 assembler->Int32Add(index, assembler->Int32Constant(1)));
477 assembler->Goto(&loop);
478 }
479 }
480
481 assembler->Bind(&keyisindex);
482 {
483 Label if_objectissimple(assembler);
484 assembler->Branch(assembler->Int32LessThanOrEqual(
485 instance_type, assembler->Int32Constant(
486 LAST_CUSTOM_ELEMENTS_RECEIVER)),
487 &call_runtime, &if_objectissimple);
488 assembler->Bind(&if_objectissimple);
489 }
490
491 Node* index = var_index.value();
492 Node* bit_field2 = assembler->LoadMapBitField2(map);
493 Node* elements_kind =
494 assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2);
495
496 // TODO(verwaest): Support other elements kinds as well.
497 Label if_isobjectorsmi(assembler);
498 assembler->Branch(
499 assembler->Int32LessThanOrEqual(
500 elements_kind, assembler->Int32Constant(FAST_HOLEY_ELEMENTS)),
501 &if_isobjectorsmi, &call_runtime);
502 assembler->Bind(&if_isobjectorsmi);
503 {
504 Node* elements = assembler->LoadElements(object);
505 Node* length = assembler->LoadFixedArrayBaseLength(elements);
506
507 Label if_iskeyinrange(assembler);
508 assembler->Branch(
509 assembler->Int32LessThan(index, assembler->SmiToWord32(length)),
510 &if_iskeyinrange, &return_false);
511
512 assembler->Bind(&if_iskeyinrange);
513 Node* element = assembler->LoadFixedArrayElementInt32Index(elements, index);
514 Node* the_hole = assembler->LoadRoot(Heap::kTheHoleValueRootIndex);
515 assembler->Branch(assembler->WordEqual(element, the_hole), &return_false,
516 &return_true);
517 }
518
519 assembler->Bind(&return_true);
520 assembler->Return(assembler->BooleanConstant(true));
521
522 assembler->Bind(&return_false);
523 assembler->Return(assembler->BooleanConstant(false));
524
525 assembler->Bind(&call_runtime);
526 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
527 context, object, key));
528}
529
530namespace {
531
532Object* DoArrayPush(Isolate* isolate,
533 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534 HandleScope scope(isolate);
535 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100536 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 return CallJsIntrinsic(isolate, isolate->array_push(), args);
John Reck59135872010-11-02 12:39:01 -0700538 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 // Fast Elements Path
Ben Murdochda12d292016-06-02 14:46:10 +0100540 int to_add = args.length() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000541 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 int len = Smi::cast(array->length())->value();
Ben Murdochda12d292016-06-02 14:46:10 +0100543 if (to_add == 0) return Smi::FromInt(len);
544
545 // Currently fixed arrays cannot grow too big, so we should never hit this.
546 DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
547
548 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 return CallJsIntrinsic(isolate, isolate->array_push(), args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000550 }
Ben Murdochda12d292016-06-02 14:46:10 +0100551
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552 ElementsAccessor* accessor = array->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100553 int new_length = accessor->Push(array, &args, to_add);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 return Smi::FromInt(new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000555}
Steve Blocka7e24c12009-10-30 11:49:00 +0000556
Ben Murdochda12d292016-06-02 14:46:10 +0100557} // namespace
558
559BUILTIN(ArrayPush) { return DoArrayPush(isolate, args); }
560
561// TODO(verwaest): This is a temporary helper until the FastArrayPush stub can
562// tailcall to the builtin directly.
563RUNTIME_FUNCTION(Runtime_ArrayPush) {
564 DCHECK_EQ(2, args.length());
565 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
566 // Rewrap the arguments as builtins arguments.
567 BuiltinArguments<BuiltinExtraArguments::kNone> caller_args(
568 incoming->length() + 1, incoming->arguments() + 1);
569 return DoArrayPush(isolate, caller_args);
570}
Steve Blocka7e24c12009-10-30 11:49:00 +0000571
572BUILTIN(ArrayPop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 HandleScope scope(isolate);
574 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100575 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
John Reck59135872010-11-02 12:39:01 -0700577 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578
579 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
580 DCHECK(!array->map()->is_observed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000581
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 if (len == 0) return isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000584
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400585 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000586 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400587 }
588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000589 Handle<Object> result;
590 if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
591 // Fast Elements Path
Ben Murdochda12d292016-06-02 14:46:10 +0100592 result = array->GetElementsAccessor()->Pop(array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 } else {
594 // Use Slow Lookup otherwise
595 uint32_t new_length = len - 1;
596 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdochda12d292016-06-02 14:46:10 +0100597 isolate, result, JSReceiver::GetElement(isolate, array, new_length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000598 JSArray::SetLength(array, new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 return *result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000601}
Steve Blocka7e24c12009-10-30 11:49:00 +0000602
603
Andrei Popescu402d9372010-02-26 13:31:12 +0000604BUILTIN(ArrayShift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100606 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100608 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0) ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
610 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100611 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
613 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000614
615 int len = Smi::cast(array->length())->value();
Steve Block44f0eee2011-05-26 01:26:41 +0100616 if (len == 0) return heap->undefined_value();
Andrei Popescu402d9372010-02-26 13:31:12 +0000617
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400618 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000619 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400620 }
621
Ben Murdochda12d292016-06-02 14:46:10 +0100622 Handle<Object> first = array->GetElementsAccessor()->Shift(array);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 return *first;
Andrei Popescu402d9372010-02-26 13:31:12 +0000624}
625
626
627BUILTIN(ArrayUnshift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100630 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100632 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
634 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000635 int to_add = args.length() - 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100636 if (to_add == 0) return array->length();
Andrei Popescu402d9372010-02-26 13:31:12 +0000637
Ben Murdochda12d292016-06-02 14:46:10 +0100638 // Currently fixed arrays cannot grow too big, so we should never hit this.
639 DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
640
641 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 }
644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 ElementsAccessor* accessor = array->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100646 int new_length = accessor->Unshift(array, &args, to_add);
Andrei Popescu402d9372010-02-26 13:31:12 +0000647 return Smi::FromInt(new_length);
648}
649
650
Andrei Popescu402d9372010-02-26 13:31:12 +0000651BUILTIN(ArraySlice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 Handle<Object> receiver = args.receiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100654 int len = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 int relative_start = 0;
656 int relative_end = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 if (receiver->IsJSArray()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660 JSArray* array = JSArray::cast(*receiver);
Ben Murdochda12d292016-06-02 14:46:10 +0100661 if (V8_UNLIKELY(!array->HasFastElements() ||
662 !IsJSArrayFastElementMovingAllowed(isolate, array) ||
663 !isolate->IsArraySpeciesLookupChainIntact() ||
664 // If this is a subclass of Array, then call out to JS
665 !array->HasArrayPrototype(isolate))) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666 AllowHeapAllocation allow_allocation;
667 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Steve Block9fac8402011-05-12 15:51:54 +0100668 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 len = Smi::cast(array->length())->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 } else if (receiver->IsJSObject() &&
671 GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
672 &len)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100673 DCHECK_EQ(FAST_ELEMENTS, JSObject::cast(*receiver)->GetElementsKind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 // Array.prototype.slice(arguments, ...) is quite a common idiom
675 // (notably more than 50% of invocations in Web apps).
676 // Treat it in C++ as well.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000677 } else {
678 AllowHeapAllocation allow_allocation;
679 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
680 }
Ben Murdochda12d292016-06-02 14:46:10 +0100681 DCHECK_LE(0, len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 int argument_count = args.length() - 1;
683 // Note carefully chosen defaults---if argument is missing,
684 // it's undefined which gets converted to 0 for relative_start
685 // and to len for relative_end.
686 relative_start = 0;
687 relative_end = len;
688 if (argument_count > 0) {
689 DisallowHeapAllocation no_gc;
690 if (!ClampedToInteger(args[1], &relative_start)) {
691 AllowHeapAllocation allow_allocation;
692 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
693 }
694 if (argument_count > 1) {
695 Object* end_arg = args[2];
696 // slice handles the end_arg specially
697 if (end_arg->IsUndefined()) {
698 relative_end = len;
699 } else if (!ClampedToInteger(end_arg, &relative_end)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000701 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000702 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000703 }
704 }
705
706 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
708 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000709
710 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 uint32_t actual_end =
712 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000713
Ben Murdochda12d292016-06-02 14:46:10 +0100714 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000715 ElementsAccessor* accessor = object->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100716 return *accessor->Slice(object, actual_start, actual_end);
Andrei Popescu402d9372010-02-26 13:31:12 +0000717}
718
719
720BUILTIN(ArraySplice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100723 if (V8_UNLIKELY(
724 !EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3) ||
725 // If this is a subclass of Array, then call out to JS.
726 !Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) ||
727 // If anything with @@species has been messed with, call out to JS.
728 !isolate->IsArraySpeciesLookupChainIntact())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100730 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
732 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000733
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000734 int argument_count = args.length() - 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100735 int relative_start = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000736 if (argument_count > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 if (!ClampedToInteger(args[1], &relative_start)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000739 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000740 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100741 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000742 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 int len = Smi::cast(array->length())->value();
744 // clip relative start to [0, len]
Steve Block6ded16b2010-05-10 14:33:55 +0100745 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
746 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000747
Steve Block1e0659c2011-05-24 12:43:12 +0100748 int actual_delete_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749 if (argument_count == 1) {
750 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
751 // given as a request to delete all the elements from the start.
752 // And it differs from the case of undefined delete count.
753 // This does not follow ECMA-262, but we do the same for compatibility.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000754 DCHECK(len - actual_start >= 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100755 actual_delete_count = len - actual_start;
756 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 int delete_count = 0;
758 DisallowHeapAllocation no_gc;
759 if (argument_count > 1) {
760 if (!ClampedToInteger(args[2], &delete_count)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100763 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000764 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
Andrei Popescu402d9372010-02-26 13:31:12 +0000766 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
769 int new_length = len - actual_delete_count + add_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400771 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
772 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400774 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 ElementsAccessor* accessor = array->GetElementsAccessor();
776 Handle<JSArray> result_array = accessor->Splice(
Ben Murdochda12d292016-06-02 14:46:10 +0100777 array, actual_start, actual_delete_count, &args, add_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000779}
780
781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782// Array Concat -------------------------------------------------------------
Steve Block6ded16b2010-05-10 14:33:55 +0100783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000784namespace {
785
786/**
787 * A simple visitor visits every element of Array's.
788 * The backend storage can be a fixed array for fast elements case,
789 * or a dictionary for sparse array. Since Dictionary is a subtype
790 * of FixedArray, the class can be used by both fast and slow cases.
791 * The second parameter of the constructor, fast_elements, specifies
792 * whether the storage is a FixedArray or Dictionary.
793 *
794 * An index limit is used to deal with the situation that a result array
795 * length overflows 32-bit non-negative integer.
796 */
797class ArrayConcatVisitor {
798 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100799 ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 bool fast_elements)
801 : isolate_(isolate),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100802 storage_(isolate->global_handles()->Create(*storage)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000803 index_offset_(0u),
804 bit_field_(FastElementsField::encode(fast_elements) |
Ben Murdoch097c5b22016-05-18 11:27:45 +0100805 ExceedsLimitField::encode(false) |
806 IsFixedArrayField::encode(storage->IsFixedArray())) {
807 DCHECK(!(this->fast_elements() && !is_fixed_array()));
808 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809
810 ~ArrayConcatVisitor() { clear_storage(); }
811
Ben Murdochda12d292016-06-02 14:46:10 +0100812 MUST_USE_RESULT bool visit(uint32_t i, Handle<Object> elm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 uint32_t index = index_offset_ + i;
814
Ben Murdoch097c5b22016-05-18 11:27:45 +0100815 if (i >= JSObject::kMaxElementCount - index_offset_) {
816 set_exceeds_array_limit(true);
817 // Exception hasn't been thrown at this point. Return true to
818 // break out, and caller will throw. !visit would imply that
819 // there is already a pending exception.
820 return true;
821 }
822
Ben Murdochda12d292016-06-02 14:46:10 +0100823 if (!is_fixed_array()) {
824 LookupIterator it(isolate_, storage_, index, LookupIterator::OWN);
825 MAYBE_RETURN(
826 JSReceiver::CreateDataProperty(&it, elm, Object::THROW_ON_ERROR),
827 false);
828 return true;
829 }
830
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 if (fast_elements()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100832 if (index < static_cast<uint32_t>(storage_fixed_array()->length())) {
833 storage_fixed_array()->set(index, *elm);
834 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 }
836 // Our initial estimate of length was foiled, possibly by
837 // getters on the arrays increasing the length of later arrays
838 // during iteration.
839 // This shouldn't happen in anything but pathological cases.
840 SetDictionaryMode();
841 // Fall-through to dictionary mode.
842 }
843 DCHECK(!fast_elements());
844 Handle<SeededNumberDictionary> dict(
845 SeededNumberDictionary::cast(*storage_));
846 // The object holding this backing store has just been allocated, so
847 // it cannot yet be used as a prototype.
848 Handle<SeededNumberDictionary> result =
849 SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
850 if (!result.is_identical_to(dict)) {
851 // Dictionary needed to grow.
852 clear_storage();
853 set_storage(*result);
854 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100855 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856 }
857
858 void increase_index_offset(uint32_t delta) {
859 if (JSObject::kMaxElementCount - index_offset_ < delta) {
860 index_offset_ = JSObject::kMaxElementCount;
861 } else {
862 index_offset_ += delta;
863 }
864 // If the initial length estimate was off (see special case in visit()),
865 // but the array blowing the limit didn't contain elements beyond the
866 // provided-for index range, go to dictionary mode now.
867 if (fast_elements() &&
868 index_offset_ >
869 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
870 SetDictionaryMode();
871 }
872 }
873
874 bool exceeds_array_limit() const {
875 return ExceedsLimitField::decode(bit_field_);
876 }
877
878 Handle<JSArray> ToArray() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100879 DCHECK(is_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
881 Handle<Object> length =
882 isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
883 Handle<Map> map = JSObject::GetElementsTransitionMap(
884 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
885 array->set_map(*map);
886 array->set_length(*length);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100887 array->set_elements(*storage_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000888 return array;
889 }
890
Ben Murdoch097c5b22016-05-18 11:27:45 +0100891 // Storage is either a FixedArray (if is_fixed_array()) or a JSReciever
892 // (otherwise)
893 Handle<FixedArray> storage_fixed_array() {
894 DCHECK(is_fixed_array());
895 return Handle<FixedArray>::cast(storage_);
896 }
897 Handle<JSReceiver> storage_jsreceiver() {
898 DCHECK(!is_fixed_array());
899 return Handle<JSReceiver>::cast(storage_);
900 }
901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 private:
903 // Convert storage to dictionary mode.
904 void SetDictionaryMode() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100905 DCHECK(fast_elements() && is_fixed_array());
906 Handle<FixedArray> current_storage = storage_fixed_array();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907 Handle<SeededNumberDictionary> slow_storage(
908 SeededNumberDictionary::New(isolate_, current_storage->length()));
909 uint32_t current_length = static_cast<uint32_t>(current_storage->length());
Ben Murdochda12d292016-06-02 14:46:10 +0100910 FOR_WITH_HANDLE_SCOPE(
911 isolate_, uint32_t, i = 0, i, i < current_length, i++, {
912 Handle<Object> element(current_storage->get(i), isolate_);
913 if (!element->IsTheHole()) {
914 // The object holding this backing store has just been allocated, so
915 // it cannot yet be used as a prototype.
916 Handle<SeededNumberDictionary> new_storage =
917 SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
918 false);
919 if (!new_storage.is_identical_to(slow_storage)) {
920 slow_storage = loop_scope.CloseAndEscape(new_storage);
921 }
922 }
923 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924 clear_storage();
925 set_storage(*slow_storage);
926 set_fast_elements(false);
927 }
928
Ben Murdochda12d292016-06-02 14:46:10 +0100929 inline void clear_storage() { GlobalHandles::Destroy(storage_.location()); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000930
931 inline void set_storage(FixedArray* storage) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100932 DCHECK(is_fixed_array());
933 storage_ = isolate_->global_handles()->Create(storage);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000934 }
935
936 class FastElementsField : public BitField<bool, 0, 1> {};
937 class ExceedsLimitField : public BitField<bool, 1, 1> {};
Ben Murdoch097c5b22016-05-18 11:27:45 +0100938 class IsFixedArrayField : public BitField<bool, 2, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939
940 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
941 void set_fast_elements(bool fast) {
942 bit_field_ = FastElementsField::update(bit_field_, fast);
943 }
944 void set_exceeds_array_limit(bool exceeds) {
945 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
946 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100947 bool is_fixed_array() const { return IsFixedArrayField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948
949 Isolate* isolate_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100950 Handle<Object> storage_; // Always a global handle.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 // Index after last seen index. Always less than or equal to
952 // JSObject::kMaxElementCount.
953 uint32_t index_offset_;
954 uint32_t bit_field_;
955};
956
957
958uint32_t EstimateElementCount(Handle<JSArray> array) {
959 uint32_t length = static_cast<uint32_t>(array->length()->Number());
960 int element_count = 0;
961 switch (array->GetElementsKind()) {
962 case FAST_SMI_ELEMENTS:
963 case FAST_HOLEY_SMI_ELEMENTS:
964 case FAST_ELEMENTS:
965 case FAST_HOLEY_ELEMENTS: {
966 // Fast elements can't have lengths that are not representable by
967 // a 32-bit signed integer.
968 DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
969 int fast_length = static_cast<int>(length);
970 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
971 for (int i = 0; i < fast_length; i++) {
972 if (!elements->get(i)->IsTheHole()) element_count++;
973 }
974 break;
975 }
976 case FAST_DOUBLE_ELEMENTS:
977 case FAST_HOLEY_DOUBLE_ELEMENTS: {
978 // Fast elements can't have lengths that are not representable by
979 // a 32-bit signed integer.
980 DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
981 int fast_length = static_cast<int>(length);
982 if (array->elements()->IsFixedArray()) {
983 DCHECK(FixedArray::cast(array->elements())->length() == 0);
984 break;
985 }
986 Handle<FixedDoubleArray> elements(
987 FixedDoubleArray::cast(array->elements()));
988 for (int i = 0; i < fast_length; i++) {
989 if (!elements->is_the_hole(i)) element_count++;
990 }
991 break;
992 }
993 case DICTIONARY_ELEMENTS: {
994 Handle<SeededNumberDictionary> dictionary(
995 SeededNumberDictionary::cast(array->elements()));
996 int capacity = dictionary->Capacity();
997 for (int i = 0; i < capacity; i++) {
998 Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
999 if (dictionary->IsKey(*key)) {
1000 element_count++;
1001 }
1002 }
1003 break;
1004 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1006
1007 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1008#undef TYPED_ARRAY_CASE
1009 // External arrays are always dense.
1010 return length;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001011 case NO_ELEMENTS:
1012 return 0;
1013 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1014 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
1015 case FAST_STRING_WRAPPER_ELEMENTS:
1016 case SLOW_STRING_WRAPPER_ELEMENTS:
1017 UNREACHABLE();
1018 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 }
1020 // As an estimate, we assume that the prototype doesn't contain any
1021 // inherited elements.
1022 return element_count;
1023}
1024
1025
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001026// Used for sorting indices in a List<uint32_t>.
1027int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
1028 uint32_t a = *ap;
1029 uint32_t b = *bp;
1030 return (a == b) ? 0 : (a < b) ? -1 : 1;
1031}
1032
1033
1034void CollectElementIndices(Handle<JSObject> object, uint32_t range,
1035 List<uint32_t>* indices) {
1036 Isolate* isolate = object->GetIsolate();
1037 ElementsKind kind = object->GetElementsKind();
1038 switch (kind) {
1039 case FAST_SMI_ELEMENTS:
1040 case FAST_ELEMENTS:
1041 case FAST_HOLEY_SMI_ELEMENTS:
1042 case FAST_HOLEY_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001043 DisallowHeapAllocation no_gc;
1044 FixedArray* elements = FixedArray::cast(object->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 uint32_t length = static_cast<uint32_t>(elements->length());
1046 if (range < length) length = range;
1047 for (uint32_t i = 0; i < length; i++) {
1048 if (!elements->get(i)->IsTheHole()) {
1049 indices->Add(i);
1050 }
1051 }
1052 break;
1053 }
1054 case FAST_HOLEY_DOUBLE_ELEMENTS:
1055 case FAST_DOUBLE_ELEMENTS: {
1056 if (object->elements()->IsFixedArray()) {
1057 DCHECK(object->elements()->length() == 0);
1058 break;
1059 }
1060 Handle<FixedDoubleArray> elements(
1061 FixedDoubleArray::cast(object->elements()));
1062 uint32_t length = static_cast<uint32_t>(elements->length());
1063 if (range < length) length = range;
1064 for (uint32_t i = 0; i < length; i++) {
1065 if (!elements->is_the_hole(i)) {
1066 indices->Add(i);
1067 }
1068 }
1069 break;
1070 }
1071 case DICTIONARY_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001072 DisallowHeapAllocation no_gc;
1073 SeededNumberDictionary* dict =
1074 SeededNumberDictionary::cast(object->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 uint32_t capacity = dict->Capacity();
Ben Murdochda12d292016-06-02 14:46:10 +01001076 Heap* heap = isolate->heap();
1077 Object* undefined = heap->undefined_value();
1078 Object* the_hole = heap->the_hole_value();
1079 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
1080 Object* k = dict->KeyAt(j);
1081 if (k == undefined) continue;
1082 if (k == the_hole) continue;
1083 DCHECK(k->IsNumber());
1084 uint32_t index = static_cast<uint32_t>(k->Number());
1085 if (index < range) {
1086 indices->Add(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087 }
Ben Murdochda12d292016-06-02 14:46:10 +01001088 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001089 break;
1090 }
1091#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1092
1093 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1094#undef TYPED_ARRAY_CASE
1095 {
1096 uint32_t length = static_cast<uint32_t>(
1097 FixedArrayBase::cast(object->elements())->length());
1098 if (range <= length) {
1099 length = range;
1100 // We will add all indices, so we might as well clear it first
1101 // and avoid duplicates.
1102 indices->Clear();
1103 }
1104 for (uint32_t i = 0; i < length; i++) {
1105 indices->Add(i);
1106 }
1107 if (length == range) return; // All indices accounted for already.
1108 break;
1109 }
1110 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1111 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1112 ElementsAccessor* accessor = object->GetElementsAccessor();
1113 for (uint32_t i = 0; i < range; i++) {
1114 if (accessor->HasElement(object, i)) {
1115 indices->Add(i);
1116 }
1117 }
1118 break;
1119 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001120 case FAST_STRING_WRAPPER_ELEMENTS:
1121 case SLOW_STRING_WRAPPER_ELEMENTS: {
1122 DCHECK(object->IsJSValue());
1123 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
1124 DCHECK(js_value->value()->IsString());
1125 Handle<String> string(String::cast(js_value->value()), isolate);
1126 uint32_t length = static_cast<uint32_t>(string->length());
1127 uint32_t i = 0;
1128 uint32_t limit = Min(length, range);
1129 for (; i < limit; i++) {
1130 indices->Add(i);
1131 }
1132 ElementsAccessor* accessor = object->GetElementsAccessor();
1133 for (; i < range; i++) {
1134 if (accessor->HasElement(object, i)) {
1135 indices->Add(i);
1136 }
1137 }
1138 break;
1139 }
1140 case NO_ELEMENTS:
1141 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142 }
1143
1144 PrototypeIterator iter(isolate, object);
1145 if (!iter.IsAtEnd()) {
1146 // The prototype will usually have no inherited element indices,
1147 // but we have to check.
1148 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
1149 indices);
1150 }
1151}
1152
1153
1154bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
1155 uint32_t length, ArrayConcatVisitor* visitor) {
Ben Murdochda12d292016-06-02 14:46:10 +01001156 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, i = 0, i, i < length, ++i, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
1158 if (!maybe.IsJust()) return false;
1159 if (maybe.FromJust()) {
1160 Handle<Object> element_value;
Ben Murdochda12d292016-06-02 14:46:10 +01001161 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1162 isolate, element_value, JSReceiver::GetElement(isolate, receiver, i),
1163 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001164 if (!visitor->visit(i, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165 }
Ben Murdochda12d292016-06-02 14:46:10 +01001166 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001167 visitor->increase_index_offset(length);
1168 return true;
1169}
1170
1171
1172/**
1173 * A helper function that visits "array" elements of a JSReceiver in numerical
1174 * order.
1175 *
1176 * The visitor argument called for each existing element in the array
1177 * with the element index and the element's value.
1178 * Afterwards it increments the base-index of the visitor by the array
1179 * length.
1180 * Returns false if any access threw an exception, otherwise true.
1181 */
1182bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1183 ArrayConcatVisitor* visitor) {
1184 uint32_t length = 0;
1185
1186 if (receiver->IsJSArray()) {
1187 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
1188 length = static_cast<uint32_t>(array->length()->Number());
1189 } else {
1190 Handle<Object> val;
1191 Handle<Object> key = isolate->factory()->length_string();
1192 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1193 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
1194 false);
1195 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
1196 Object::ToLength(isolate, val), false);
1197 // TODO(caitp): Support larger element indexes (up to 2^53-1).
1198 if (!val->ToUint32(&length)) {
1199 length = 0;
1200 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001201 // TODO(cbruni): handle other element kind as well
1202 return IterateElementsSlow(isolate, receiver, length, visitor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001203 }
1204
Ben Murdoch097c5b22016-05-18 11:27:45 +01001205 if (!HasOnlySimpleElements(isolate, *receiver)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 return IterateElementsSlow(isolate, receiver, length, visitor);
1207 }
1208 Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1209
1210 switch (array->GetElementsKind()) {
1211 case FAST_SMI_ELEMENTS:
1212 case FAST_ELEMENTS:
1213 case FAST_HOLEY_SMI_ELEMENTS:
1214 case FAST_HOLEY_ELEMENTS: {
1215 // Run through the elements FixedArray and use HasElement and GetElement
1216 // to check the prototype for missing elements.
1217 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1218 int fast_length = static_cast<int>(length);
Ben Murdochda12d292016-06-02 14:46:10 +01001219 DCHECK(fast_length <= elements->length());
1220 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 Handle<Object> element_value(elements->get(j), isolate);
1222 if (!element_value->IsTheHole()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001223 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224 } else {
1225 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1226 if (!maybe.IsJust()) return false;
1227 if (maybe.FromJust()) {
1228 // Call GetElement on array, not its prototype, or getters won't
1229 // have the correct receiver.
1230 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001231 isolate, element_value,
1232 JSReceiver::GetElement(isolate, array, j), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001233 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 }
1235 }
Ben Murdochda12d292016-06-02 14:46:10 +01001236 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237 break;
1238 }
1239 case FAST_HOLEY_DOUBLE_ELEMENTS:
1240 case FAST_DOUBLE_ELEMENTS: {
1241 // Empty array is FixedArray but not FixedDoubleArray.
1242 if (length == 0) break;
1243 // Run through the elements FixedArray and use HasElement and GetElement
1244 // to check the prototype for missing elements.
1245 if (array->elements()->IsFixedArray()) {
1246 DCHECK(array->elements()->length() == 0);
1247 break;
1248 }
1249 Handle<FixedDoubleArray> elements(
1250 FixedDoubleArray::cast(array->elements()));
1251 int fast_length = static_cast<int>(length);
1252 DCHECK(fast_length <= elements->length());
Ben Murdochda12d292016-06-02 14:46:10 +01001253 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 if (!elements->is_the_hole(j)) {
1255 double double_value = elements->get_scalar(j);
1256 Handle<Object> element_value =
1257 isolate->factory()->NewNumber(double_value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001258 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259 } else {
1260 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1261 if (!maybe.IsJust()) return false;
1262 if (maybe.FromJust()) {
1263 // Call GetElement on array, not its prototype, or getters won't
1264 // have the correct receiver.
1265 Handle<Object> element_value;
1266 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001267 isolate, element_value,
1268 JSReceiver::GetElement(isolate, array, j), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001269 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 }
1271 }
Ben Murdochda12d292016-06-02 14:46:10 +01001272 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001273 break;
1274 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001275
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 case DICTIONARY_ELEMENTS: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001277 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1278 List<uint32_t> indices(dict->Capacity() / 2);
1279 // Collect all indices in the object and the prototypes less
1280 // than length. This might introduce duplicates in the indices list.
1281 CollectElementIndices(array, length, &indices);
1282 indices.Sort(&compareUInt32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 int n = indices.length();
Ben Murdochda12d292016-06-02 14:46:10 +01001284 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < n, (void)0, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001285 uint32_t index = indices[j];
1286 Handle<Object> element;
1287 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001288 isolate, element, JSReceiver::GetElement(isolate, array, index),
1289 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001290 if (!visitor->visit(index, element)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 // Skip to next different index (i.e., omit duplicates).
1292 do {
1293 j++;
1294 } while (j < n && indices[j] == index);
Ben Murdochda12d292016-06-02 14:46:10 +01001295 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001296 break;
1297 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1299 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001300 FOR_WITH_HANDLE_SCOPE(
1301 isolate, uint32_t, index = 0, index, index < length, index++, {
1302 Handle<Object> element;
1303 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1304 isolate, element, JSReceiver::GetElement(isolate, array, index),
1305 false);
1306 if (!visitor->visit(index, element)) return false;
1307 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001308 break;
1309 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001310 case NO_ELEMENTS:
1311 break;
1312#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1313 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1314#undef TYPED_ARRAY_CASE
1315 return IterateElementsSlow(isolate, receiver, length, visitor);
1316 case FAST_STRING_WRAPPER_ELEMENTS:
1317 case SLOW_STRING_WRAPPER_ELEMENTS:
1318 // |array| is guaranteed to be an array or typed array.
1319 UNREACHABLE();
1320 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 }
1322 visitor->increase_index_offset(length);
1323 return true;
1324}
1325
1326
1327bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1329 Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1330 return maybe.FromMaybe(false);
1331}
1332
1333
1334static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1335 HandleScope handle_scope(isolate);
1336 if (!obj->IsJSReceiver()) return Just(false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001337 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1338 Handle<Object> value;
1339 MaybeHandle<Object> maybeValue =
1340 i::Runtime::GetObjectProperty(isolate, obj, key);
1341 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1342 if (!value->IsUndefined()) return Just(value->BooleanValue());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 return Object::IsArray(obj);
1344}
1345
1346
Ben Murdoch097c5b22016-05-18 11:27:45 +01001347Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
1348 Isolate* isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001349 int argument_count = args->length();
1350
Ben Murdoch097c5b22016-05-18 11:27:45 +01001351 bool is_array_species = *species == isolate->context()->array_function();
1352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001353 // Pass 1: estimate the length and number of elements of the result.
1354 // The actual length can be larger if any of the arguments have getters
1355 // that mutate other arguments (but will otherwise be precise).
1356 // The number of elements is precise if there are no inherited elements.
1357
1358 ElementsKind kind = FAST_SMI_ELEMENTS;
1359
1360 uint32_t estimate_result_length = 0;
1361 uint32_t estimate_nof_elements = 0;
Ben Murdochda12d292016-06-02 14:46:10 +01001362 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < argument_count, i++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 Handle<Object> obj((*args)[i], isolate);
1364 uint32_t length_estimate;
1365 uint32_t element_estimate;
1366 if (obj->IsJSArray()) {
1367 Handle<JSArray> array(Handle<JSArray>::cast(obj));
1368 length_estimate = static_cast<uint32_t>(array->length()->Number());
1369 if (length_estimate != 0) {
1370 ElementsKind array_kind =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001371 GetPackedElementsKind(array->GetElementsKind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001372 kind = GetMoreGeneralElementsKind(kind, array_kind);
1373 }
1374 element_estimate = EstimateElementCount(array);
1375 } else {
1376 if (obj->IsHeapObject()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001377 kind = GetMoreGeneralElementsKind(
1378 kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001379 }
1380 length_estimate = 1;
1381 element_estimate = 1;
1382 }
1383 // Avoid overflows by capping at kMaxElementCount.
1384 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1385 estimate_result_length = JSObject::kMaxElementCount;
1386 } else {
1387 estimate_result_length += length_estimate;
1388 }
1389 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1390 estimate_nof_elements = JSObject::kMaxElementCount;
1391 } else {
1392 estimate_nof_elements += element_estimate;
1393 }
Ben Murdochda12d292016-06-02 14:46:10 +01001394 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001395
1396 // If estimated number of elements is more than half of length, a
1397 // fixed array (fast case) is more time and space-efficient than a
1398 // dictionary.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001399 bool fast_case =
1400 is_array_species && (estimate_nof_elements * 2) >= estimate_result_length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401
1402 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1403 Handle<FixedArrayBase> storage =
1404 isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1405 int j = 0;
1406 bool failure = false;
1407 if (estimate_result_length > 0) {
1408 Handle<FixedDoubleArray> double_storage =
1409 Handle<FixedDoubleArray>::cast(storage);
1410 for (int i = 0; i < argument_count; i++) {
1411 Handle<Object> obj((*args)[i], isolate);
1412 if (obj->IsSmi()) {
1413 double_storage->set(j, Smi::cast(*obj)->value());
1414 j++;
1415 } else if (obj->IsNumber()) {
1416 double_storage->set(j, obj->Number());
1417 j++;
1418 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001419 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001420 JSArray* array = JSArray::cast(*obj);
1421 uint32_t length = static_cast<uint32_t>(array->length()->Number());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001422 switch (array->GetElementsKind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001423 case FAST_HOLEY_DOUBLE_ELEMENTS:
1424 case FAST_DOUBLE_ELEMENTS: {
1425 // Empty array is FixedArray but not FixedDoubleArray.
1426 if (length == 0) break;
1427 FixedDoubleArray* elements =
1428 FixedDoubleArray::cast(array->elements());
1429 for (uint32_t i = 0; i < length; i++) {
1430 if (elements->is_the_hole(i)) {
1431 // TODO(jkummerow/verwaest): We could be a bit more clever
1432 // here: Check if there are no elements/getters on the
1433 // prototype chain, and if so, allow creation of a holey
1434 // result array.
1435 // Same thing below (holey smi case).
1436 failure = true;
1437 break;
1438 }
1439 double double_value = elements->get_scalar(i);
1440 double_storage->set(j, double_value);
1441 j++;
1442 }
1443 break;
1444 }
1445 case FAST_HOLEY_SMI_ELEMENTS:
1446 case FAST_SMI_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001447 Object* the_hole = isolate->heap()->the_hole_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001448 FixedArray* elements(FixedArray::cast(array->elements()));
1449 for (uint32_t i = 0; i < length; i++) {
1450 Object* element = elements->get(i);
Ben Murdochda12d292016-06-02 14:46:10 +01001451 if (element == the_hole) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452 failure = true;
1453 break;
1454 }
1455 int32_t int_value = Smi::cast(element)->value();
1456 double_storage->set(j, int_value);
1457 j++;
1458 }
1459 break;
1460 }
1461 case FAST_HOLEY_ELEMENTS:
1462 case FAST_ELEMENTS:
1463 case DICTIONARY_ELEMENTS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001464 case NO_ELEMENTS:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001465 DCHECK_EQ(0u, length);
1466 break;
1467 default:
1468 UNREACHABLE();
1469 }
1470 }
1471 if (failure) break;
1472 }
1473 }
1474 if (!failure) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001475 return *isolate->factory()->NewJSArrayWithElements(storage, kind, j);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001476 }
1477 // In case of failure, fall through.
1478 }
1479
Ben Murdoch097c5b22016-05-18 11:27:45 +01001480 Handle<Object> storage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001481 if (fast_case) {
1482 // The backing storage array must have non-existing elements to preserve
1483 // holes across concat operations.
1484 storage =
1485 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001486 } else if (is_array_species) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001487 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1488 uint32_t at_least_space_for =
1489 estimate_nof_elements + (estimate_nof_elements >> 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001490 storage = SeededNumberDictionary::New(isolate, at_least_space_for);
1491 } else {
1492 DCHECK(species->IsConstructor());
1493 Handle<Object> length(Smi::FromInt(0), isolate);
1494 Handle<Object> storage_object;
1495 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1496 isolate, storage_object,
1497 Execution::New(isolate, species, species, 1, &length));
1498 storage = storage_object;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001499 }
1500
1501 ArrayConcatVisitor visitor(isolate, storage, fast_case);
1502
1503 for (int i = 0; i < argument_count; i++) {
1504 Handle<Object> obj((*args)[i], isolate);
1505 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1506 MAYBE_RETURN(spreadable, isolate->heap()->exception());
1507 if (spreadable.FromJust()) {
1508 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1509 if (!IterateElements(isolate, object, &visitor)) {
1510 return isolate->heap()->exception();
1511 }
1512 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001513 if (!visitor.visit(0, obj)) return isolate->heap()->exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001514 visitor.increase_index_offset(1);
1515 }
1516 }
1517
1518 if (visitor.exceeds_array_limit()) {
1519 THROW_NEW_ERROR_RETURN_FAILURE(
1520 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1521 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001522
1523 if (is_array_species) {
1524 return *visitor.ToArray();
1525 } else {
1526 return *visitor.storage_jsreceiver();
1527 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528}
1529
1530
1531MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
Ben Murdochda12d292016-06-02 14:46:10 +01001532 // We shouldn't overflow when adding another len.
1533 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1534 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1535 STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt);
1536 USE(kHalfOfMaxInt);
1537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001538 int n_arguments = args->length();
Steve Block6ded16b2010-05-10 14:33:55 +01001539 int result_len = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 {
1541 DisallowHeapAllocation no_gc;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001542 // Iterate through all the arguments performing checks
1543 // and calculating total length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544 for (int i = 0; i < n_arguments; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001545 Object* arg = (*args)[i];
1546 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
Ben Murdochda12d292016-06-02 14:46:10 +01001547 if (!JSObject::cast(arg)->HasFastElements()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001548 return MaybeHandle<JSArray>();
1549 }
Ben Murdochda12d292016-06-02 14:46:10 +01001550 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001551 return MaybeHandle<JSArray>();
1552 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001553 Handle<JSArray> array(JSArray::cast(arg), isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001554 if (HasConcatSpreadableModifier(isolate, array)) {
1555 return MaybeHandle<JSArray>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001556 }
Ben Murdochda12d292016-06-02 14:46:10 +01001557 // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't
1558 // overflow.
1559 result_len += Smi::cast(array->length())->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001560 DCHECK(result_len >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001561 // Throw an Error if we overflow the FixedArray limits
Ben Murdochda12d292016-06-02 14:46:10 +01001562 if (FixedDoubleArray::kMaxLength < result_len ||
1563 FixedArray::kMaxLength < result_len) {
1564 AllowHeapAllocation allow_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001565 THROW_NEW_ERROR(isolate,
1566 NewRangeError(MessageTemplate::kInvalidArrayLength),
1567 JSArray);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001568 }
Steve Block6ded16b2010-05-10 14:33:55 +01001569 }
Steve Block6ded16b2010-05-10 14:33:55 +01001570 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001571 return ElementsAccessor::Concat(isolate, args, n_arguments);
1572}
Steve Block6ded16b2010-05-10 14:33:55 +01001573
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001574} // namespace
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001575
Ben Murdoch097c5b22016-05-18 11:27:45 +01001576
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577// ES6 22.1.3.1 Array.prototype.concat
1578BUILTIN(ArrayConcat) {
1579 HandleScope scope(isolate);
1580
Ben Murdoch097c5b22016-05-18 11:27:45 +01001581 Handle<Object> receiver = args.receiver();
1582 // TODO(bmeurer): Do we really care about the exact exception message here?
1583 if (receiver->IsNull() || receiver->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 THROW_NEW_ERROR_RETURN_FAILURE(
1585 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1586 isolate->factory()->NewStringFromAsciiChecked(
1587 "Array.prototype.concat")));
1588 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001589 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1590 isolate, receiver, Object::ToObject(isolate, args.receiver()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001591 args[0] = *receiver;
1592
1593 Handle<JSArray> result_array;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001594
Ben Murdochda12d292016-06-02 14:46:10 +01001595 // Avoid a real species read to avoid extra lookups to the array constructor
1596 if (V8_LIKELY(receiver->IsJSArray() &&
1597 Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) &&
1598 isolate->IsArraySpeciesLookupChainIntact())) {
1599 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1600 return *result_array;
1601 }
1602 if (isolate->has_pending_exception()) return isolate->heap()->exception();
1603 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001604 // Reading @@species happens before anything else with a side effect, so
1605 // we can do it here to determine whether to take the fast path.
1606 Handle<Object> species;
1607 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1608 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
Ben Murdochda12d292016-06-02 14:46:10 +01001609 if (*species == *isolate->array_function()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001610 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1611 return *result_array;
1612 }
1613 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001614 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001615 return Slow_ArrayConcat(&args, species, isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616}
1617
1618
1619// ES6 22.1.2.2 Array.isArray
1620BUILTIN(ArrayIsArray) {
1621 HandleScope scope(isolate);
1622 DCHECK_EQ(2, args.length());
1623 Handle<Object> object = args.at<Object>(1);
1624 Maybe<bool> result = Object::IsArray(object);
1625 MAYBE_RETURN(result, isolate->heap()->exception());
1626 return *isolate->factory()->ToBoolean(result.FromJust());
1627}
1628
Ben Murdoch097c5b22016-05-18 11:27:45 +01001629namespace {
1630
1631MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
1632 Handle<Object> next_source) {
1633 // Non-empty strings are the only non-JSReceivers that need to be handled
1634 // explicitly by Object.assign.
1635 if (!next_source->IsJSReceiver()) {
1636 return Just(!next_source->IsString() ||
1637 String::cast(*next_source)->length() == 0);
1638 }
1639
1640 Isolate* isolate = to->GetIsolate();
1641 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
1642
1643 if (!map->IsJSObjectMap()) return Just(false);
1644 if (!map->OnlyHasSimpleProperties()) return Just(false);
1645
1646 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
1647 if (from->elements() != isolate->heap()->empty_fixed_array()) {
1648 return Just(false);
1649 }
1650
1651 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
1652 int length = map->NumberOfOwnDescriptors();
1653
1654 bool stable = true;
1655
1656 for (int i = 0; i < length; i++) {
1657 Handle<Name> next_key(descriptors->GetKey(i), isolate);
1658 Handle<Object> prop_value;
1659 // Directly decode from the descriptor array if |from| did not change shape.
1660 if (stable) {
1661 PropertyDetails details = descriptors->GetDetails(i);
1662 if (!details.IsEnumerable()) continue;
1663 if (details.kind() == kData) {
1664 if (details.location() == kDescriptor) {
1665 prop_value = handle(descriptors->GetValue(i), isolate);
1666 } else {
1667 Representation representation = details.representation();
1668 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
1669 prop_value = JSObject::FastPropertyAt(from, representation, index);
1670 }
1671 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001672 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1673 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
1674 Nothing<bool>());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001675 stable = from->map() == *map;
1676 }
1677 } else {
1678 // If the map did change, do a slower lookup. We are still guaranteed that
1679 // the object has a simple shape, and that the key is a name.
Ben Murdochda12d292016-06-02 14:46:10 +01001680 LookupIterator it(from, next_key, from,
1681 LookupIterator::OWN_SKIP_INTERCEPTOR);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001682 if (!it.IsFound()) continue;
1683 DCHECK(it.state() == LookupIterator::DATA ||
1684 it.state() == LookupIterator::ACCESSOR);
1685 if (!it.IsEnumerable()) continue;
1686 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1687 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
1688 }
Ben Murdochda12d292016-06-02 14:46:10 +01001689 LookupIterator it(to, next_key, to);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001690 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
1691 Maybe<bool> result = Object::SetProperty(
1692 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
1693 if (result.IsNothing()) return result;
1694 if (stable && call_to_js) stable = from->map() == *map;
1695 }
1696
1697 return Just(true);
1698}
1699
1700} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001701
1702// ES6 19.1.2.1 Object.assign
1703BUILTIN(ObjectAssign) {
1704 HandleScope scope(isolate);
1705 Handle<Object> target = args.atOrUndefined(isolate, 1);
1706
1707 // 1. Let to be ? ToObject(target).
1708 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001709 Object::ToObject(isolate, target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001710 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
1711 // 2. If only one argument was passed, return to.
1712 if (args.length() == 2) return *to;
1713 // 3. Let sources be the List of argument values starting with the
1714 // second argument.
1715 // 4. For each element nextSource of sources, in ascending index order,
1716 for (int i = 2; i < args.length(); ++i) {
1717 Handle<Object> next_source = args.at<Object>(i);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001718 Maybe<bool> fast_assign = FastAssign(to, next_source);
1719 if (fast_assign.IsNothing()) return isolate->heap()->exception();
1720 if (fast_assign.FromJust()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001721 // 4a. If nextSource is undefined or null, let keys be an empty List.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001722 // 4b. Else,
1723 // 4b i. Let from be ToObject(nextSource).
Ben Murdoch097c5b22016-05-18 11:27:45 +01001724 // Only non-empty strings and JSReceivers have enumerable properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001725 Handle<JSReceiver> from =
1726 Object::ToObject(isolate, next_source).ToHandleChecked();
1727 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
1728 Handle<FixedArray> keys;
1729 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001730 isolate, keys,
1731 JSReceiver::GetKeys(from, OWN_ONLY, ALL_PROPERTIES, KEEP_NUMBERS));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001732 // 4c. Repeat for each element nextKey of keys in List order,
1733 for (int j = 0; j < keys->length(); ++j) {
1734 Handle<Object> next_key(keys->get(j), isolate);
1735 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
1736 PropertyDescriptor desc;
1737 Maybe<bool> found =
1738 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
1739 if (found.IsNothing()) return isolate->heap()->exception();
1740 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
1741 if (found.FromJust() && desc.enumerable()) {
1742 // 4c ii 1. Let propValue be ? Get(from, nextKey).
1743 Handle<Object> prop_value;
1744 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1745 isolate, prop_value,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001746 Runtime::GetObjectProperty(isolate, from, next_key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001747 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
1748 Handle<Object> status;
1749 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1750 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
1751 prop_value, STRICT));
1752 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001753 }
Steve Block6ded16b2010-05-10 14:33:55 +01001754 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 // 5. Return to.
1756 return *to;
1757}
Steve Block6ded16b2010-05-10 14:33:55 +01001758
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001759
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001760// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
1761BUILTIN(ObjectCreate) {
1762 HandleScope scope(isolate);
1763 Handle<Object> prototype = args.atOrUndefined(isolate, 1);
1764 if (!prototype->IsNull() && !prototype->IsJSReceiver()) {
1765 THROW_NEW_ERROR_RETURN_FAILURE(
1766 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
1767 }
1768
1769 // Generate the map with the specified {prototype} based on the Object
1770 // function's initial map from the current native context.
1771 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1772 // slack tracking for Object.create.
1773 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
1774 isolate);
1775 if (map->prototype() != *prototype) {
1776 map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
1777 }
1778
1779 // Actually allocate the object.
1780 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
1781
1782 // Define the properties if properties was specified and is not undefined.
1783 Handle<Object> properties = args.atOrUndefined(isolate, 2);
1784 if (!properties->IsUndefined()) {
1785 RETURN_FAILURE_ON_EXCEPTION(
1786 isolate, JSReceiver::DefineProperties(isolate, object, properties));
1787 }
1788
1789 return *object;
1790}
1791
1792
1793// ES6 section 19.1.2.5 Object.freeze ( O )
1794BUILTIN(ObjectFreeze) {
1795 HandleScope scope(isolate);
1796 Handle<Object> object = args.atOrUndefined(isolate, 1);
1797 if (object->IsJSReceiver()) {
1798 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1799 FROZEN, Object::THROW_ON_ERROR),
1800 isolate->heap()->exception());
1801 }
1802 return *object;
1803}
1804
1805
Ben Murdoch097c5b22016-05-18 11:27:45 +01001806// ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
1807BUILTIN(ObjectGetOwnPropertyDescriptor) {
1808 HandleScope scope(isolate);
1809 // 1. Let obj be ? ToObject(O).
1810 Handle<Object> object = args.atOrUndefined(isolate, 1);
1811 Handle<JSReceiver> receiver;
1812 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1813 Object::ToObject(isolate, object));
1814 // 2. Let key be ? ToPropertyKey(P).
1815 Handle<Object> property = args.atOrUndefined(isolate, 2);
1816 Handle<Name> key;
1817 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1818 Object::ToName(isolate, property));
1819 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
1820 PropertyDescriptor desc;
1821 Maybe<bool> found =
1822 JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
1823 MAYBE_RETURN(found, isolate->heap()->exception());
1824 // 4. Return FromPropertyDescriptor(desc).
1825 if (!found.FromJust()) return isolate->heap()->undefined_value();
1826 return *desc.ToObject(isolate);
1827}
1828
1829
1830namespace {
1831
1832Object* GetOwnPropertyKeys(Isolate* isolate,
1833 BuiltinArguments<BuiltinExtraArguments::kNone> args,
1834 PropertyFilter filter) {
1835 HandleScope scope(isolate);
1836 Handle<Object> object = args.atOrUndefined(isolate, 1);
1837 Handle<JSReceiver> receiver;
1838 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1839 Object::ToObject(isolate, object));
1840 Handle<FixedArray> keys;
1841 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1842 isolate, keys,
1843 JSReceiver::GetKeys(receiver, OWN_ONLY, filter, CONVERT_TO_STRING));
1844 return *isolate->factory()->NewJSArrayWithElements(keys);
1845}
1846
1847} // namespace
1848
1849
1850// ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
1851BUILTIN(ObjectGetOwnPropertyNames) {
1852 return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
1853}
1854
1855
1856// ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
1857BUILTIN(ObjectGetOwnPropertySymbols) {
1858 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
1859}
1860
1861
1862// ES#sec-object.is Object.is ( value1, value2 )
1863BUILTIN(ObjectIs) {
1864 SealHandleScope shs(isolate);
1865 DCHECK_EQ(3, args.length());
1866 Handle<Object> value1 = args.at<Object>(1);
1867 Handle<Object> value2 = args.at<Object>(2);
1868 return isolate->heap()->ToBoolean(value1->SameValue(*value2));
1869}
1870
1871
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001872// ES6 section 19.1.2.11 Object.isExtensible ( O )
1873BUILTIN(ObjectIsExtensible) {
1874 HandleScope scope(isolate);
1875 Handle<Object> object = args.atOrUndefined(isolate, 1);
1876 Maybe<bool> result =
1877 object->IsJSReceiver()
1878 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
1879 : Just(false);
1880 MAYBE_RETURN(result, isolate->heap()->exception());
1881 return isolate->heap()->ToBoolean(result.FromJust());
1882}
1883
1884
1885// ES6 section 19.1.2.12 Object.isFrozen ( O )
1886BUILTIN(ObjectIsFrozen) {
1887 HandleScope scope(isolate);
1888 Handle<Object> object = args.atOrUndefined(isolate, 1);
1889 Maybe<bool> result = object->IsJSReceiver()
1890 ? JSReceiver::TestIntegrityLevel(
1891 Handle<JSReceiver>::cast(object), FROZEN)
1892 : Just(true);
1893 MAYBE_RETURN(result, isolate->heap()->exception());
1894 return isolate->heap()->ToBoolean(result.FromJust());
1895}
1896
1897
1898// ES6 section 19.1.2.13 Object.isSealed ( O )
1899BUILTIN(ObjectIsSealed) {
1900 HandleScope scope(isolate);
1901 Handle<Object> object = args.atOrUndefined(isolate, 1);
1902 Maybe<bool> result = object->IsJSReceiver()
1903 ? JSReceiver::TestIntegrityLevel(
1904 Handle<JSReceiver>::cast(object), SEALED)
1905 : Just(true);
1906 MAYBE_RETURN(result, isolate->heap()->exception());
1907 return isolate->heap()->ToBoolean(result.FromJust());
1908}
1909
1910
1911// ES6 section 19.1.2.14 Object.keys ( O )
1912BUILTIN(ObjectKeys) {
1913 HandleScope scope(isolate);
1914 Handle<Object> object = args.atOrUndefined(isolate, 1);
1915 Handle<JSReceiver> receiver;
1916 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001917 Object::ToObject(isolate, object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001918
Ben Murdoch097c5b22016-05-18 11:27:45 +01001919 Handle<FixedArray> keys;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001920 int enum_length = receiver->map()->EnumLength();
1921 if (enum_length != kInvalidEnumCacheSentinel &&
1922 JSObject::cast(*receiver)->elements() ==
1923 isolate->heap()->empty_fixed_array()) {
1924 DCHECK(receiver->IsJSObject());
1925 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
1926 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001927 DCHECK(!receiver->map()->has_hidden_prototype());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001928 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
1929 if (enum_length == 0) {
1930 keys = isolate->factory()->empty_fixed_array();
1931 } else {
1932 Handle<FixedArray> cache(
1933 receiver->map()->instance_descriptors()->GetEnumCache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001934 keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001935 }
1936 } else {
1937 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1938 isolate, keys,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001939 JSReceiver::GetKeys(receiver, OWN_ONLY, ENUMERABLE_STRINGS,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001940 CONVERT_TO_STRING));
1941 }
1942 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
1943}
1944
Ben Murdoch097c5b22016-05-18 11:27:45 +01001945BUILTIN(ObjectValues) {
1946 HandleScope scope(isolate);
1947 Handle<Object> object = args.atOrUndefined(isolate, 1);
1948 Handle<JSReceiver> receiver;
1949 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1950 Object::ToObject(isolate, object));
1951 Handle<FixedArray> values;
1952 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1953 isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
1954 return *isolate->factory()->NewJSArrayWithElements(values);
1955}
1956
1957
1958BUILTIN(ObjectEntries) {
1959 HandleScope scope(isolate);
1960 Handle<Object> object = args.atOrUndefined(isolate, 1);
1961 Handle<JSReceiver> receiver;
1962 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1963 Object::ToObject(isolate, object));
1964 Handle<FixedArray> entries;
1965 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1966 isolate, entries,
1967 JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
1968 return *isolate->factory()->NewJSArrayWithElements(entries);
1969}
1970
1971BUILTIN(ObjectGetOwnPropertyDescriptors) {
1972 HandleScope scope(isolate);
1973 Handle<Object> object = args.atOrUndefined(isolate, 1);
1974 Handle<Object> undefined = isolate->factory()->undefined_value();
1975
1976 Handle<JSReceiver> receiver;
1977 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1978 Object::ToObject(isolate, object));
1979
1980 Handle<FixedArray> keys;
1981 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1982 isolate, keys, JSReceiver::GetKeys(receiver, OWN_ONLY, ALL_PROPERTIES,
1983 CONVERT_TO_STRING));
1984
Ben Murdochda12d292016-06-02 14:46:10 +01001985 Handle<JSObject> descriptors =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001986 isolate->factory()->NewJSObject(isolate->object_function());
1987
1988 for (int i = 0; i < keys->length(); ++i) {
1989 Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
1990 PropertyDescriptor descriptor;
1991 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
1992 isolate, receiver, key, &descriptor);
1993 MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
1994
1995 Handle<Object> from_descriptor = did_get_descriptor.FromJust()
1996 ? descriptor.ToObject(isolate)
1997 : undefined;
1998
1999 LookupIterator it = LookupIterator::PropertyOrElement(
Ben Murdochda12d292016-06-02 14:46:10 +01002000 isolate, descriptors, key, descriptors, LookupIterator::OWN);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002001 Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
2002 Object::DONT_THROW);
2003 CHECK(success.FromJust());
2004 }
2005
2006 return *descriptors;
2007}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002008
2009// ES6 section 19.1.2.15 Object.preventExtensions ( O )
2010BUILTIN(ObjectPreventExtensions) {
2011 HandleScope scope(isolate);
2012 Handle<Object> object = args.atOrUndefined(isolate, 1);
2013 if (object->IsJSReceiver()) {
2014 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
2015 Object::THROW_ON_ERROR),
2016 isolate->heap()->exception());
2017 }
2018 return *object;
2019}
2020
2021
2022// ES6 section 19.1.2.17 Object.seal ( O )
2023BUILTIN(ObjectSeal) {
2024 HandleScope scope(isolate);
2025 Handle<Object> object = args.atOrUndefined(isolate, 1);
2026 if (object->IsJSReceiver()) {
2027 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
2028 SEALED, Object::THROW_ON_ERROR),
2029 isolate->heap()->exception());
2030 }
2031 return *object;
2032}
2033
2034
2035namespace {
2036
2037bool CodeGenerationFromStringsAllowed(Isolate* isolate,
2038 Handle<Context> context) {
2039 DCHECK(context->allow_code_gen_from_strings()->IsFalse());
2040 // Check with callback if set.
2041 AllowCodeGenerationFromStringsCallback callback =
2042 isolate->allow_code_gen_callback();
2043 if (callback == NULL) {
2044 // No callback set and code generation disallowed.
2045 return false;
2046 } else {
2047 // Callback set. Let it decide if code generation is allowed.
2048 VMState<EXTERNAL> state(isolate);
2049 return callback(v8::Utils::ToLocal(context));
2050 }
2051}
2052
2053
2054MaybeHandle<JSFunction> CompileString(Handle<Context> context,
2055 Handle<String> source,
2056 ParseRestriction restriction) {
2057 Isolate* const isolate = context->GetIsolate();
2058 Handle<Context> native_context(context->native_context(), isolate);
2059
2060 // Check if native context allows code generation from
2061 // strings. Throw an exception if it doesn't.
2062 if (native_context->allow_code_gen_from_strings()->IsFalse() &&
2063 !CodeGenerationFromStringsAllowed(isolate, native_context)) {
2064 Handle<Object> error_message =
2065 native_context->ErrorMessageForCodeGenerationFromStrings();
2066 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
2067 error_message),
2068 JSFunction);
2069 }
2070
2071 // Compile source string in the native context.
2072 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared(),
2073 isolate);
2074 return Compiler::GetFunctionFromEval(source, outer_info, native_context,
2075 SLOPPY, restriction,
2076 RelocInfo::kNoPosition);
2077}
2078
2079} // namespace
2080
2081
2082// ES6 section 18.2.1 eval (x)
2083BUILTIN(GlobalEval) {
2084 HandleScope scope(isolate);
2085 Handle<Object> x = args.atOrUndefined(isolate, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002086 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002087 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
2088 if (!x->IsString()) return *x;
2089 Handle<JSFunction> function;
2090 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2091 isolate, function,
2092 CompileString(handle(target->native_context(), isolate),
2093 Handle<String>::cast(x), NO_PARSE_RESTRICTION));
2094 Handle<Object> result;
2095 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2096 isolate, result,
2097 Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
2098 return *result;
2099}
2100
2101
Ben Murdochda12d292016-06-02 14:46:10 +01002102// -----------------------------------------------------------------------------
2103// ES6 section 20.2.2 Function Properties of the Math Object
2104
2105
2106// ES6 section 20.2.2.2 Math.acos ( x )
2107BUILTIN(MathAcos) {
2108 HandleScope scope(isolate);
2109 DCHECK_EQ(2, args.length());
2110 Handle<Object> x = args.at<Object>(1);
2111 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2112 return *isolate->factory()->NewHeapNumber(std::acos(x->Number()));
2113}
2114
2115
2116// ES6 section 20.2.2.4 Math.asin ( x )
2117BUILTIN(MathAsin) {
2118 HandleScope scope(isolate);
2119 DCHECK_EQ(2, args.length());
2120 Handle<Object> x = args.at<Object>(1);
2121 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2122 return *isolate->factory()->NewHeapNumber(std::asin(x->Number()));
2123}
2124
2125
2126// ES6 section 20.2.2.6 Math.atan ( x )
2127BUILTIN(MathAtan) {
2128 HandleScope scope(isolate);
2129 DCHECK_EQ(2, args.length());
2130 Handle<Object> x = args.at<Object>(1);
2131 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2132 return *isolate->factory()->NewHeapNumber(std::atan(x->Number()));
2133}
2134
2135namespace {
2136
2137void Generate_MathRoundingOperation(
2138 compiler::CodeStubAssembler* assembler,
2139 compiler::Node* (compiler::CodeStubAssembler::*float64op)(
2140 compiler::Node*)) {
2141 typedef compiler::CodeStubAssembler::Label Label;
2142 typedef compiler::Node Node;
2143 typedef compiler::CodeStubAssembler::Variable Variable;
2144
2145 Node* context = assembler->Parameter(4);
2146
2147 // We might need to loop once for ToNumber conversion.
2148 Variable var_x(assembler, MachineRepresentation::kTagged);
2149 Label loop(assembler, &var_x);
2150 var_x.Bind(assembler->Parameter(1));
2151 assembler->Goto(&loop);
2152 assembler->Bind(&loop);
2153 {
2154 // Load the current {x} value.
2155 Node* x = var_x.value();
2156
2157 // Check if {x} is a Smi or a HeapObject.
2158 Label if_xissmi(assembler), if_xisnotsmi(assembler);
2159 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2160
2161 assembler->Bind(&if_xissmi);
2162 {
2163 // Nothing to do when {x} is a Smi.
2164 assembler->Return(x);
2165 }
2166
2167 assembler->Bind(&if_xisnotsmi);
2168 {
2169 // Check if {x} is a HeapNumber.
2170 Label if_xisheapnumber(assembler),
2171 if_xisnotheapnumber(assembler, Label::kDeferred);
2172 assembler->Branch(
2173 assembler->WordEqual(assembler->LoadMap(x),
2174 assembler->HeapNumberMapConstant()),
2175 &if_xisheapnumber, &if_xisnotheapnumber);
2176
2177 assembler->Bind(&if_xisheapnumber);
2178 {
2179 Node* x_value = assembler->LoadHeapNumberValue(x);
2180 Node* value = (assembler->*float64op)(x_value);
2181 Node* result = assembler->ChangeFloat64ToTagged(value);
2182 assembler->Return(result);
2183 }
2184
2185 assembler->Bind(&if_xisnotheapnumber);
2186 {
2187 // Need to convert {x} to a Number first.
2188 Callable callable =
2189 CodeFactory::NonNumberToNumber(assembler->isolate());
2190 var_x.Bind(assembler->CallStub(callable, context, x));
2191 assembler->Goto(&loop);
2192 }
2193 }
2194 }
2195}
2196
2197} // namespace
2198
2199// ES6 section 20.2.2.10 Math.ceil ( x )
2200void Builtins::Generate_MathCeil(compiler::CodeStubAssembler* assembler) {
2201 Generate_MathRoundingOperation(assembler,
2202 &compiler::CodeStubAssembler::Float64Ceil);
2203}
2204
2205// ES6 section 20.2.2.11 Math.clz32 ( x )
2206void Builtins::Generate_MathClz32(compiler::CodeStubAssembler* assembler) {
2207 typedef compiler::CodeStubAssembler::Label Label;
2208 typedef compiler::Node Node;
2209 typedef compiler::CodeStubAssembler::Variable Variable;
2210
2211 Node* context = assembler->Parameter(4);
2212
2213 // Shared entry point for the clz32 operation.
2214 Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
2215 Label do_clz32(assembler);
2216
2217 // We might need to loop once for ToNumber conversion.
2218 Variable var_x(assembler, MachineRepresentation::kTagged);
2219 Label loop(assembler, &var_x);
2220 var_x.Bind(assembler->Parameter(1));
2221 assembler->Goto(&loop);
2222 assembler->Bind(&loop);
2223 {
2224 // Load the current {x} value.
2225 Node* x = var_x.value();
2226
2227 // Check if {x} is a Smi or a HeapObject.
2228 Label if_xissmi(assembler), if_xisnotsmi(assembler);
2229 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2230
2231 assembler->Bind(&if_xissmi);
2232 {
2233 var_clz32_x.Bind(assembler->SmiToWord32(x));
2234 assembler->Goto(&do_clz32);
2235 }
2236
2237 assembler->Bind(&if_xisnotsmi);
2238 {
2239 // Check if {x} is a HeapNumber.
2240 Label if_xisheapnumber(assembler),
2241 if_xisnotheapnumber(assembler, Label::kDeferred);
2242 assembler->Branch(
2243 assembler->WordEqual(assembler->LoadMap(x),
2244 assembler->HeapNumberMapConstant()),
2245 &if_xisheapnumber, &if_xisnotheapnumber);
2246
2247 assembler->Bind(&if_xisheapnumber);
2248 {
2249 var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
2250 assembler->Goto(&do_clz32);
2251 }
2252
2253 assembler->Bind(&if_xisnotheapnumber);
2254 {
2255 // Need to convert {x} to a Number first.
2256 Callable callable =
2257 CodeFactory::NonNumberToNumber(assembler->isolate());
2258 var_x.Bind(assembler->CallStub(callable, context, x));
2259 assembler->Goto(&loop);
2260 }
2261 }
2262 }
2263
2264 assembler->Bind(&do_clz32);
2265 {
2266 Node* x_value = var_clz32_x.value();
2267 Node* value = assembler->Word32Clz(x_value);
2268 Node* result = assembler->ChangeInt32ToTagged(value);
2269 assembler->Return(result);
2270 }
2271}
2272
2273// ES6 section 20.2.2.16 Math.floor ( x )
2274void Builtins::Generate_MathFloor(compiler::CodeStubAssembler* assembler) {
2275 Generate_MathRoundingOperation(assembler,
2276 &compiler::CodeStubAssembler::Float64Floor);
2277}
2278
2279// ES6 section 20.2.2.17 Math.fround ( x )
2280BUILTIN(MathFround) {
2281 HandleScope scope(isolate);
2282 DCHECK_EQ(2, args.length());
2283 Handle<Object> x = args.at<Object>(1);
2284 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2285 float x32 = DoubleToFloat32(x->Number());
2286 return *isolate->factory()->NewNumber(x32);
2287}
2288
2289// ES6 section 20.2.2.19 Math.imul ( x, y )
2290BUILTIN(MathImul) {
2291 HandleScope scope(isolate);
2292 DCHECK_EQ(3, args.length());
2293 Handle<Object> x = args.at<Object>(1);
2294 Handle<Object> y = args.at<Object>(2);
2295 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2296 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, y, Object::ToNumber(y));
2297 int product = static_cast<int>(NumberToUint32(*x) * NumberToUint32(*y));
2298 return *isolate->factory()->NewNumberFromInt(product);
2299}
2300
2301// ES6 section 20.2.2.28 Math.round ( x )
2302void Builtins::Generate_MathRound(compiler::CodeStubAssembler* assembler) {
2303 Generate_MathRoundingOperation(assembler,
2304 &compiler::CodeStubAssembler::Float64Round);
2305}
2306
2307// ES6 section 20.2.2.32 Math.sqrt ( x )
2308void Builtins::Generate_MathSqrt(compiler::CodeStubAssembler* assembler) {
2309 using compiler::Node;
2310
2311 Node* x = assembler->Parameter(1);
2312 Node* context = assembler->Parameter(4);
2313 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2314 Node* value = assembler->Float64Sqrt(x_value);
2315 Node* result = assembler->ChangeFloat64ToTagged(value);
2316 assembler->Return(result);
2317}
2318
2319// ES6 section 20.2.2.35 Math.trunc ( x )
2320void Builtins::Generate_MathTrunc(compiler::CodeStubAssembler* assembler) {
2321 Generate_MathRoundingOperation(assembler,
2322 &compiler::CodeStubAssembler::Float64Trunc);
2323}
2324
2325// -----------------------------------------------------------------------------
2326// ES6 section 26.1 The Reflect Object
2327
2328
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002329// ES6 section 26.1.3 Reflect.defineProperty
2330BUILTIN(ReflectDefineProperty) {
2331 HandleScope scope(isolate);
2332 DCHECK_EQ(4, args.length());
2333 Handle<Object> target = args.at<Object>(1);
2334 Handle<Object> key = args.at<Object>(2);
2335 Handle<Object> attributes = args.at<Object>(3);
2336
2337 if (!target->IsJSReceiver()) {
2338 THROW_NEW_ERROR_RETURN_FAILURE(
2339 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2340 isolate->factory()->NewStringFromAsciiChecked(
2341 "Reflect.defineProperty")));
2342 }
2343
2344 Handle<Name> name;
2345 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2346 Object::ToName(isolate, key));
2347
2348 PropertyDescriptor desc;
2349 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
2350 return isolate->heap()->exception();
2351 }
2352
2353 Maybe<bool> result =
2354 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
2355 name, &desc, Object::DONT_THROW);
2356 MAYBE_RETURN(result, isolate->heap()->exception());
2357 return *isolate->factory()->ToBoolean(result.FromJust());
2358}
2359
2360
2361// ES6 section 26.1.4 Reflect.deleteProperty
2362BUILTIN(ReflectDeleteProperty) {
2363 HandleScope scope(isolate);
2364 DCHECK_EQ(3, args.length());
2365 Handle<Object> target = args.at<Object>(1);
2366 Handle<Object> key = args.at<Object>(2);
2367
2368 if (!target->IsJSReceiver()) {
2369 THROW_NEW_ERROR_RETURN_FAILURE(
2370 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2371 isolate->factory()->NewStringFromAsciiChecked(
2372 "Reflect.deleteProperty")));
2373 }
2374
2375 Handle<Name> name;
2376 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2377 Object::ToName(isolate, key));
2378
2379 Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
2380 Handle<JSReceiver>::cast(target), name, SLOPPY);
2381 MAYBE_RETURN(result, isolate->heap()->exception());
2382 return *isolate->factory()->ToBoolean(result.FromJust());
2383}
2384
2385
2386// ES6 section 26.1.6 Reflect.get
2387BUILTIN(ReflectGet) {
2388 HandleScope scope(isolate);
2389 Handle<Object> target = args.atOrUndefined(isolate, 1);
2390 Handle<Object> key = args.atOrUndefined(isolate, 2);
2391 Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
2392
2393 if (!target->IsJSReceiver()) {
2394 THROW_NEW_ERROR_RETURN_FAILURE(
2395 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2396 isolate->factory()->NewStringFromAsciiChecked(
2397 "Reflect.get")));
2398 }
2399
2400 Handle<Name> name;
2401 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2402 Object::ToName(isolate, key));
2403
2404 Handle<Object> result;
2405 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2406 isolate, result, Object::GetPropertyOrElement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002407 receiver, name, Handle<JSReceiver>::cast(target)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002408
2409 return *result;
2410}
2411
2412
2413// ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
2414BUILTIN(ReflectGetOwnPropertyDescriptor) {
2415 HandleScope scope(isolate);
2416 DCHECK_EQ(3, args.length());
2417 Handle<Object> target = args.at<Object>(1);
2418 Handle<Object> key = args.at<Object>(2);
2419
2420 if (!target->IsJSReceiver()) {
2421 THROW_NEW_ERROR_RETURN_FAILURE(
2422 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2423 isolate->factory()->NewStringFromAsciiChecked(
2424 "Reflect.getOwnPropertyDescriptor")));
2425 }
2426
2427 Handle<Name> name;
2428 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2429 Object::ToName(isolate, key));
2430
2431 PropertyDescriptor desc;
2432 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
2433 isolate, Handle<JSReceiver>::cast(target), name, &desc);
2434 MAYBE_RETURN(found, isolate->heap()->exception());
2435 if (!found.FromJust()) return isolate->heap()->undefined_value();
2436 return *desc.ToObject(isolate);
2437}
2438
2439
2440// ES6 section 26.1.8 Reflect.getPrototypeOf
2441BUILTIN(ReflectGetPrototypeOf) {
2442 HandleScope scope(isolate);
2443 DCHECK_EQ(2, args.length());
2444 Handle<Object> target = args.at<Object>(1);
2445
2446 if (!target->IsJSReceiver()) {
2447 THROW_NEW_ERROR_RETURN_FAILURE(
2448 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2449 isolate->factory()->NewStringFromAsciiChecked(
2450 "Reflect.getPrototypeOf")));
2451 }
2452 Handle<Object> prototype;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002453 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
2454 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2455 isolate, prototype, JSReceiver::GetPrototype(isolate, receiver));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002456 return *prototype;
2457}
2458
2459
2460// ES6 section 26.1.9 Reflect.has
2461BUILTIN(ReflectHas) {
2462 HandleScope scope(isolate);
2463 DCHECK_EQ(3, args.length());
2464 Handle<Object> target = args.at<Object>(1);
2465 Handle<Object> key = args.at<Object>(2);
2466
2467 if (!target->IsJSReceiver()) {
2468 THROW_NEW_ERROR_RETURN_FAILURE(
2469 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2470 isolate->factory()->NewStringFromAsciiChecked(
2471 "Reflect.has")));
2472 }
2473
2474 Handle<Name> name;
2475 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2476 Object::ToName(isolate, key));
2477
2478 Maybe<bool> result =
2479 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
2480 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
2481 : isolate->heap()->exception();
2482}
2483
2484
2485// ES6 section 26.1.10 Reflect.isExtensible
2486BUILTIN(ReflectIsExtensible) {
2487 HandleScope scope(isolate);
2488 DCHECK_EQ(2, args.length());
2489 Handle<Object> target = args.at<Object>(1);
2490
2491 if (!target->IsJSReceiver()) {
2492 THROW_NEW_ERROR_RETURN_FAILURE(
2493 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2494 isolate->factory()->NewStringFromAsciiChecked(
2495 "Reflect.isExtensible")));
2496 }
2497
2498 Maybe<bool> result =
2499 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
2500 MAYBE_RETURN(result, isolate->heap()->exception());
2501 return *isolate->factory()->ToBoolean(result.FromJust());
2502}
2503
2504
2505// ES6 section 26.1.11 Reflect.ownKeys
2506BUILTIN(ReflectOwnKeys) {
2507 HandleScope scope(isolate);
2508 DCHECK_EQ(2, args.length());
2509 Handle<Object> target = args.at<Object>(1);
2510
2511 if (!target->IsJSReceiver()) {
2512 THROW_NEW_ERROR_RETURN_FAILURE(
2513 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2514 isolate->factory()->NewStringFromAsciiChecked(
2515 "Reflect.ownKeys")));
2516 }
2517
2518 Handle<FixedArray> keys;
2519 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002520 isolate, keys,
2521 JSReceiver::GetKeys(Handle<JSReceiver>::cast(target), OWN_ONLY,
2522 ALL_PROPERTIES, CONVERT_TO_STRING));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002523 return *isolate->factory()->NewJSArrayWithElements(keys);
2524}
2525
2526
2527// ES6 section 26.1.12 Reflect.preventExtensions
2528BUILTIN(ReflectPreventExtensions) {
2529 HandleScope scope(isolate);
2530 DCHECK_EQ(2, args.length());
2531 Handle<Object> target = args.at<Object>(1);
2532
2533 if (!target->IsJSReceiver()) {
2534 THROW_NEW_ERROR_RETURN_FAILURE(
2535 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2536 isolate->factory()->NewStringFromAsciiChecked(
2537 "Reflect.preventExtensions")));
2538 }
2539
2540 Maybe<bool> result = JSReceiver::PreventExtensions(
2541 Handle<JSReceiver>::cast(target), Object::DONT_THROW);
2542 MAYBE_RETURN(result, isolate->heap()->exception());
2543 return *isolate->factory()->ToBoolean(result.FromJust());
2544}
2545
2546
2547// ES6 section 26.1.13 Reflect.set
2548BUILTIN(ReflectSet) {
2549 HandleScope scope(isolate);
2550 Handle<Object> target = args.atOrUndefined(isolate, 1);
2551 Handle<Object> key = args.atOrUndefined(isolate, 2);
2552 Handle<Object> value = args.atOrUndefined(isolate, 3);
2553 Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
2554
2555 if (!target->IsJSReceiver()) {
2556 THROW_NEW_ERROR_RETURN_FAILURE(
2557 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2558 isolate->factory()->NewStringFromAsciiChecked(
2559 "Reflect.set")));
2560 }
2561
2562 Handle<Name> name;
2563 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2564 Object::ToName(isolate, key));
2565
2566 LookupIterator it = LookupIterator::PropertyOrElement(
2567 isolate, receiver, name, Handle<JSReceiver>::cast(target));
2568 Maybe<bool> result = Object::SetSuperProperty(
2569 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
2570 MAYBE_RETURN(result, isolate->heap()->exception());
2571 return *isolate->factory()->ToBoolean(result.FromJust());
2572}
2573
2574
2575// ES6 section 26.1.14 Reflect.setPrototypeOf
2576BUILTIN(ReflectSetPrototypeOf) {
2577 HandleScope scope(isolate);
2578 DCHECK_EQ(3, args.length());
2579 Handle<Object> target = args.at<Object>(1);
2580 Handle<Object> proto = args.at<Object>(2);
2581
2582 if (!target->IsJSReceiver()) {
2583 THROW_NEW_ERROR_RETURN_FAILURE(
2584 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2585 isolate->factory()->NewStringFromAsciiChecked(
2586 "Reflect.setPrototypeOf")));
2587 }
2588
2589 if (!proto->IsJSReceiver() && !proto->IsNull()) {
2590 THROW_NEW_ERROR_RETURN_FAILURE(
2591 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2592 }
2593
2594 Maybe<bool> result = JSReceiver::SetPrototype(
2595 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2596 MAYBE_RETURN(result, isolate->heap()->exception());
2597 return *isolate->factory()->ToBoolean(result.FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002598}
2599
2600
Steve Blocka7e24c12009-10-30 11:49:00 +00002601// -----------------------------------------------------------------------------
Ben Murdoch097c5b22016-05-18 11:27:45 +01002602// ES6 section 19.3 Boolean Objects
2603
2604
2605// ES6 section 19.3.1.1 Boolean ( value ) for the [[Call]] case.
2606BUILTIN(BooleanConstructor) {
2607 HandleScope scope(isolate);
2608 Handle<Object> value = args.atOrUndefined(isolate, 1);
2609 return isolate->heap()->ToBoolean(value->BooleanValue());
2610}
2611
2612
2613// ES6 section 19.3.1.1 Boolean ( value ) for the [[Construct]] case.
2614BUILTIN(BooleanConstructor_ConstructStub) {
2615 HandleScope scope(isolate);
2616 Handle<Object> value = args.atOrUndefined(isolate, 1);
2617 Handle<JSFunction> target = args.target<JSFunction>();
2618 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2619 DCHECK(*target == target->native_context()->boolean_function());
2620 Handle<JSObject> result;
2621 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2622 JSObject::New(target, new_target));
2623 Handle<JSValue>::cast(result)->set_value(
2624 isolate->heap()->ToBoolean(value->BooleanValue()));
2625 return *result;
2626}
2627
2628
2629// ES6 section 19.3.3.2 Boolean.prototype.toString ( )
2630BUILTIN(BooleanPrototypeToString) {
2631 HandleScope scope(isolate);
2632 Handle<Object> receiver = args.receiver();
2633 if (receiver->IsJSValue()) {
2634 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
2635 }
2636 if (!receiver->IsBoolean()) {
2637 THROW_NEW_ERROR_RETURN_FAILURE(
2638 isolate, NewTypeError(MessageTemplate::kNotGeneric,
2639 isolate->factory()->NewStringFromAsciiChecked(
2640 "Boolean.prototype.toString")));
2641 }
2642 return Handle<Oddball>::cast(receiver)->to_string();
2643}
2644
2645
2646// ES6 section 19.3.3.3 Boolean.prototype.valueOf ( )
2647BUILTIN(BooleanPrototypeValueOf) {
2648 HandleScope scope(isolate);
2649 Handle<Object> receiver = args.receiver();
2650 if (receiver->IsJSValue()) {
2651 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
2652 }
2653 if (!receiver->IsBoolean()) {
2654 THROW_NEW_ERROR_RETURN_FAILURE(
2655 isolate, NewTypeError(MessageTemplate::kNotGeneric,
2656 isolate->factory()->NewStringFromAsciiChecked(
2657 "Boolean.prototype.valueOf")));
2658 }
2659 return *receiver;
2660}
2661
2662
2663// -----------------------------------------------------------------------------
2664// ES6 section 24.2 DataView Objects
2665
2666
2667// ES6 section 24.2.2 The DataView Constructor for the [[Call]] case.
2668BUILTIN(DataViewConstructor) {
2669 HandleScope scope(isolate);
2670 THROW_NEW_ERROR_RETURN_FAILURE(
2671 isolate,
2672 NewTypeError(MessageTemplate::kConstructorNotFunction,
2673 isolate->factory()->NewStringFromAsciiChecked("DataView")));
2674}
2675
2676
2677// ES6 section 24.2.2 The DataView Constructor for the [[Construct]] case.
2678BUILTIN(DataViewConstructor_ConstructStub) {
2679 HandleScope scope(isolate);
2680 Handle<JSFunction> target = args.target<JSFunction>();
2681 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2682 Handle<Object> buffer = args.atOrUndefined(isolate, 1);
2683 Handle<Object> byte_offset = args.atOrUndefined(isolate, 2);
2684 Handle<Object> byte_length = args.atOrUndefined(isolate, 3);
2685
2686 // 2. If Type(buffer) is not Object, throw a TypeError exception.
2687 // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a
2688 // TypeError exception.
2689 if (!buffer->IsJSArrayBuffer()) {
2690 THROW_NEW_ERROR_RETURN_FAILURE(
2691 isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
2692 }
2693 Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
2694
2695 // 4. Let numberOffset be ? ToNumber(byteOffset).
2696 Handle<Object> number_offset;
2697 if (byte_offset->IsUndefined()) {
2698 // We intentionally violate the specification at this point to allow
2699 // for new DataView(buffer) invocations to be equivalent to the full
2700 // new DataView(buffer, 0) invocation.
2701 number_offset = handle(Smi::FromInt(0), isolate);
2702 } else {
2703 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_offset,
2704 Object::ToNumber(byte_offset));
2705 }
2706
2707 // 5. Let offset be ToInteger(numberOffset).
2708 Handle<Object> offset;
2709 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, offset,
2710 Object::ToInteger(isolate, number_offset));
2711
2712 // 6. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
2713 if (number_offset->Number() != offset->Number() || offset->Number() < 0.0) {
2714 THROW_NEW_ERROR_RETURN_FAILURE(
2715 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2716 }
2717
2718 // 7. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
2719 // We currently violate the specification at this point.
2720
2721 // 8. Let bufferByteLength be the value of buffer's [[ArrayBufferByteLength]]
2722 // internal slot.
2723 double const buffer_byte_length = array_buffer->byte_length()->Number();
2724
2725 // 9. If offset > bufferByteLength, throw a RangeError exception
2726 if (offset->Number() > buffer_byte_length) {
2727 THROW_NEW_ERROR_RETURN_FAILURE(
2728 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2729 }
2730
2731 Handle<Object> view_byte_length;
2732 if (byte_length->IsUndefined()) {
2733 // 10. If byteLength is undefined, then
2734 // a. Let viewByteLength be bufferByteLength - offset.
2735 view_byte_length =
2736 isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
2737 } else {
2738 // 11. Else,
2739 // a. Let viewByteLength be ? ToLength(byteLength).
2740 // b. If offset+viewByteLength > bufferByteLength, throw a RangeError
2741 // exception
2742 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2743 isolate, view_byte_length, Object::ToLength(isolate, byte_length));
2744 if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
2745 THROW_NEW_ERROR_RETURN_FAILURE(
2746 isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
2747 }
2748 }
2749
2750 // 12. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
2751 // "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
2752 // [[ByteLength]], [[ByteOffset]]»).
2753 // 13. Set O's [[DataView]] internal slot to true.
2754 Handle<JSObject> result;
2755 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2756 JSObject::New(target, new_target));
2757 for (int i = 0; i < ArrayBufferView::kInternalFieldCount; ++i) {
2758 Handle<JSDataView>::cast(result)->SetInternalField(i, Smi::FromInt(0));
2759 }
2760
2761 // 14. Set O's [[ViewedArrayBuffer]] internal slot to buffer.
2762 Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
2763
2764 // 15. Set O's [[ByteLength]] internal slot to viewByteLength.
2765 Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
2766
2767 // 16. Set O's [[ByteOffset]] internal slot to offset.
2768 Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
2769
2770 // 17. Return O.
2771 return *result;
2772}
2773
2774
2775// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002776// ES6 section 20.3 Date Objects
Steve Block44f0eee2011-05-26 01:26:41 +01002777
2778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002779namespace {
2780
2781// ES6 section 20.3.1.1 Time Values and Time Range
2782const double kMinYear = -1000000.0;
2783const double kMaxYear = -kMinYear;
2784const double kMinMonth = -10000000.0;
2785const double kMaxMonth = -kMinMonth;
2786
2787
2788// 20.3.1.2 Day Number and Time within Day
2789const double kMsPerDay = 86400000.0;
2790
2791
2792// ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
2793const double kMsPerSecond = 1000.0;
2794const double kMsPerMinute = 60000.0;
2795const double kMsPerHour = 3600000.0;
2796
2797
2798// ES6 section 20.3.1.14 MakeDate (day, time)
2799double MakeDate(double day, double time) {
2800 if (std::isfinite(day) && std::isfinite(time)) {
2801 return time + day * kMsPerDay;
2802 }
2803 return std::numeric_limits<double>::quiet_NaN();
Steve Block44f0eee2011-05-26 01:26:41 +01002804}
2805
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002806
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002807// ES6 section 20.3.1.13 MakeDay (year, month, date)
2808double MakeDay(double year, double month, double date) {
2809 if ((kMinYear <= year && year <= kMaxYear) &&
2810 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
2811 int y = FastD2I(year);
2812 int m = FastD2I(month);
2813 y += m / 12;
2814 m %= 12;
2815 if (m < 0) {
2816 m += 12;
2817 y -= 1;
2818 }
2819 DCHECK_LE(0, m);
2820 DCHECK_LT(m, 12);
2821
2822 // kYearDelta is an arbitrary number such that:
2823 // a) kYearDelta = -1 (mod 400)
2824 // b) year + kYearDelta > 0 for years in the range defined by
2825 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
2826 // Jan 1 1970. This is required so that we don't run into integer
2827 // division of negative numbers.
2828 // c) there shouldn't be an overflow for 32-bit integers in the following
2829 // operations.
2830 static const int kYearDelta = 399999;
2831 static const int kBaseDay =
2832 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
2833 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
2834 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
2835 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
2836 kBaseDay;
2837 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
2838 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151,
2839 181, 212, 243, 273, 304, 334};
2840 day_from_year += kDayFromMonth[m];
2841 } else {
2842 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152,
2843 182, 213, 244, 274, 305, 335};
2844 day_from_year += kDayFromMonth[m];
2845 }
2846 return static_cast<double>(day_from_year - 1) + date;
2847 }
2848 return std::numeric_limits<double>::quiet_NaN();
2849}
2850
2851
2852// ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
2853double MakeTime(double hour, double min, double sec, double ms) {
2854 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
2855 std::isfinite(ms)) {
2856 double const h = DoubleToInteger(hour);
2857 double const m = DoubleToInteger(min);
2858 double const s = DoubleToInteger(sec);
2859 double const milli = DoubleToInteger(ms);
2860 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
2861 }
2862 return std::numeric_limits<double>::quiet_NaN();
2863}
2864
2865
2866// ES6 section 20.3.1.15 TimeClip (time)
2867double TimeClip(double time) {
2868 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
2869 return DoubleToInteger(time) + 0.0;
2870 }
2871 return std::numeric_limits<double>::quiet_NaN();
2872}
2873
2874
2875const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
2876 "Thu", "Fri", "Sat"};
2877const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
2878 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
2879
2880
2881// ES6 section 20.3.1.16 Date Time String Format
2882double ParseDateTimeString(Handle<String> str) {
2883 Isolate* const isolate = str->GetIsolate();
2884 str = String::Flatten(str);
2885 // TODO(bmeurer): Change DateParser to not use the FixedArray.
2886 Handle<FixedArray> tmp =
2887 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
2888 DisallowHeapAllocation no_gc;
2889 String::FlatContent str_content = str->GetFlatContent();
2890 bool result;
2891 if (str_content.IsOneByte()) {
2892 result = DateParser::Parse(str_content.ToOneByteVector(), *tmp,
2893 isolate->unicode_cache());
2894 } else {
2895 result = DateParser::Parse(str_content.ToUC16Vector(), *tmp,
2896 isolate->unicode_cache());
2897 }
2898 if (!result) return std::numeric_limits<double>::quiet_NaN();
2899 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
2900 tmp->get(2)->Number());
2901 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
2902 tmp->get(5)->Number(), tmp->get(6)->Number());
2903 double date = MakeDate(day, time);
2904 if (tmp->get(7)->IsNull()) {
2905 if (!std::isnan(date)) {
2906 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
2907 }
2908 } else {
2909 date -= tmp->get(7)->Number() * 1000.0;
2910 }
2911 return date;
2912}
2913
2914
2915enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
2916
2917
2918// ES6 section 20.3.4.41.1 ToDateString(tv)
2919void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
2920 ToDateStringMode mode = kDateAndTime) {
2921 if (std::isnan(time_val)) {
2922 SNPrintF(str, "Invalid Date");
2923 return;
2924 }
2925 int64_t time_ms = static_cast<int64_t>(time_val);
2926 int64_t local_time_ms = date_cache->ToLocal(time_ms);
2927 int year, month, day, weekday, hour, min, sec, ms;
2928 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
2929 &min, &sec, &ms);
2930 int timezone_offset = -date_cache->TimezoneOffset(time_ms);
2931 int timezone_hour = std::abs(timezone_offset) / 60;
2932 int timezone_min = std::abs(timezone_offset) % 60;
2933 const char* local_timezone = date_cache->LocalTimezone(time_ms);
2934 switch (mode) {
2935 case kDateOnly:
2936 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
2937 kShortMonths[month], day, year);
2938 return;
2939 case kTimeOnly:
2940 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
2941 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
2942 local_timezone);
2943 return;
2944 case kDateAndTime:
2945 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
2946 kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
2947 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
2948 timezone_min, local_timezone);
2949 return;
2950 }
2951 UNREACHABLE();
2952}
2953
2954
2955Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
2956 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2957 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2958 Isolate* const isolate = date->GetIsolate();
2959 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2960 } else {
2961 time_val = std::numeric_limits<double>::quiet_NaN();
2962 }
2963 return *JSDate::SetValue(date, TimeClip(time_val));
2964}
2965
2966} // namespace
2967
2968
2969// ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
2970BUILTIN(DateConstructor) {
2971 HandleScope scope(isolate);
2972 double const time_val = JSDate::CurrentTimeValue(isolate);
2973 char buffer[128];
2974 Vector<char> str(buffer, arraysize(buffer));
2975 ToDateString(time_val, str, isolate->date_cache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002976 Handle<String> result;
2977 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2978 isolate, result,
2979 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
2980 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002981}
2982
2983
2984// ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
2985BUILTIN(DateConstructor_ConstructStub) {
2986 HandleScope scope(isolate);
2987 int const argc = args.length() - 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002988 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002989 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2990 double time_val;
2991 if (argc == 0) {
2992 time_val = JSDate::CurrentTimeValue(isolate);
2993 } else if (argc == 1) {
2994 Handle<Object> value = args.at<Object>(1);
2995 if (value->IsJSDate()) {
2996 time_val = Handle<JSDate>::cast(value)->value()->Number();
2997 } else {
2998 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2999 Object::ToPrimitive(value));
3000 if (value->IsString()) {
3001 time_val = ParseDateTimeString(Handle<String>::cast(value));
3002 } else {
3003 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
3004 Object::ToNumber(value));
3005 time_val = value->Number();
3006 }
3007 }
3008 } else {
3009 Handle<Object> year_object;
3010 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3011 Object::ToNumber(args.at<Object>(1)));
3012 Handle<Object> month_object;
3013 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3014 Object::ToNumber(args.at<Object>(2)));
3015 double year = year_object->Number();
3016 double month = month_object->Number();
3017 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3018 if (argc >= 3) {
3019 Handle<Object> date_object;
3020 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
3021 Object::ToNumber(args.at<Object>(3)));
3022 date = date_object->Number();
3023 if (argc >= 4) {
3024 Handle<Object> hours_object;
3025 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3026 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3027 hours = hours_object->Number();
3028 if (argc >= 5) {
3029 Handle<Object> minutes_object;
3030 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3031 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3032 minutes = minutes_object->Number();
3033 if (argc >= 6) {
3034 Handle<Object> seconds_object;
3035 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3036 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
3037 seconds = seconds_object->Number();
3038 if (argc >= 7) {
3039 Handle<Object> ms_object;
3040 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3041 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3042 ms = ms_object->Number();
3043 }
3044 }
3045 }
3046 }
3047 }
3048 if (!std::isnan(year)) {
3049 double const y = DoubleToInteger(year);
3050 if (0.0 <= y && y <= 99) year = 1900 + y;
3051 }
3052 double const day = MakeDay(year, month, date);
3053 double const time = MakeTime(hours, minutes, seconds, ms);
3054 time_val = MakeDate(day, time);
3055 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
3056 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
3057 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
3058 } else {
3059 time_val = std::numeric_limits<double>::quiet_NaN();
3060 }
3061 }
3062 Handle<JSDate> result;
3063 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3064 JSDate::New(target, new_target, time_val));
3065 return *result;
3066}
3067
3068
3069// ES6 section 20.3.3.1 Date.now ( )
3070BUILTIN(DateNow) {
3071 HandleScope scope(isolate);
3072 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
3073}
3074
3075
3076// ES6 section 20.3.3.2 Date.parse ( string )
3077BUILTIN(DateParse) {
3078 HandleScope scope(isolate);
3079 Handle<String> string;
3080 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3081 isolate, string,
3082 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
3083 return *isolate->factory()->NewNumber(ParseDateTimeString(string));
3084}
3085
3086
3087// ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
3088BUILTIN(DateUTC) {
3089 HandleScope scope(isolate);
3090 int const argc = args.length() - 1;
3091 double year = std::numeric_limits<double>::quiet_NaN();
3092 double month = std::numeric_limits<double>::quiet_NaN();
3093 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3094 if (argc >= 1) {
3095 Handle<Object> year_object;
3096 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3097 Object::ToNumber(args.at<Object>(1)));
3098 year = year_object->Number();
3099 if (argc >= 2) {
3100 Handle<Object> month_object;
3101 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3102 Object::ToNumber(args.at<Object>(2)));
3103 month = month_object->Number();
3104 if (argc >= 3) {
3105 Handle<Object> date_object;
3106 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3107 isolate, date_object, Object::ToNumber(args.at<Object>(3)));
3108 date = date_object->Number();
3109 if (argc >= 4) {
3110 Handle<Object> hours_object;
3111 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3112 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3113 hours = hours_object->Number();
3114 if (argc >= 5) {
3115 Handle<Object> minutes_object;
3116 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3117 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3118 minutes = minutes_object->Number();
3119 if (argc >= 6) {
3120 Handle<Object> seconds_object;
3121 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3122 isolate, seconds_object,
3123 Object::ToNumber(args.at<Object>(6)));
3124 seconds = seconds_object->Number();
3125 if (argc >= 7) {
3126 Handle<Object> ms_object;
3127 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3128 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3129 ms = ms_object->Number();
3130 }
3131 }
3132 }
3133 }
3134 }
3135 }
3136 }
3137 if (!std::isnan(year)) {
3138 double const y = DoubleToInteger(year);
3139 if (0.0 <= y && y <= 99) year = 1900 + y;
3140 }
3141 double const day = MakeDay(year, month, date);
3142 double const time = MakeTime(hours, minutes, seconds, ms);
3143 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
3144}
3145
3146
3147// ES6 section 20.3.4.20 Date.prototype.setDate ( date )
3148BUILTIN(DatePrototypeSetDate) {
3149 HandleScope scope(isolate);
3150 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
3151 Handle<Object> value = args.atOrUndefined(isolate, 1);
3152 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3153 double time_val = date->value()->Number();
3154 if (!std::isnan(time_val)) {
3155 int64_t const time_ms = static_cast<int64_t>(time_val);
3156 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3157 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3158 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3159 int year, month, day;
3160 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3161 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3162 }
3163 return SetLocalDateValue(date, time_val);
3164}
3165
3166
3167// ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
3168BUILTIN(DatePrototypeSetFullYear) {
3169 HandleScope scope(isolate);
3170 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
3171 int const argc = args.length() - 1;
3172 Handle<Object> year = args.atOrUndefined(isolate, 1);
3173 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3174 double y = year->Number(), m = 0.0, dt = 1.0;
3175 int time_within_day = 0;
3176 if (!std::isnan(date->value()->Number())) {
3177 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3178 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3179 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3180 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3181 int year, month, day;
3182 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3183 m = month;
3184 dt = day;
3185 }
3186 if (argc >= 2) {
3187 Handle<Object> month = args.at<Object>(2);
3188 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3189 m = month->Number();
3190 if (argc >= 3) {
3191 Handle<Object> date = args.at<Object>(3);
3192 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3193 dt = date->Number();
3194 }
3195 }
3196 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3197 return SetLocalDateValue(date, time_val);
3198}
3199
3200
3201// ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
3202BUILTIN(DatePrototypeSetHours) {
3203 HandleScope scope(isolate);
3204 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
3205 int const argc = args.length() - 1;
3206 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3207 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3208 double h = hour->Number();
3209 double time_val = date->value()->Number();
3210 if (!std::isnan(time_val)) {
3211 int64_t const time_ms = static_cast<int64_t>(time_val);
3212 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3213 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3214 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3215 double m = (time_within_day / (60 * 1000)) % 60;
3216 double s = (time_within_day / 1000) % 60;
3217 double milli = time_within_day % 1000;
3218 if (argc >= 2) {
3219 Handle<Object> min = args.at<Object>(2);
3220 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3221 m = min->Number();
3222 if (argc >= 3) {
3223 Handle<Object> sec = args.at<Object>(3);
3224 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3225 s = sec->Number();
3226 if (argc >= 4) {
3227 Handle<Object> ms = args.at<Object>(4);
3228 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3229 milli = ms->Number();
3230 }
3231 }
3232 }
3233 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3234 }
3235 return SetLocalDateValue(date, time_val);
3236}
3237
3238
3239// ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
3240BUILTIN(DatePrototypeSetMilliseconds) {
3241 HandleScope scope(isolate);
3242 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
3243 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3244 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3245 double time_val = date->value()->Number();
3246 if (!std::isnan(time_val)) {
3247 int64_t const time_ms = static_cast<int64_t>(time_val);
3248 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3249 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3250 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3251 int h = time_within_day / (60 * 60 * 1000);
3252 int m = (time_within_day / (60 * 1000)) % 60;
3253 int s = (time_within_day / 1000) % 60;
3254 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3255 }
3256 return SetLocalDateValue(date, time_val);
3257}
3258
3259
3260// ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
3261BUILTIN(DatePrototypeSetMinutes) {
3262 HandleScope scope(isolate);
3263 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
3264 int const argc = args.length() - 1;
3265 Handle<Object> min = args.atOrUndefined(isolate, 1);
3266 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3267 double time_val = date->value()->Number();
3268 if (!std::isnan(time_val)) {
3269 int64_t const time_ms = static_cast<int64_t>(time_val);
3270 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3271 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3272 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3273 int h = time_within_day / (60 * 60 * 1000);
3274 double m = min->Number();
3275 double s = (time_within_day / 1000) % 60;
3276 double milli = time_within_day % 1000;
3277 if (argc >= 2) {
3278 Handle<Object> sec = args.at<Object>(2);
3279 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3280 s = sec->Number();
3281 if (argc >= 3) {
3282 Handle<Object> ms = args.at<Object>(3);
3283 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3284 milli = ms->Number();
3285 }
3286 }
3287 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3288 }
3289 return SetLocalDateValue(date, time_val);
3290}
3291
3292
3293// ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
3294BUILTIN(DatePrototypeSetMonth) {
3295 HandleScope scope(isolate);
3296 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
3297 int const argc = args.length() - 1;
3298 Handle<Object> month = args.atOrUndefined(isolate, 1);
3299 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3300 double time_val = date->value()->Number();
3301 if (!std::isnan(time_val)) {
3302 int64_t const time_ms = static_cast<int64_t>(time_val);
3303 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3304 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3305 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3306 int year, unused, day;
3307 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3308 double m = month->Number();
3309 double dt = day;
3310 if (argc >= 2) {
3311 Handle<Object> date = args.at<Object>(2);
3312 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3313 dt = date->Number();
3314 }
3315 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3316 }
3317 return SetLocalDateValue(date, time_val);
3318}
3319
3320
3321// ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
3322BUILTIN(DatePrototypeSetSeconds) {
3323 HandleScope scope(isolate);
3324 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
3325 int const argc = args.length() - 1;
3326 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3327 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3328 double time_val = date->value()->Number();
3329 if (!std::isnan(time_val)) {
3330 int64_t const time_ms = static_cast<int64_t>(time_val);
3331 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3332 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3333 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3334 int h = time_within_day / (60 * 60 * 1000);
3335 double m = (time_within_day / (60 * 1000)) % 60;
3336 double s = sec->Number();
3337 double milli = time_within_day % 1000;
3338 if (argc >= 2) {
3339 Handle<Object> ms = args.at<Object>(2);
3340 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3341 milli = ms->Number();
3342 }
3343 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3344 }
3345 return SetLocalDateValue(date, time_val);
3346}
3347
3348
3349// ES6 section 20.3.4.27 Date.prototype.setTime ( time )
3350BUILTIN(DatePrototypeSetTime) {
3351 HandleScope scope(isolate);
3352 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
3353 Handle<Object> value = args.atOrUndefined(isolate, 1);
3354 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3355 return *JSDate::SetValue(date, TimeClip(value->Number()));
3356}
3357
3358
3359// ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
3360BUILTIN(DatePrototypeSetUTCDate) {
3361 HandleScope scope(isolate);
3362 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
3363 Handle<Object> value = args.atOrUndefined(isolate, 1);
3364 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3365 if (std::isnan(date->value()->Number())) return date->value();
3366 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3367 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3368 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3369 int year, month, day;
3370 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3371 double const time_val =
3372 MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3373 return *JSDate::SetValue(date, TimeClip(time_val));
3374}
3375
3376
3377// ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
3378BUILTIN(DatePrototypeSetUTCFullYear) {
3379 HandleScope scope(isolate);
3380 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
3381 int const argc = args.length() - 1;
3382 Handle<Object> year = args.atOrUndefined(isolate, 1);
3383 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3384 double y = year->Number(), m = 0.0, dt = 1.0;
3385 int time_within_day = 0;
3386 if (!std::isnan(date->value()->Number())) {
3387 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3388 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3389 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3390 int year, month, day;
3391 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3392 m = month;
3393 dt = day;
3394 }
3395 if (argc >= 2) {
3396 Handle<Object> month = args.at<Object>(2);
3397 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3398 m = month->Number();
3399 if (argc >= 3) {
3400 Handle<Object> date = args.at<Object>(3);
3401 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3402 dt = date->Number();
3403 }
3404 }
3405 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3406 return *JSDate::SetValue(date, TimeClip(time_val));
3407}
3408
3409
3410// ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
3411BUILTIN(DatePrototypeSetUTCHours) {
3412 HandleScope scope(isolate);
3413 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
3414 int const argc = args.length() - 1;
3415 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3416 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3417 double h = hour->Number();
3418 double time_val = date->value()->Number();
3419 if (!std::isnan(time_val)) {
3420 int64_t const time_ms = static_cast<int64_t>(time_val);
3421 int day = isolate->date_cache()->DaysFromTime(time_ms);
3422 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3423 double m = (time_within_day / (60 * 1000)) % 60;
3424 double s = (time_within_day / 1000) % 60;
3425 double milli = time_within_day % 1000;
3426 if (argc >= 2) {
3427 Handle<Object> min = args.at<Object>(2);
3428 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3429 m = min->Number();
3430 if (argc >= 3) {
3431 Handle<Object> sec = args.at<Object>(3);
3432 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3433 s = sec->Number();
3434 if (argc >= 4) {
3435 Handle<Object> ms = args.at<Object>(4);
3436 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3437 milli = ms->Number();
3438 }
3439 }
3440 }
3441 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3442 }
3443 return *JSDate::SetValue(date, TimeClip(time_val));
3444}
3445
3446
3447// ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
3448BUILTIN(DatePrototypeSetUTCMilliseconds) {
3449 HandleScope scope(isolate);
3450 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
3451 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3452 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3453 double time_val = date->value()->Number();
3454 if (!std::isnan(time_val)) {
3455 int64_t const time_ms = static_cast<int64_t>(time_val);
3456 int day = isolate->date_cache()->DaysFromTime(time_ms);
3457 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3458 int h = time_within_day / (60 * 60 * 1000);
3459 int m = (time_within_day / (60 * 1000)) % 60;
3460 int s = (time_within_day / 1000) % 60;
3461 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3462 }
3463 return *JSDate::SetValue(date, TimeClip(time_val));
3464}
3465
3466
3467// ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
3468BUILTIN(DatePrototypeSetUTCMinutes) {
3469 HandleScope scope(isolate);
3470 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
3471 int const argc = args.length() - 1;
3472 Handle<Object> min = args.atOrUndefined(isolate, 1);
3473 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3474 double time_val = date->value()->Number();
3475 if (!std::isnan(time_val)) {
3476 int64_t const time_ms = static_cast<int64_t>(time_val);
3477 int day = isolate->date_cache()->DaysFromTime(time_ms);
3478 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3479 int h = time_within_day / (60 * 60 * 1000);
3480 double m = min->Number();
3481 double s = (time_within_day / 1000) % 60;
3482 double milli = time_within_day % 1000;
3483 if (argc >= 2) {
3484 Handle<Object> sec = args.at<Object>(2);
3485 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3486 s = sec->Number();
3487 if (argc >= 3) {
3488 Handle<Object> ms = args.at<Object>(3);
3489 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3490 milli = ms->Number();
3491 }
3492 }
3493 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3494 }
3495 return *JSDate::SetValue(date, TimeClip(time_val));
3496}
3497
3498
3499// ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
3500BUILTIN(DatePrototypeSetUTCMonth) {
3501 HandleScope scope(isolate);
3502 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
3503 int const argc = args.length() - 1;
3504 Handle<Object> month = args.atOrUndefined(isolate, 1);
3505 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3506 double time_val = date->value()->Number();
3507 if (!std::isnan(time_val)) {
3508 int64_t const time_ms = static_cast<int64_t>(time_val);
3509 int days = isolate->date_cache()->DaysFromTime(time_ms);
3510 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3511 int year, unused, day;
3512 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3513 double m = month->Number();
3514 double dt = day;
3515 if (argc >= 2) {
3516 Handle<Object> date = args.at<Object>(2);
3517 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3518 dt = date->Number();
3519 }
3520 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3521 }
3522 return *JSDate::SetValue(date, TimeClip(time_val));
3523}
3524
3525
3526// ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
3527BUILTIN(DatePrototypeSetUTCSeconds) {
3528 HandleScope scope(isolate);
3529 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
3530 int const argc = args.length() - 1;
3531 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3532 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3533 double time_val = date->value()->Number();
3534 if (!std::isnan(time_val)) {
3535 int64_t const time_ms = static_cast<int64_t>(time_val);
3536 int day = isolate->date_cache()->DaysFromTime(time_ms);
3537 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3538 int h = time_within_day / (60 * 60 * 1000);
3539 double m = (time_within_day / (60 * 1000)) % 60;
3540 double s = sec->Number();
3541 double milli = time_within_day % 1000;
3542 if (argc >= 2) {
3543 Handle<Object> ms = args.at<Object>(2);
3544 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3545 milli = ms->Number();
3546 }
3547 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3548 }
3549 return *JSDate::SetValue(date, TimeClip(time_val));
3550}
3551
3552
3553// ES6 section 20.3.4.35 Date.prototype.toDateString ( )
3554BUILTIN(DatePrototypeToDateString) {
3555 HandleScope scope(isolate);
3556 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
3557 char buffer[128];
3558 Vector<char> str(buffer, arraysize(buffer));
3559 ToDateString(date->value()->Number(), str, isolate->date_cache(), kDateOnly);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003560 Handle<String> result;
3561 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3562 isolate, result,
3563 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3564 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003565}
3566
3567
3568// ES6 section 20.3.4.36 Date.prototype.toISOString ( )
3569BUILTIN(DatePrototypeToISOString) {
3570 HandleScope scope(isolate);
3571 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
3572 double const time_val = date->value()->Number();
3573 if (std::isnan(time_val)) {
3574 THROW_NEW_ERROR_RETURN_FAILURE(
3575 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
3576 }
3577 int64_t const time_ms = static_cast<int64_t>(time_val);
3578 int year, month, day, weekday, hour, min, sec, ms;
3579 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3580 &hour, &min, &sec, &ms);
3581 char buffer[128];
3582 Vector<char> str(buffer, arraysize(buffer));
3583 if (year >= 0 && year <= 9999) {
3584 SNPrintF(str, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
3585 hour, min, sec, ms);
3586 } else if (year < 0) {
3587 SNPrintF(str, "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, month + 1, day,
3588 hour, min, sec, ms);
3589 } else {
3590 SNPrintF(str, "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
3591 hour, min, sec, ms);
3592 }
3593 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
3594}
3595
3596
3597// ES6 section 20.3.4.41 Date.prototype.toString ( )
3598BUILTIN(DatePrototypeToString) {
3599 HandleScope scope(isolate);
3600 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
3601 char buffer[128];
3602 Vector<char> str(buffer, arraysize(buffer));
3603 ToDateString(date->value()->Number(), str, isolate->date_cache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003604 Handle<String> result;
3605 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3606 isolate, result,
3607 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3608 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003609}
3610
3611
3612// ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
3613BUILTIN(DatePrototypeToTimeString) {
3614 HandleScope scope(isolate);
3615 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
3616 char buffer[128];
3617 Vector<char> str(buffer, arraysize(buffer));
3618 ToDateString(date->value()->Number(), str, isolate->date_cache(), kTimeOnly);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003619 Handle<String> result;
3620 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3621 isolate, result,
3622 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3623 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003624}
3625
3626
3627// ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
3628BUILTIN(DatePrototypeToUTCString) {
3629 HandleScope scope(isolate);
3630 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
3631 double const time_val = date->value()->Number();
3632 if (std::isnan(time_val)) {
3633 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
3634 }
3635 char buffer[128];
3636 Vector<char> str(buffer, arraysize(buffer));
3637 int64_t time_ms = static_cast<int64_t>(time_val);
3638 int year, month, day, weekday, hour, min, sec, ms;
3639 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3640 &hour, &min, &sec, &ms);
3641 SNPrintF(str, "%s, %02d %s %4d %02d:%02d:%02d GMT", kShortWeekDays[weekday],
3642 day, kShortMonths[month], year, hour, min, sec);
3643 return *isolate->factory()->NewStringFromAsciiChecked(str.start());
3644}
3645
3646
3647// ES6 section 20.3.4.44 Date.prototype.valueOf ( )
3648BUILTIN(DatePrototypeValueOf) {
3649 HandleScope scope(isolate);
3650 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
3651 return date->value();
3652}
3653
3654
3655// ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
3656BUILTIN(DatePrototypeToPrimitive) {
3657 HandleScope scope(isolate);
3658 DCHECK_EQ(2, args.length());
3659 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
3660 Handle<Object> hint = args.at<Object>(1);
3661 Handle<Object> result;
3662 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3663 JSDate::ToPrimitive(receiver, hint));
3664 return *result;
3665}
3666
3667
3668// ES6 section B.2.4.1 Date.prototype.getYear ( )
3669BUILTIN(DatePrototypeGetYear) {
3670 HandleScope scope(isolate);
3671 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
3672 double time_val = date->value()->Number();
3673 if (std::isnan(time_val)) return date->value();
3674 int64_t time_ms = static_cast<int64_t>(time_val);
3675 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3676 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3677 int year, month, day;
3678 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3679 return Smi::FromInt(year - 1900);
3680}
3681
3682
3683// ES6 section B.2.4.2 Date.prototype.setYear ( year )
3684BUILTIN(DatePrototypeSetYear) {
3685 HandleScope scope(isolate);
3686 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
3687 Handle<Object> year = args.atOrUndefined(isolate, 1);
3688 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3689 double m = 0.0, dt = 1.0, y = year->Number();
3690 if (0.0 <= y && y <= 99.0) {
3691 y = 1900.0 + DoubleToInteger(y);
3692 }
3693 int time_within_day = 0;
3694 if (!std::isnan(date->value()->Number())) {
3695 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3696 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3697 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3698 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3699 int year, month, day;
3700 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3701 m = month;
3702 dt = day;
3703 }
3704 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3705 return SetLocalDateValue(date, time_val);
3706}
3707
3708
3709// static
3710void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
3711 Generate_DatePrototype_GetField(masm, JSDate::kDay);
3712}
3713
3714
3715// static
3716void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
3717 Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
3718}
3719
3720
3721// static
3722void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
3723 Generate_DatePrototype_GetField(masm, JSDate::kYear);
3724}
3725
3726
3727// static
3728void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
3729 Generate_DatePrototype_GetField(masm, JSDate::kHour);
3730}
3731
3732
3733// static
3734void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
3735 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
3736}
3737
3738
3739// static
3740void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
3741 Generate_DatePrototype_GetField(masm, JSDate::kMinute);
3742}
3743
3744
3745// static
3746void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
3747 Generate_DatePrototype_GetField(masm, JSDate::kMonth);
3748}
3749
3750
3751// static
3752void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
3753 Generate_DatePrototype_GetField(masm, JSDate::kSecond);
3754}
3755
3756
3757// static
3758void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
3759 Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
3760}
3761
3762
3763// static
3764void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
3765 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
3766}
3767
3768
3769// static
3770void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
3771 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
3772}
3773
3774
3775// static
3776void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
3777 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
3778}
3779
3780
3781// static
3782void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
3783 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
3784}
3785
3786
3787// static
3788void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
3789 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
3790}
3791
3792
3793// static
3794void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
3795 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
3796}
3797
3798
3799// static
3800void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
3801 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
3802}
3803
3804
3805// static
3806void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
3807 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
3808}
3809
3810
3811// static
3812void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
3813 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
3814}
3815
3816
3817namespace {
3818
3819// ES6 section 19.2.1.1.1 CreateDynamicFunction
3820MaybeHandle<JSFunction> CreateDynamicFunction(
3821 Isolate* isolate,
3822 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,
3823 const char* token) {
3824 // Compute number of arguments, ignoring the receiver.
3825 DCHECK_LE(1, args.length());
3826 int const argc = args.length() - 1;
3827
3828 // Build the source string.
3829 Handle<String> source;
3830 {
3831 IncrementalStringBuilder builder(isolate);
3832 builder.AppendCharacter('(');
3833 builder.AppendCString(token);
3834 builder.AppendCharacter('(');
3835 bool parenthesis_in_arg_string = false;
3836 if (argc > 1) {
3837 for (int i = 1; i < argc; ++i) {
3838 if (i > 1) builder.AppendCharacter(',');
3839 Handle<String> param;
3840 ASSIGN_RETURN_ON_EXCEPTION(
3841 isolate, param, Object::ToString(isolate, args.at<Object>(i)),
3842 JSFunction);
3843 param = String::Flatten(param);
3844 builder.AppendString(param);
3845 // If the formal parameters string include ) - an illegal
3846 // character - it may make the combined function expression
3847 // compile. We avoid this problem by checking for this early on.
3848 DisallowHeapAllocation no_gc; // Ensure vectors stay valid.
3849 String::FlatContent param_content = param->GetFlatContent();
3850 for (int i = 0, length = param->length(); i < length; ++i) {
3851 if (param_content.Get(i) == ')') {
3852 parenthesis_in_arg_string = true;
3853 break;
3854 }
3855 }
3856 }
3857 // If the formal parameters include an unbalanced block comment, the
3858 // function must be rejected. Since JavaScript does not allow nested
3859 // comments we can include a trailing block comment to catch this.
3860 builder.AppendCString("\n/**/");
3861 }
3862 builder.AppendCString(") {\n");
3863 if (argc > 0) {
3864 Handle<String> body;
3865 ASSIGN_RETURN_ON_EXCEPTION(
3866 isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
3867 JSFunction);
3868 builder.AppendString(body);
3869 }
3870 builder.AppendCString("\n})");
3871 ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction);
3872
3873 // The SyntaxError must be thrown after all the (observable) ToString
3874 // conversions are done.
3875 if (parenthesis_in_arg_string) {
3876 THROW_NEW_ERROR(isolate,
3877 NewSyntaxError(MessageTemplate::kParenthesisInArgString),
3878 JSFunction);
3879 }
3880 }
3881
3882 // Compile the string in the constructor and not a helper so that errors to
3883 // come from here.
Ben Murdoch097c5b22016-05-18 11:27:45 +01003884 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003885 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
3886 Handle<JSFunction> function;
3887 {
3888 ASSIGN_RETURN_ON_EXCEPTION(
3889 isolate, function,
3890 CompileString(handle(target->native_context(), isolate), source,
3891 ONLY_SINGLE_FUNCTION_LITERAL),
3892 JSFunction);
3893 Handle<Object> result;
3894 ASSIGN_RETURN_ON_EXCEPTION(
3895 isolate, result,
3896 Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
3897 JSFunction);
3898 function = Handle<JSFunction>::cast(result);
3899 function->shared()->set_name_should_print_as_anonymous(true);
3900 }
3901
3902 // If new.target is equal to target then the function created
3903 // is already correctly setup and nothing else should be done
3904 // here. But if new.target is not equal to target then we are
3905 // have a Function builtin subclassing case and therefore the
3906 // function has wrong initial map. To fix that we create a new
3907 // function object with correct initial map.
3908 Handle<Object> unchecked_new_target = args.new_target();
3909 if (!unchecked_new_target->IsUndefined() &&
3910 !unchecked_new_target.is_identical_to(target)) {
3911 Handle<JSReceiver> new_target =
3912 Handle<JSReceiver>::cast(unchecked_new_target);
3913 Handle<Map> initial_map;
3914 ASSIGN_RETURN_ON_EXCEPTION(
3915 isolate, initial_map,
3916 JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction);
3917
3918 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
3919 Handle<Map> map = Map::AsLanguageMode(
3920 initial_map, shared_info->language_mode(), shared_info->kind());
3921
3922 Handle<Context> context(function->context(), isolate);
3923 function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
3924 map, shared_info, context, NOT_TENURED);
3925 }
3926 return function;
3927}
3928
3929} // namespace
3930
3931
3932// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
3933BUILTIN(FunctionConstructor) {
3934 HandleScope scope(isolate);
3935 Handle<JSFunction> result;
3936 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3937 isolate, result, CreateDynamicFunction(isolate, args, "function"));
3938 return *result;
3939}
3940
3941
3942// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
3943BUILTIN(FunctionPrototypeBind) {
3944 HandleScope scope(isolate);
3945 DCHECK_LE(1, args.length());
3946 if (!args.receiver()->IsCallable()) {
3947 THROW_NEW_ERROR_RETURN_FAILURE(
3948 isolate, NewTypeError(MessageTemplate::kFunctionBind));
3949 }
3950
3951 // Allocate the bound function with the given {this_arg} and {args}.
3952 Handle<JSReceiver> target = args.at<JSReceiver>(0);
3953 Handle<Object> this_arg = isolate->factory()->undefined_value();
3954 ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
3955 if (args.length() > 1) {
3956 this_arg = args.at<Object>(1);
3957 for (int i = 2; i < args.length(); ++i) {
3958 argv[i - 2] = args.at<Object>(i);
3959 }
3960 }
3961 Handle<JSBoundFunction> function;
3962 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3963 isolate, function,
3964 isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
3965
3966 // TODO(bmeurer): Optimize the rest for the common cases where {target} is
3967 // a function with some initial map or even a bound function.
3968 // Setup the "length" property based on the "length" of the {target}.
3969 Handle<Object> length(Smi::FromInt(0), isolate);
3970 Maybe<bool> target_has_length =
3971 JSReceiver::HasOwnProperty(target, isolate->factory()->length_string());
3972 if (!target_has_length.IsJust()) {
3973 return isolate->heap()->exception();
3974 } else if (target_has_length.FromJust()) {
3975 Handle<Object> target_length;
3976 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3977 isolate, target_length,
3978 JSReceiver::GetProperty(target, isolate->factory()->length_string()));
3979 if (target_length->IsNumber()) {
3980 length = isolate->factory()->NewNumber(std::max(
3981 0.0, DoubleToInteger(target_length->Number()) - argv.length()));
3982 }
3983 }
3984 function->set_length(*length);
3985
3986 // Setup the "name" property based on the "name" of the {target}.
3987 Handle<Object> target_name;
3988 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3989 isolate, target_name,
3990 JSReceiver::GetProperty(target, isolate->factory()->name_string()));
3991 Handle<String> name;
3992 if (!target_name->IsString()) {
3993 name = isolate->factory()->bound__string();
3994 } else {
3995 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3996 isolate, name, Name::ToFunctionName(Handle<String>::cast(target_name)));
3997 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3998 isolate, name, isolate->factory()->NewConsString(
3999 isolate->factory()->bound__string(), name));
4000 }
4001 function->set_name(*name);
4002 return *function;
4003}
4004
4005
4006// ES6 section 19.2.3.5 Function.prototype.toString ( )
4007BUILTIN(FunctionPrototypeToString) {
4008 HandleScope scope(isolate);
4009 Handle<Object> receiver = args.receiver();
4010 if (receiver->IsJSBoundFunction()) {
4011 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
4012 } else if (receiver->IsJSFunction()) {
4013 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
4014 }
4015 THROW_NEW_ERROR_RETURN_FAILURE(
4016 isolate, NewTypeError(MessageTemplate::kNotGeneric,
4017 isolate->factory()->NewStringFromAsciiChecked(
4018 "Function.prototype.toString")));
4019}
4020
4021
4022// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
4023BUILTIN(GeneratorFunctionConstructor) {
4024 HandleScope scope(isolate);
4025 Handle<JSFunction> result;
4026 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4027 isolate, result, CreateDynamicFunction(isolate, args, "function*"));
4028 return *result;
4029}
4030
4031
4032// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
4033BUILTIN(SymbolConstructor) {
4034 HandleScope scope(isolate);
4035 Handle<Symbol> result = isolate->factory()->NewSymbol();
4036 Handle<Object> description = args.atOrUndefined(isolate, 1);
4037 if (!description->IsUndefined()) {
4038 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
4039 Object::ToString(isolate, description));
4040 result->set_name(*description);
4041 }
4042 return *result;
4043}
4044
4045
4046// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
4047BUILTIN(SymbolConstructor_ConstructStub) {
4048 HandleScope scope(isolate);
4049 THROW_NEW_ERROR_RETURN_FAILURE(
4050 isolate, NewTypeError(MessageTemplate::kNotConstructor,
4051 isolate->factory()->Symbol_string()));
4052}
4053
4054
4055// ES6 19.1.3.6 Object.prototype.toString
4056BUILTIN(ObjectProtoToString) {
4057 HandleScope scope(isolate);
4058 Handle<Object> object = args.at<Object>(0);
4059 Handle<String> result;
4060 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdochda12d292016-06-02 14:46:10 +01004061 isolate, result, Object::ObjectProtoToString(isolate, object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004062 return *result;
4063}
4064
Ben Murdochda12d292016-06-02 14:46:10 +01004065// -----------------------------------------------------------------------------
4066// ES6 section 21.1 String Objects
4067
4068namespace {
4069
4070bool ToUint16(Handle<Object> value, uint16_t* result) {
4071 if (value->IsNumber() || Object::ToNumber(value).ToHandle(&value)) {
4072 *result = DoubleToUint32(value->Number());
4073 return true;
4074 }
4075 return false;
4076}
4077
4078} // namespace
4079
4080// ES6 21.1.2.1 String.fromCharCode ( ...codeUnits )
4081BUILTIN(StringFromCharCode) {
4082 HandleScope scope(isolate);
4083 // Check resulting string length.
4084 int index = 0;
4085 Handle<String> result;
4086 int const length = args.length() - 1;
4087 if (length == 0) return isolate->heap()->empty_string();
4088 DCHECK_LT(0, length);
4089 // Load the first character code.
4090 uint16_t code;
4091 if (!ToUint16(args.at<Object>(1), &code)) return isolate->heap()->exception();
4092 // Assume that the resulting String contains only one byte characters.
4093 if (code <= String::kMaxOneByteCharCodeU) {
4094 // Check for single one-byte character fast case.
4095 if (length == 1) {
4096 return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
4097 }
4098 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4099 isolate, result, isolate->factory()->NewRawOneByteString(length));
4100 do {
4101 Handle<SeqOneByteString>::cast(result)->Set(index, code);
4102 if (++index == length) break;
4103 if (!ToUint16(args.at<Object>(1 + index), &code)) {
4104 return isolate->heap()->exception();
4105 }
4106 } while (code <= String::kMaxOneByteCharCodeU);
4107 }
4108 // Check if all characters fit into the one byte range.
4109 if (index < length) {
4110 // Fallback to two byte string.
4111 Handle<String> new_result;
4112 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4113 isolate, new_result, isolate->factory()->NewRawTwoByteString(length));
4114 for (int new_index = 0; new_index < index; ++new_index) {
4115 uint16_t new_code =
4116 Handle<SeqOneByteString>::cast(result)->Get(new_index);
4117 Handle<SeqTwoByteString>::cast(new_result)->Set(new_index, new_code);
4118 }
4119 while (true) {
4120 Handle<SeqTwoByteString>::cast(new_result)->Set(index, code);
4121 if (++index == length) break;
4122 if (!ToUint16(args.at<Object>(1 + index), &code)) {
4123 return isolate->heap()->exception();
4124 }
4125 }
4126 result = new_result;
4127 }
4128 return *result;
4129}
4130
4131// -----------------------------------------------------------------------------
4132// ES6 section 21.1 ArrayBuffer Objects
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004133
4134// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
4135BUILTIN(ArrayBufferConstructor) {
4136 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004137 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004138 DCHECK(*target == target->native_context()->array_buffer_fun() ||
4139 *target == target->native_context()->shared_array_buffer_fun());
4140 THROW_NEW_ERROR_RETURN_FAILURE(
4141 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
4142 handle(target->shared()->name(), isolate)));
4143}
4144
4145
4146// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
4147BUILTIN(ArrayBufferConstructor_ConstructStub) {
4148 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004149 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004150 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
4151 Handle<Object> length = args.atOrUndefined(isolate, 1);
4152 DCHECK(*target == target->native_context()->array_buffer_fun() ||
4153 *target == target->native_context()->shared_array_buffer_fun());
4154 Handle<Object> number_length;
4155 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
4156 Object::ToInteger(isolate, length));
4157 if (number_length->Number() < 0.0) {
4158 THROW_NEW_ERROR_RETURN_FAILURE(
4159 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
4160 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004161 Handle<JSObject> result;
4162 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
4163 JSObject::New(target, new_target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004164 size_t byte_length;
4165 if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
4166 THROW_NEW_ERROR_RETURN_FAILURE(
4167 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
4168 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004169 SharedFlag shared_flag =
4170 (*target == target->native_context()->array_buffer_fun())
4171 ? SharedFlag::kNotShared
4172 : SharedFlag::kShared;
Ben Murdoch097c5b22016-05-18 11:27:45 +01004173 if (!JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer>::cast(result),
4174 isolate, byte_length, true,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004175 shared_flag)) {
4176 THROW_NEW_ERROR_RETURN_FAILURE(
4177 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
4178 }
4179 return *result;
4180}
4181
4182
4183// ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
4184BUILTIN(ArrayBufferIsView) {
4185 SealHandleScope shs(isolate);
4186 DCHECK_EQ(2, args.length());
4187 Object* arg = args[1];
4188 return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
4189}
4190
4191
4192// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
4193BUILTIN(ProxyConstructor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004194 HandleScope scope(isolate);
4195 THROW_NEW_ERROR_RETURN_FAILURE(
4196 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004197 NewTypeError(MessageTemplate::kConstructorNotFunction,
4198 isolate->factory()->NewStringFromAsciiChecked("Proxy")));
4199}
4200
4201
4202// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
4203BUILTIN(ProxyConstructor_ConstructStub) {
4204 HandleScope scope(isolate);
4205 DCHECK(isolate->proxy_function()->IsConstructor());
4206 Handle<Object> target = args.atOrUndefined(isolate, 1);
4207 Handle<Object> handler = args.atOrUndefined(isolate, 2);
4208 Handle<JSProxy> result;
4209 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
4210 JSProxy::New(isolate, target, handler));
4211 return *result;
4212}
4213
4214
4215// -----------------------------------------------------------------------------
4216// Throwers for restricted function properties and strict arguments object
4217// properties
4218
4219
4220BUILTIN(RestrictedFunctionPropertiesThrower) {
4221 HandleScope scope(isolate);
4222 THROW_NEW_ERROR_RETURN_FAILURE(
4223 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
4224}
4225
4226
4227BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
4228 HandleScope scope(isolate);
4229 THROW_NEW_ERROR_RETURN_FAILURE(
4230 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004231}
4232
4233
Steve Block44f0eee2011-05-26 01:26:41 +01004234// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004235//
4236
4237
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004238namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +00004239
Leon Clarkee46be812010-01-19 14:06:41 +00004240template <bool is_construct>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004241MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
4242 Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
Steve Block44f0eee2011-05-26 01:26:41 +01004243 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004244 Handle<HeapObject> function = args.target<HeapObject>();
4245 Handle<JSReceiver> receiver;
Ben Murdochda12d292016-06-02 14:46:10 +01004246
4247 DCHECK(function->IsFunctionTemplateInfo() ||
4248 Handle<JSFunction>::cast(function)->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00004249
Ben Murdoch097c5b22016-05-18 11:27:45 +01004250 Handle<FunctionTemplateInfo> fun_data =
4251 function->IsFunctionTemplateInfo()
4252 ? Handle<FunctionTemplateInfo>::cast(function)
4253 : handle(JSFunction::cast(*function)->shared()->get_api_func_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00004254 if (is_construct) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004255 DCHECK(args.receiver()->IsTheHole());
4256 if (fun_data->instance_template()->IsUndefined()) {
4257 v8::Local<ObjectTemplate> templ =
4258 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
4259 ToApiHandle<v8::FunctionTemplate>(fun_data));
4260 fun_data->set_instance_template(*Utils::OpenHandle(*templ));
4261 }
4262 Handle<ObjectTemplateInfo> instance_template(
4263 ObjectTemplateInfo::cast(fun_data->instance_template()), isolate);
4264 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
4265 ApiNatives::InstantiateObject(instance_template),
4266 Object);
4267 args[0] = *receiver;
4268 DCHECK_EQ(*receiver, *args.receiver());
4269 } else {
4270 DCHECK(args.receiver()->IsJSReceiver());
4271 receiver = args.at<JSReceiver>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00004272 }
4273
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004274 if (!is_construct && !fun_data->accept_any_receiver()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004275 if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
4276 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
4277 if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
4278 isolate->ReportFailedAccessCheck(js_receiver);
4279 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
4280 }
4281 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004282 }
4283
Ben Murdoch097c5b22016-05-18 11:27:45 +01004284 Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, *receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00004285
4286 if (raw_holder->IsNull()) {
4287 // This function cannot be called with the given receiver. Abort!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004288 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
4289 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +00004290 }
4291
4292 Object* raw_call_data = fun_data->call_code();
4293 if (!raw_call_data->IsUndefined()) {
Ben Murdochda12d292016-06-02 14:46:10 +01004294 DCHECK(raw_call_data->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00004295 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
4296 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004297 v8::FunctionCallback callback =
4298 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00004299 Object* data_obj = call_data->data();
Steve Blocka7e24c12009-10-30 11:49:00 +00004300
Steve Block44f0eee2011-05-26 01:26:41 +01004301 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004302 DCHECK(raw_holder->IsJSObject());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004303
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004304 FunctionCallbackArguments custom(isolate,
4305 data_obj,
4306 *function,
4307 raw_holder,
4308 &args[0] - 1,
4309 args.length() - 1,
4310 is_construct);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004311
Ben Murdochda12d292016-06-02 14:46:10 +01004312 Handle<Object> result = custom.Call(callback);
4313 if (result.is_null()) result = isolate->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00004314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004315 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
4316 if (!is_construct || result->IsJSObject()) {
4317 return scope.CloseAndEscape(result);
4318 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004319 }
4320
Ben Murdoch097c5b22016-05-18 11:27:45 +01004321 return scope.CloseAndEscape(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00004322}
Leon Clarkee46be812010-01-19 14:06:41 +00004323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004324} // namespace
4325
Leon Clarkee46be812010-01-19 14:06:41 +00004326
4327BUILTIN(HandleApiCall) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004328 HandleScope scope(isolate);
4329 Handle<Object> result;
4330 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
4331 HandleApiCallHelper<false>(isolate, args));
4332 return *result;
Leon Clarkee46be812010-01-19 14:06:41 +00004333}
4334
4335
4336BUILTIN(HandleApiCallConstruct) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004337 HandleScope scope(isolate);
4338 Handle<Object> result;
4339 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
4340 HandleApiCallHelper<true>(isolate, args));
4341 return *result;
4342}
4343
Ben Murdoch097c5b22016-05-18 11:27:45 +01004344Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode,
4345 TailCallMode tail_call_mode) {
4346 switch (tail_call_mode) {
4347 case TailCallMode::kDisallow:
4348 switch (mode) {
4349 case ConvertReceiverMode::kNullOrUndefined:
4350 return CallFunction_ReceiverIsNullOrUndefined();
4351 case ConvertReceiverMode::kNotNullOrUndefined:
4352 return CallFunction_ReceiverIsNotNullOrUndefined();
4353 case ConvertReceiverMode::kAny:
4354 return CallFunction_ReceiverIsAny();
4355 }
4356 break;
4357 case TailCallMode::kAllow:
4358 switch (mode) {
4359 case ConvertReceiverMode::kNullOrUndefined:
4360 return TailCallFunction_ReceiverIsNullOrUndefined();
4361 case ConvertReceiverMode::kNotNullOrUndefined:
4362 return TailCallFunction_ReceiverIsNotNullOrUndefined();
4363 case ConvertReceiverMode::kAny:
4364 return TailCallFunction_ReceiverIsAny();
4365 }
4366 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004367 }
4368 UNREACHABLE();
4369 return Handle<Code>::null();
4370}
4371
Ben Murdoch097c5b22016-05-18 11:27:45 +01004372Handle<Code> Builtins::Call(ConvertReceiverMode mode,
4373 TailCallMode tail_call_mode) {
4374 switch (tail_call_mode) {
4375 case TailCallMode::kDisallow:
4376 switch (mode) {
4377 case ConvertReceiverMode::kNullOrUndefined:
4378 return Call_ReceiverIsNullOrUndefined();
4379 case ConvertReceiverMode::kNotNullOrUndefined:
4380 return Call_ReceiverIsNotNullOrUndefined();
4381 case ConvertReceiverMode::kAny:
4382 return Call_ReceiverIsAny();
4383 }
4384 break;
4385 case TailCallMode::kAllow:
4386 switch (mode) {
4387 case ConvertReceiverMode::kNullOrUndefined:
4388 return TailCall_ReceiverIsNullOrUndefined();
4389 case ConvertReceiverMode::kNotNullOrUndefined:
4390 return TailCall_ReceiverIsNotNullOrUndefined();
4391 case ConvertReceiverMode::kAny:
4392 return TailCall_ReceiverIsAny();
4393 }
4394 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004395 }
4396 UNREACHABLE();
4397 return Handle<Code>::null();
4398}
4399
Ben Murdoch097c5b22016-05-18 11:27:45 +01004400Handle<Code> Builtins::CallBoundFunction(TailCallMode tail_call_mode) {
4401 switch (tail_call_mode) {
4402 case TailCallMode::kDisallow:
4403 return CallBoundFunction();
4404 case TailCallMode::kAllow:
4405 return TailCallBoundFunction();
4406 }
4407 UNREACHABLE();
4408 return Handle<Code>::null();
4409}
4410
4411Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode) {
4412 switch (tail_call_mode) {
4413 case TailCallMode::kDisallow:
4414 return InterpreterPushArgsAndCall();
4415 case TailCallMode::kAllow:
4416 return InterpreterPushArgsAndTailCall();
4417 }
4418 UNREACHABLE();
4419 return Handle<Code>::null();
4420}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004421
4422namespace {
4423
4424class RelocatableArguments
4425 : public BuiltinArguments<BuiltinExtraArguments::kTarget>,
4426 public Relocatable {
4427 public:
4428 RelocatableArguments(Isolate* isolate, int length, Object** arguments)
4429 : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
4430 Relocatable(isolate) {}
4431
4432 virtual inline void IterateInstance(ObjectVisitor* v) {
4433 if (length() == 0) return;
4434 v->VisitPointers(lowest_address(), highest_address() + 1);
4435 }
4436
4437 private:
4438 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
4439};
4440
4441} // namespace
4442
Ben Murdoch097c5b22016-05-18 11:27:45 +01004443MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004444 Handle<Object> receiver,
4445 int argc,
4446 Handle<Object> args[]) {
Ben Murdochda12d292016-06-02 14:46:10 +01004447 Isolate* isolate = function->GetIsolate();
4448 // Do proper receiver conversion for non-strict mode api functions.
4449 if (!receiver->IsJSReceiver()) {
4450 DCHECK(function->IsFunctionTemplateInfo() || function->IsJSFunction());
4451 if (function->IsFunctionTemplateInfo() ||
4452 is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
4453 if (receiver->IsUndefined() || receiver->IsNull()) {
4454 receiver = handle(isolate->global_proxy(), isolate);
4455 } else {
4456 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
4457 Object::ToObject(isolate, receiver), Object);
4458 }
4459 }
4460 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004461 // Construct BuiltinArguments object: function, arguments reversed, receiver.
4462 const int kBufferSize = 32;
4463 Object* small_argv[kBufferSize];
4464 Object** argv;
4465 if (argc + 2 <= kBufferSize) {
4466 argv = small_argv;
4467 } else {
4468 argv = new Object* [argc + 2];
4469 }
4470 argv[argc + 1] = *receiver;
4471 for (int i = 0; i < argc; ++i) {
4472 argv[argc - i] = *args[i];
4473 }
4474 argv[0] = *function;
4475 MaybeHandle<Object> result;
4476 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004477 RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
4478 result = HandleApiCallHelper<false>(isolate, arguments);
4479 }
4480 if (argv != small_argv) {
4481 delete[] argv;
4482 }
4483 return result;
Leon Clarkee46be812010-01-19 14:06:41 +00004484}
Steve Blocka7e24c12009-10-30 11:49:00 +00004485
4486
4487// Helper function to handle calls to non-function objects created through the
4488// API. The object can be called as either a constructor (using new) or just as
4489// a function (without new).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004490MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004491 Isolate* isolate, bool is_construct_call,
4492 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004493 Handle<Object> receiver = args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00004494
4495 // Get the object called.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004496 JSObject* obj = JSObject::cast(*receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00004497
4498 // Get the invocation callback from the function descriptor that was
4499 // used to create the called object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004500 DCHECK(obj->map()->is_callable());
4501 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
4502 // TODO(ishell): turn this back to a DCHECK.
4503 CHECK(constructor->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00004504 Object* handler =
Steve Block6ded16b2010-05-10 14:33:55 +01004505 constructor->shared()->get_api_func_data()->instance_call_handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004506 DCHECK(!handler->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004507 // TODO(ishell): remove this debugging code.
4508 CHECK(handler->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00004509 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
4510 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004511 v8::FunctionCallback callback =
4512 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00004513
4514 // Get the data for the call and perform the callback.
Steve Blocka7e24c12009-10-30 11:49:00 +00004515 Object* result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004516 {
Steve Block44f0eee2011-05-26 01:26:41 +01004517 HandleScope scope(isolate);
4518 LOG(isolate, ApiObjectAccess("call non-function", obj));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004519
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004520 FunctionCallbackArguments custom(isolate,
4521 call_data->data(),
4522 constructor,
4523 obj,
4524 &args[0] - 1,
4525 args.length() - 1,
4526 is_construct_call);
Ben Murdochda12d292016-06-02 14:46:10 +01004527 Handle<Object> result_handle = custom.Call(callback);
4528 if (result_handle.is_null()) {
4529 result = isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00004530 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01004531 result = *result_handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00004532 }
4533 }
4534 // Check for exceptions and return result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004535 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004536 return result;
4537}
4538
4539
4540// Handle calls to non-function objects created through the API. This delegate
4541// function is used when the call is a normal function call.
4542BUILTIN(HandleApiCallAsFunction) {
Steve Block44f0eee2011-05-26 01:26:41 +01004543 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004544}
Steve Blocka7e24c12009-10-30 11:49:00 +00004545
4546
4547// Handle calls to non-function objects created through the API. This delegate
4548// function is used when the call is a construct call.
4549BUILTIN(HandleApiCallAsConstructor) {
Steve Block44f0eee2011-05-26 01:26:41 +01004550 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004551}
Steve Blocka7e24c12009-10-30 11:49:00 +00004552
4553
Steve Blocka7e24c12009-10-30 11:49:00 +00004554static void Generate_LoadIC_Miss(MacroAssembler* masm) {
4555 LoadIC::GenerateMiss(masm);
4556}
4557
4558
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004559static void Generate_LoadIC_Normal(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004560 LoadIC::GenerateNormal(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004561}
4562
4563
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004564static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
4565 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
4566}
4567
4568
4569static void Generate_LoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004570 LoadIC::GenerateRuntimeGetProperty(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004571}
4572
4573
Ben Murdoch257744e2011-11-30 15:57:28 +00004574static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004575 KeyedLoadIC::GenerateRuntimeGetProperty(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00004576}
4577
4578
Steve Blocka7e24c12009-10-30 11:49:00 +00004579static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004580 KeyedLoadIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004581}
4582
4583
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004584static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004585 KeyedLoadIC::GenerateMegamorphic(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004586}
4587
Steve Block1e0659c2011-05-24 12:43:12 +01004588
Steve Blocka7e24c12009-10-30 11:49:00 +00004589static void Generate_StoreIC_Miss(MacroAssembler* masm) {
4590 StoreIC::GenerateMiss(masm);
4591}
4592
4593
Steve Block8defd9f2010-07-08 12:39:36 +01004594static void Generate_StoreIC_Normal(MacroAssembler* masm) {
4595 StoreIC::GenerateNormal(masm);
4596}
4597
4598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004599static void Generate_StoreIC_Slow(MacroAssembler* masm) {
4600 NamedStoreHandlerCompiler::GenerateSlow(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00004601}
4602
4603
4604static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004605 ElementHandlerCompiler::GenerateStoreSlow(masm);
4606}
4607
4608
4609static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
4610 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
4611}
4612
4613
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004614static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
4615 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
4616}
4617
4618
4619static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
4620 KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
4621}
4622
4623
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004624static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
4625 KeyedStoreIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004626}
4627
4628
4629static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
4630 KeyedStoreIC::GenerateInitialize(masm);
4631}
4632
4633
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004634static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
4635 KeyedStoreIC::GenerateInitialize(masm);
4636}
4637
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004638
4639static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
4640 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004641}
Ben Murdoche0cee9b2011-05-25 10:26:03 +01004642
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004643
4644static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
4645 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004646}
4647
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004648
Steve Blocka7e24c12009-10-30 11:49:00 +00004649static void Generate_Return_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004650 DebugCodegen::GenerateDebugBreakStub(masm,
4651 DebugCodegen::SAVE_RESULT_REGISTER);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01004652}
4653
4654
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004655static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004656 DebugCodegen::GenerateDebugBreakStub(masm,
4657 DebugCodegen::IGNORE_RESULT_REGISTER);
Steve Block6ded16b2010-05-10 14:33:55 +01004658}
4659
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004660
Steve Block6ded16b2010-05-10 14:33:55 +01004661static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004662 DebugCodegen::GenerateFrameDropperLiveEdit(masm);
Steve Block6ded16b2010-05-10 14:33:55 +01004663}
Steve Blocka7e24c12009-10-30 11:49:00 +00004664
Steve Block44f0eee2011-05-26 01:26:41 +01004665
4666Builtins::Builtins() : initialized_(false) {
4667 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
4668 memset(names_, 0, sizeof(names_[0]) * builtin_count);
4669}
4670
4671
4672Builtins::~Builtins() {
4673}
4674
Steve Blocka7e24c12009-10-30 11:49:00 +00004675
Leon Clarkee46be812010-01-19 14:06:41 +00004676#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
Steve Block44f0eee2011-05-26 01:26:41 +01004677Address const Builtins::c_functions_[cfunction_count] = {
4678 BUILTIN_LIST_C(DEF_ENUM_C)
4679};
Steve Blocka7e24c12009-10-30 11:49:00 +00004680#undef DEF_ENUM_C
4681
Steve Blocka7e24c12009-10-30 11:49:00 +00004682
Steve Block44f0eee2011-05-26 01:26:41 +01004683struct BuiltinDesc {
Ben Murdochda12d292016-06-02 14:46:10 +01004684 Handle<Code> (*builder)(Isolate*, struct BuiltinDesc const*);
Steve Block44f0eee2011-05-26 01:26:41 +01004685 byte* generator;
4686 byte* c_code;
4687 const char* s_name; // name is only used for generating log information.
4688 int name;
4689 Code::Flags flags;
4690 BuiltinExtraArguments extra_args;
Ben Murdochda12d292016-06-02 14:46:10 +01004691 int argc;
Steve Block44f0eee2011-05-26 01:26:41 +01004692};
4693
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004694#define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
4695
Steve Block44f0eee2011-05-26 01:26:41 +01004696class BuiltinFunctionTable {
4697 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004698 BuiltinDesc* functions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004699 base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004700 return functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01004701 }
4702
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004703 base::OnceType once_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004704 BuiltinDesc functions_[Builtins::builtin_count + 1];
Steve Block44f0eee2011-05-26 01:26:41 +01004705
4706 friend class Builtins;
4707};
4708
Ben Murdochda12d292016-06-02 14:46:10 +01004709namespace {
4710
4711BuiltinFunctionTable builtin_function_table = BUILTIN_FUNCTION_TABLE_INIT;
4712
4713Handle<Code> MacroAssemblerBuilder(Isolate* isolate,
4714 BuiltinDesc const* builtin_desc) {
4715// For now we generate builtin adaptor code into a stack-allocated
4716// buffer, before copying it into individual code objects. Be careful
4717// with alignment, some platforms don't like unaligned code.
4718#ifdef DEBUG
4719 // We can generate a lot of debug code on Arm64.
4720 const size_t buffer_size = 32 * KB;
4721#elif V8_TARGET_ARCH_PPC64
4722 // 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
4723 const size_t buffer_size = 10 * KB;
4724#else
4725 const size_t buffer_size = 8 * KB;
4726#endif
4727 union {
4728 int force_alignment;
4729 byte buffer[buffer_size]; // NOLINT(runtime/arrays)
4730 } u;
4731
4732 MacroAssembler masm(isolate, u.buffer, sizeof(u.buffer),
4733 CodeObjectRequired::kYes);
4734 // Generate the code/adaptor.
4735 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
4736 Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
4737 // We pass all arguments to the generator, but it may not use all of
4738 // them. This works because the first arguments are on top of the
4739 // stack.
4740 DCHECK(!masm.has_frame());
4741 g(&masm, builtin_desc->name, builtin_desc->extra_args);
4742 // Move the code into the object heap.
4743 CodeDesc desc;
4744 masm.GetCode(&desc);
4745 Code::Flags flags = builtin_desc->flags;
4746 return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
4747}
4748
4749Handle<Code> CodeStubAssemblerBuilder(Isolate* isolate,
4750 BuiltinDesc const* builtin_desc) {
4751 Zone zone(isolate->allocator());
4752 compiler::CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
4753 builtin_desc->flags,
4754 builtin_desc->s_name);
4755 // Generate the code/adaptor.
4756 typedef void (*Generator)(compiler::CodeStubAssembler*);
4757 Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
4758 g(&assembler);
4759 return assembler.GenerateCode();
4760}
4761
4762} // namespace
Steve Block44f0eee2011-05-26 01:26:41 +01004763
4764// Define array of pointers to generators and C builtin functions.
4765// We do this in a sort of roundabout way so that we can do the initialization
4766// within the lexical scope of Builtins:: and within a context where
4767// Code::Flags names a non-abstract type.
4768void Builtins::InitBuiltinFunctionTable() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004769 BuiltinDesc* functions = builtin_function_table.functions_;
Ben Murdochda12d292016-06-02 14:46:10 +01004770 functions[builtin_count].builder = nullptr;
4771 functions[builtin_count].generator = nullptr;
4772 functions[builtin_count].c_code = nullptr;
4773 functions[builtin_count].s_name = nullptr;
Steve Block44f0eee2011-05-26 01:26:41 +01004774 functions[builtin_count].name = builtin_count;
4775 functions[builtin_count].flags = static_cast<Code::Flags>(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004776 functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
Ben Murdochda12d292016-06-02 14:46:10 +01004777 functions[builtin_count].argc = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01004778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004779#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
Ben Murdochda12d292016-06-02 14:46:10 +01004780 functions->builder = &MacroAssemblerBuilder; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004781 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
4782 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
4783 functions->s_name = #aname; \
4784 functions->name = c_##aname; \
4785 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
4786 functions->extra_args = BuiltinExtraArguments::aextra_args; \
Ben Murdochda12d292016-06-02 14:46:10 +01004787 functions->argc = 0; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004788 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01004789
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004790#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
Ben Murdochda12d292016-06-02 14:46:10 +01004791 functions->builder = &MacroAssemblerBuilder; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004792 functions->generator = FUNCTION_ADDR(Generate_##aname); \
4793 functions->c_code = NULL; \
4794 functions->s_name = #aname; \
4795 functions->name = k##aname; \
4796 functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
4797 functions->extra_args = BuiltinExtraArguments::kNone; \
Ben Murdochda12d292016-06-02 14:46:10 +01004798 functions->argc = 0; \
4799 ++functions;
4800
4801#define DEF_FUNCTION_PTR_T(aname, aargc) \
4802 functions->builder = &CodeStubAssemblerBuilder; \
4803 functions->generator = FUNCTION_ADDR(Generate_##aname); \
4804 functions->c_code = NULL; \
4805 functions->s_name = #aname; \
4806 functions->name = k##aname; \
4807 functions->flags = \
4808 Code::ComputeFlags(Code::BUILTIN, UNINITIALIZED, kNoExtraICState); \
4809 functions->extra_args = BuiltinExtraArguments::kNone; \
4810 functions->argc = aargc; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004811 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01004812
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004813#define DEF_FUNCTION_PTR_H(aname, kind) \
Ben Murdochda12d292016-06-02 14:46:10 +01004814 functions->builder = &MacroAssemblerBuilder; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004815 functions->generator = FUNCTION_ADDR(Generate_##aname); \
4816 functions->c_code = NULL; \
4817 functions->s_name = #aname; \
4818 functions->name = k##aname; \
4819 functions->flags = Code::ComputeHandlerFlags(Code::kind); \
4820 functions->extra_args = BuiltinExtraArguments::kNone; \
Ben Murdochda12d292016-06-02 14:46:10 +01004821 functions->argc = 0; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004822 ++functions;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004823
Steve Block44f0eee2011-05-26 01:26:41 +01004824 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
4825 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
Ben Murdochda12d292016-06-02 14:46:10 +01004826 BUILTIN_LIST_T(DEF_FUNCTION_PTR_T)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004827 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01004828 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
4829
4830#undef DEF_FUNCTION_PTR_C
4831#undef DEF_FUNCTION_PTR_A
Ben Murdochda12d292016-06-02 14:46:10 +01004832#undef DEF_FUNCTION_PTR_H
4833#undef DEF_FUNCTION_PTR_T
Steve Block44f0eee2011-05-26 01:26:41 +01004834}
4835
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004836
4837void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
4838 DCHECK(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +00004839
4840 // Create a scope for the handles in the builtins.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004841 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004842
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004843 const BuiltinDesc* functions = builtin_function_table.functions();
Steve Blocka7e24c12009-10-30 11:49:00 +00004844
Steve Blocka7e24c12009-10-30 11:49:00 +00004845 // Traverse the list of builtins and generate an adaptor in a
4846 // separate code object for each one.
4847 for (int i = 0; i < builtin_count; i++) {
4848 if (create_heap_objects) {
Ben Murdochda12d292016-06-02 14:46:10 +01004849 Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
Steve Blocka7e24c12009-10-30 11:49:00 +00004850 // Log the event and add the code to the builtins array.
Ben Murdoch8b112d22011-06-08 16:22:53 +01004851 PROFILE(isolate,
Ben Murdochda12d292016-06-02 14:46:10 +01004852 CodeCreateEvent(Logger::BUILTIN_TAG, AbstractCode::cast(*code),
4853 functions[i].s_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004854 builtins_[i] = *code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004855 code->set_builtin_index(i);
Steve Blocka7e24c12009-10-30 11:49:00 +00004856#ifdef ENABLE_DISASSEMBLER
4857 if (FLAG_print_builtin_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004858 CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
4859 OFStream os(trace_scope.file());
4860 os << "Builtin: " << functions[i].s_name << "\n";
4861 code->Disassemble(functions[i].s_name, os);
4862 os << "\n";
Steve Blocka7e24c12009-10-30 11:49:00 +00004863 }
4864#endif
4865 } else {
4866 // Deserializing. The values will be filled in during IterateBuiltins.
4867 builtins_[i] = NULL;
4868 }
4869 names_[i] = functions[i].s_name;
4870 }
4871
4872 // Mark as initialized.
Steve Block44f0eee2011-05-26 01:26:41 +01004873 initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00004874}
4875
4876
4877void Builtins::TearDown() {
Steve Block44f0eee2011-05-26 01:26:41 +01004878 initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00004879}
4880
4881
4882void Builtins::IterateBuiltins(ObjectVisitor* v) {
4883 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
4884}
4885
4886
4887const char* Builtins::Lookup(byte* pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01004888 // may be called during initialization (disassembler!)
4889 if (initialized_) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004890 for (int i = 0; i < builtin_count; i++) {
4891 Code* entry = Code::cast(builtins_[i]);
4892 if (entry->contains(pc)) {
4893 return names_[i];
4894 }
4895 }
4896 }
4897 return NULL;
4898}
4899
Ben Murdochb0fe1622011-05-05 13:52:32 +01004900
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004901void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004902 masm->TailCallRuntime(Runtime::kInterrupt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004903}
4904
4905
4906void Builtins::Generate_StackCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004907 masm->TailCallRuntime(Runtime::kStackGuard);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004908}
4909
4910
Steve Block44f0eee2011-05-26 01:26:41 +01004911#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
4912Handle<Code> Builtins::name() { \
4913 Code** code_address = \
4914 reinterpret_cast<Code**>(builtin_address(k##name)); \
4915 return Handle<Code>(code_address); \
4916}
4917#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
4918Handle<Code> Builtins::name() { \
4919 Code** code_address = \
4920 reinterpret_cast<Code**>(builtin_address(k##name)); \
4921 return Handle<Code>(code_address); \
4922}
Ben Murdochda12d292016-06-02 14:46:10 +01004923#define DEFINE_BUILTIN_ACCESSOR_T(name, argc) \
4924 Handle<Code> Builtins::name() { \
4925 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
4926 return Handle<Code>(code_address); \
4927 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004928#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
4929Handle<Code> Builtins::name() { \
4930 Code** code_address = \
4931 reinterpret_cast<Code**>(builtin_address(k##name)); \
4932 return Handle<Code>(code_address); \
4933}
Steve Block44f0eee2011-05-26 01:26:41 +01004934BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
4935BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
Ben Murdochda12d292016-06-02 14:46:10 +01004936BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004937BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01004938BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4939#undef DEFINE_BUILTIN_ACCESSOR_C
4940#undef DEFINE_BUILTIN_ACCESSOR_A
Ben Murdochda12d292016-06-02 14:46:10 +01004941#undef DEFINE_BUILTIN_ACCESSOR_T
4942#undef DEFINE_BUILTIN_ACCESSOR_H
Steve Block44f0eee2011-05-26 01:26:41 +01004943
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004944} // namespace internal
4945} // namespace v8