blob: 75f6150c77a34af1050e7edc2abc99a6cff86860 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/builtins.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochda12d292016-06-02 14:46:10 +01007#include "src/api-arguments.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/api-natives.h"
Ben Murdochc5610432016-08-08 18:44:38 +01009#include "src/api.h"
Ben 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"
Ben Murdochc5610432016-08-08 18:44:38 +010013#include "src/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 Murdochc5610432016-08-08 18:44:38 +010026#include "src/uri.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000028
29namespace v8 {
30namespace internal {
31
Leon Clarkee46be812010-01-19 14:06:41 +000032namespace {
33
34// Arguments object passed to C++ builtins.
35template <BuiltinExtraArguments extra_args>
36class BuiltinArguments : public Arguments {
37 public:
38 BuiltinArguments(int length, Object** arguments)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 : Arguments(length, arguments) {
40 // Check we have at least the receiver.
41 DCHECK_LE(1, this->length());
42 }
Leon Clarkee46be812010-01-19 14:06:41 +000043
44 Object*& operator[] (int index) {
Ben Murdochc5610432016-08-08 18:44:38 +010045 DCHECK_LT(index, length());
Leon Clarkee46be812010-01-19 14:06:41 +000046 return Arguments::operator[](index);
47 }
48
49 template <class S> Handle<S> at(int index) {
Ben Murdochc5610432016-08-08 18:44:38 +010050 DCHECK_LT(index, length());
Leon Clarkee46be812010-01-19 14:06:41 +000051 return Arguments::at<S>(index);
52 }
53
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054 Handle<Object> atOrUndefined(Isolate* isolate, int index) {
55 if (index >= length()) {
56 return isolate->factory()->undefined_value();
57 }
58 return at<Object>(index);
59 }
60
Leon Clarkee46be812010-01-19 14:06:41 +000061 Handle<Object> receiver() {
62 return Arguments::at<Object>(0);
63 }
64
Ben Murdoch097c5b22016-05-18 11:27:45 +010065 template <class S>
66 Handle<S> target();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 Handle<HeapObject> new_target();
Leon Clarkee46be812010-01-19 14:06:41 +000068
69 // Gets the total number of arguments including the receiver (but
70 // excluding extra arguments).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 int length() const;
Leon Clarkee46be812010-01-19 14:06:41 +000072};
73
74
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075// Specialize BuiltinArguments for the extra arguments.
Leon Clarkee46be812010-01-19 14:06:41 +000076
77template <>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
79 return Arguments::length();
80}
81
82template <>
83int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
Leon Clarkee46be812010-01-19 14:06:41 +000084 return Arguments::length() - 1;
85}
86
Leon Clarkee46be812010-01-19 14:06:41 +000087template <>
Ben Murdoch097c5b22016-05-18 11:27:45 +010088template <class S>
89Handle<S> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
90 return Arguments::at<S>(Arguments::length() - 1);
Leon Clarkee46be812010-01-19 14:06:41 +000091}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092
93template <>
94int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
95 return Arguments::length() - 1;
96}
97
98template <>
99Handle<HeapObject>
100BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
101 return Arguments::at<HeapObject>(Arguments::length() - 1);
102}
103
104template <>
105int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
106 const {
107 return Arguments::length() - 2;
108}
109
110template <>
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111template <class S>
112Handle<S>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100114 return Arguments::at<S>(Arguments::length() - 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115}
116
117template <>
118Handle<HeapObject>
119BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
120 return Arguments::at<HeapObject>(Arguments::length() - 1);
121}
Leon Clarkee46be812010-01-19 14:06:41 +0000122
123
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124#define DEF_ARG_TYPE(name, spec) \
125 typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
Leon Clarkee46be812010-01-19 14:06:41 +0000126BUILTIN_LIST_C(DEF_ARG_TYPE)
127#undef DEF_ARG_TYPE
128
Leon Clarkee46be812010-01-19 14:06:41 +0000129
Steve Blocka7e24c12009-10-30 11:49:00 +0000130// ----------------------------------------------------------------------------
Leon Clarkee46be812010-01-19 14:06:41 +0000131// Support macro for defining builtins in C++.
Steve Blocka7e24c12009-10-30 11:49:00 +0000132// ----------------------------------------------------------------------------
133//
134// A builtin function is defined by writing:
135//
136// BUILTIN(name) {
137// ...
138// }
Steve Blocka7e24c12009-10-30 11:49:00 +0000139//
Leon Clarkee46be812010-01-19 14:06:41 +0000140// In the body of the builtin function the arguments can be accessed
141// through the BuiltinArguments object args.
Ben Murdochc5610432016-08-08 18:44:38 +0100142// TODO(cbruni): add global flag to check whether any tracing events have been
143// enabled.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100144#define BUILTIN(name) \
145 MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
146 Isolate* isolate); \
Ben Murdochc5610432016-08-08 18:44:38 +0100147 \
148 V8_NOINLINE static Object* Builtin_Impl_Stats_##name( \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100149 int args_length, Object** args_object, Isolate* isolate) { \
Ben Murdochc5610432016-08-08 18:44:38 +0100150 name##ArgumentsType args(args_length, args_object); \
151 RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Builtin_##name); \
Ben Murdochda12d292016-06-02 14:46:10 +0100152 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
153 "V8.Builtin_" #name); \
Ben Murdochc5610432016-08-08 18:44:38 +0100154 return Builtin_Impl_##name(args, isolate); \
155 } \
156 \
157 MUST_USE_RESULT static Object* Builtin_##name( \
158 int args_length, Object** args_object, Isolate* isolate) { \
Ben Murdochda12d292016-06-02 14:46:10 +0100159 if (FLAG_runtime_call_stats) { \
Ben Murdochc5610432016-08-08 18:44:38 +0100160 return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \
Ben Murdochda12d292016-06-02 14:46:10 +0100161 } \
Ben Murdochc5610432016-08-08 18:44:38 +0100162 name##ArgumentsType args(args_length, args_object); \
163 return Builtin_Impl_##name(args, isolate); \
Ben Murdoch097c5b22016-05-18 11:27:45 +0100164 } \
165 \
166 MUST_USE_RESULT static Object* Builtin_Impl_##name(name##ArgumentsType args, \
167 Isolate* isolate)
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
169// ----------------------------------------------------------------------------
170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171#define CHECK_RECEIVER(Type, name, method) \
172 if (!args.receiver()->Is##Type()) { \
173 THROW_NEW_ERROR_RETURN_FAILURE( \
174 isolate, \
175 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
176 isolate->factory()->NewStringFromAsciiChecked(method), \
177 args.receiver())); \
178 } \
179 Handle<Type> name = Handle<Type>::cast(args.receiver())
180
181
182inline bool ClampedToInteger(Object* object, int* out) {
183 // This is an extended version of ECMA-262 7.1.11 handling signed values
184 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
185 if (object->IsSmi()) {
186 *out = Smi::cast(object)->value();
187 return true;
188 } else if (object->IsHeapNumber()) {
189 double value = HeapNumber::cast(object)->value();
190 if (std::isnan(value)) {
191 *out = 0;
192 } else if (value > kMaxInt) {
193 *out = kMaxInt;
194 } else if (value < kMinInt) {
195 *out = kMinInt;
196 } else {
197 *out = static_cast<int>(value);
198 }
199 return true;
200 } else if (object->IsUndefined() || object->IsNull()) {
201 *out = 0;
202 return true;
203 } else if (object->IsBoolean()) {
204 *out = object->IsTrue();
205 return true;
206 }
207 return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000208}
Steve Blocka7e24c12009-10-30 11:49:00 +0000209
210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
212 int* out) {
Ben Murdochc5610432016-08-08 18:44:38 +0100213 Context* context = *isolate->native_context();
214 Map* map = object->map();
215 if (map != context->sloppy_arguments_map() &&
216 map != context->strict_arguments_map() &&
217 map != context->fast_aliased_arguments_map()) {
218 return false;
219 }
220 DCHECK(object->HasFastElements() || object->HasFastArgumentsElements());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100221 Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 if (!len_obj->IsSmi()) return false;
223 *out = Max(0, Smi::cast(len_obj)->value());
224 return *out <= object->elements()->length();
Steve Blocka7e24c12009-10-30 11:49:00 +0000225}
Steve Blocka7e24c12009-10-30 11:49:00 +0000226
Ben Murdochda12d292016-06-02 14:46:10 +0100227inline bool PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 DisallowHeapAllocation no_gc;
Ben Murdochda12d292016-06-02 14:46:10 +0100229 HeapObject* prototype = HeapObject::cast(object->map()->prototype());
230 HeapObject* null = isolate->heap()->null_value();
231 HeapObject* empty = isolate->heap()->empty_fixed_array();
232 while (prototype != null) {
233 Map* map = prototype->map();
234 if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false;
235 if (JSObject::cast(prototype)->elements() != empty) return false;
236 prototype = HeapObject::cast(map->prototype());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238 return true;
239}
240
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
242 JSArray* receiver) {
Ben Murdochda12d292016-06-02 14:46:10 +0100243 return PrototypeHasNoElements(isolate, receiver);
Steve Block6ded16b2010-05-10 14:33:55 +0100244}
245
Ben Murdoch097c5b22016-05-18 11:27:45 +0100246inline bool HasSimpleElements(JSObject* current) {
Ben Murdochda12d292016-06-02 14:46:10 +0100247 return current->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
248 !current->GetElementsAccessor()->HasAccessors(current);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100249}
250
251inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
Ben Murdochda12d292016-06-02 14:46:10 +0100252 JSObject* receiver) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100253 // Check that we have no accessors on the receiver's elements.
Ben Murdochda12d292016-06-02 14:46:10 +0100254 if (!HasSimpleElements(receiver)) return false;
255 return PrototypeHasNoElements(isolate, receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100256}
257
258inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100259 DisallowHeapAllocation no_gc;
260 PrototypeIterator iter(isolate, receiver,
261 PrototypeIterator::START_AT_RECEIVER);
262 for (; !iter.IsAtEnd(); iter.Advance()) {
263 if (iter.GetCurrent()->IsJSProxy()) return false;
264 JSObject* current = iter.GetCurrent<JSObject>();
265 if (!HasSimpleElements(current)) return false;
266 }
267 return true;
268}
Steve Block6ded16b2010-05-10 14:33:55 +0100269
Ben Murdochda12d292016-06-02 14:46:10 +0100270// Returns |false| if not applicable.
John Reck59135872010-11-02 12:39:01 -0700271MUST_USE_RESULT
Ben Murdochda12d292016-06-02 14:46:10 +0100272inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
273 Handle<Object> receiver,
274 Arguments* args,
275 int first_added_arg) {
276 if (!receiver->IsJSArray()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000277 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Ben Murdochda12d292016-06-02 14:46:10 +0100278 ElementsKind origin_kind = array->GetElementsKind();
279 if (IsDictionaryElementsKind(origin_kind)) return false;
Ben Murdochda12d292016-06-02 14:46:10 +0100280 if (!array->map()->is_extensible()) return false;
281 if (args == nullptr) return true;
282
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 // If there may be elements accessors in the prototype chain, the fast path
284 // cannot be used if there arguments to add to the array.
Ben Murdochda12d292016-06-02 14:46:10 +0100285 if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100286
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 // Adding elements to the array prototype would break code that makes sure
288 // it has no elements. Handle that elsewhere.
Ben Murdochda12d292016-06-02 14:46:10 +0100289 if (isolate->IsAnyInitialArrayPrototype(array)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100291 // Need to ensure that the arguments passed in args can be contained in
292 // the array.
293 int args_length = args->length();
Ben Murdochda12d292016-06-02 14:46:10 +0100294 if (first_added_arg >= args_length) return true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100295
Ben Murdochda12d292016-06-02 14:46:10 +0100296 if (IsFastObjectElementsKind(origin_kind)) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 ElementsKind target_kind = origin_kind;
298 {
299 DisallowHeapAllocation no_gc;
Ben Murdochda12d292016-06-02 14:46:10 +0100300 for (int i = first_added_arg; i < args_length; i++) {
301 Object* arg = (*args)[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 if (arg->IsHeapObject()) {
303 if (arg->IsHeapNumber()) {
304 target_kind = FAST_DOUBLE_ELEMENTS;
305 } else {
306 target_kind = FAST_ELEMENTS;
307 break;
308 }
309 }
310 }
311 }
312 if (target_kind != origin_kind) {
Ben Murdochda12d292016-06-02 14:46:10 +0100313 // Use a short-lived HandleScope to avoid creating several copies of the
314 // elements handle which would cause issues when left-trimming later-on.
315 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316 JSObject::TransitionElementsKind(array, target_kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 }
Ben Murdochda12d292016-06-02 14:46:10 +0100318 return true;
Steve Block6ded16b2010-05-10 14:33:55 +0100319}
320
321
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322MUST_USE_RESULT static Object* CallJsIntrinsic(
323 Isolate* isolate, Handle<JSFunction> function,
324 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100325 HandleScope handleScope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100326 int argc = args.length() - 1;
327 ScopedVector<Handle<Object> > argv(argc);
328 for (int i = 0; i < argc; ++i) {
329 argv[i] = args.at<Object>(i + 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100330 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000331 Handle<Object> result;
332 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
333 isolate, result,
334 Execution::Call(isolate,
335 function,
336 args.receiver(),
337 argc,
338 argv.start()));
Steve Block6ded16b2010-05-10 14:33:55 +0100339 return *result;
340}
341
342
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343} // namespace
344
345
346BUILTIN(Illegal) {
347 UNREACHABLE();
348 return isolate->heap()->undefined_value(); // Make compiler happy.
349}
350
351
352BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
353
Ben Murdochc5610432016-08-08 18:44:38 +0100354void Builtins::Generate_ArrayIsArray(CodeStubAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100355 typedef compiler::Node Node;
Ben Murdochc5610432016-08-08 18:44:38 +0100356 typedef CodeStubAssembler::Label Label;
357
358 Node* object = assembler->Parameter(1);
359 Node* context = assembler->Parameter(4);
360
361 Label call_runtime(assembler), return_true(assembler),
362 return_false(assembler);
363
364 assembler->GotoIf(assembler->WordIsSmi(object), &return_false);
365 Node* instance_type = assembler->LoadInstanceType(object);
366
367 assembler->GotoIf(assembler->Word32Equal(
368 instance_type, assembler->Int32Constant(JS_ARRAY_TYPE)),
369 &return_true);
370
371 // TODO(verwaest): Handle proxies in-place.
372 assembler->Branch(assembler->Word32Equal(
373 instance_type, assembler->Int32Constant(JS_PROXY_TYPE)),
374 &call_runtime, &return_false);
375
376 assembler->Bind(&return_true);
377 assembler->Return(assembler->BooleanConstant(true));
378
379 assembler->Bind(&return_false);
380 assembler->Return(assembler->BooleanConstant(false));
381
382 assembler->Bind(&call_runtime);
383 assembler->Return(
384 assembler->CallRuntime(Runtime::kArrayIsArray, context, object));
385}
386
387void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
388 typedef compiler::Node Node;
389 typedef CodeStubAssembler::Label Label;
390 typedef CodeStubAssembler::Variable Variable;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391
Ben Murdochda12d292016-06-02 14:46:10 +0100392 Node* object = assembler->Parameter(0);
393 Node* key = assembler->Parameter(1);
394 Node* context = assembler->Parameter(4);
395
396 Label call_runtime(assembler), return_true(assembler),
397 return_false(assembler);
398
399 // Smi receivers do not have own properties.
400 Label if_objectisnotsmi(assembler);
401 assembler->Branch(assembler->WordIsSmi(object), &return_false,
402 &if_objectisnotsmi);
403 assembler->Bind(&if_objectisnotsmi);
404
405 Node* map = assembler->LoadMap(object);
406 Node* instance_type = assembler->LoadMapInstanceType(map);
407
408 Variable var_index(assembler, MachineRepresentation::kWord32);
409
Ben Murdochc5610432016-08-08 18:44:38 +0100410 Label keyisindex(assembler), if_iskeyunique(assembler);
411 assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
412 &call_runtime);
Ben Murdochda12d292016-06-02 14:46:10 +0100413
Ben Murdochda12d292016-06-02 14:46:10 +0100414 assembler->Bind(&if_iskeyunique);
Ben Murdochc5610432016-08-08 18:44:38 +0100415 assembler->TryLookupProperty(object, map, instance_type, key, &return_true,
416 &return_false, &call_runtime);
Ben Murdochda12d292016-06-02 14:46:10 +0100417
418 assembler->Bind(&keyisindex);
Ben Murdochc5610432016-08-08 18:44:38 +0100419 assembler->TryLookupElement(object, map, instance_type, var_index.value(),
420 &return_true, &return_false, &call_runtime);
Ben Murdochda12d292016-06-02 14:46:10 +0100421
422 assembler->Bind(&return_true);
423 assembler->Return(assembler->BooleanConstant(true));
424
425 assembler->Bind(&return_false);
426 assembler->Return(assembler->BooleanConstant(false));
427
428 assembler->Bind(&call_runtime);
429 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
430 context, object, key));
431}
432
433namespace {
434
435Object* DoArrayPush(Isolate* isolate,
436 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000437 HandleScope scope(isolate);
438 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100439 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 return CallJsIntrinsic(isolate, isolate->array_push(), args);
John Reck59135872010-11-02 12:39:01 -0700441 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 // Fast Elements Path
Ben Murdochda12d292016-06-02 14:46:10 +0100443 int to_add = args.length() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000444 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000445 int len = Smi::cast(array->length())->value();
Ben Murdochda12d292016-06-02 14:46:10 +0100446 if (to_add == 0) return Smi::FromInt(len);
447
448 // Currently fixed arrays cannot grow too big, so we should never hit this.
449 DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
450
451 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 return CallJsIntrinsic(isolate, isolate->array_push(), args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000453 }
Ben Murdochda12d292016-06-02 14:46:10 +0100454
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000455 ElementsAccessor* accessor = array->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100456 int new_length = accessor->Push(array, &args, to_add);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 return Smi::FromInt(new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000458}
Steve Blocka7e24c12009-10-30 11:49:00 +0000459
Ben Murdochda12d292016-06-02 14:46:10 +0100460} // namespace
461
462BUILTIN(ArrayPush) { return DoArrayPush(isolate, args); }
463
464// TODO(verwaest): This is a temporary helper until the FastArrayPush stub can
465// tailcall to the builtin directly.
466RUNTIME_FUNCTION(Runtime_ArrayPush) {
467 DCHECK_EQ(2, args.length());
468 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
469 // Rewrap the arguments as builtins arguments.
470 BuiltinArguments<BuiltinExtraArguments::kNone> caller_args(
471 incoming->length() + 1, incoming->arguments() + 1);
472 return DoArrayPush(isolate, caller_args);
473}
Steve Blocka7e24c12009-10-30 11:49:00 +0000474
475BUILTIN(ArrayPop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 HandleScope scope(isolate);
477 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100478 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
John Reck59135872010-11-02 12:39:01 -0700480 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481
482 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000483
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485 if (len == 0) return isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000486
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400487 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 return CallJsIntrinsic(isolate, isolate->array_pop(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400489 }
490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000491 Handle<Object> result;
492 if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
493 // Fast Elements Path
Ben Murdochda12d292016-06-02 14:46:10 +0100494 result = array->GetElementsAccessor()->Pop(array);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495 } else {
496 // Use Slow Lookup otherwise
497 uint32_t new_length = len - 1;
498 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdochda12d292016-06-02 14:46:10 +0100499 isolate, result, JSReceiver::GetElement(isolate, array, new_length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 JSArray::SetLength(array, new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000502 return *result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000503}
Steve Blocka7e24c12009-10-30 11:49:00 +0000504
505
Andrei Popescu402d9372010-02-26 13:31:12 +0000506BUILTIN(ArrayShift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100508 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100510 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, nullptr, 0) ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
512 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100513 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Andrei Popescu402d9372010-02-26 13:31:12 +0000515
516 int len = Smi::cast(array->length())->value();
Steve Block44f0eee2011-05-26 01:26:41 +0100517 if (len == 0) return heap->undefined_value();
Andrei Popescu402d9372010-02-26 13:31:12 +0000518
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400519 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 return CallJsIntrinsic(isolate, isolate->array_shift(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400521 }
522
Ben Murdochda12d292016-06-02 14:46:10 +0100523 Handle<Object> first = array->GetElementsAccessor()->Shift(array);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524 return *first;
Andrei Popescu402d9372010-02-26 13:31:12 +0000525}
526
527
528BUILTIN(ArrayUnshift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100531 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100533 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Andrei Popescu402d9372010-02-26 13:31:12 +0000535 int to_add = args.length() - 1;
Ben Murdochda12d292016-06-02 14:46:10 +0100536 if (to_add == 0) return array->length();
Andrei Popescu402d9372010-02-26 13:31:12 +0000537
Ben Murdochda12d292016-06-02 14:46:10 +0100538 // Currently fixed arrays cannot grow too big, so we should never hit this.
539 DCHECK_LE(to_add, Smi::kMaxValue - Smi::cast(array->length())->value());
540
541 if (JSArray::HasReadOnlyLength(array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 }
544
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545 ElementsAccessor* accessor = array->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100546 int new_length = accessor->Unshift(array, &args, to_add);
Andrei Popescu402d9372010-02-26 13:31:12 +0000547 return Smi::FromInt(new_length);
548}
549
550
Andrei Popescu402d9372010-02-26 13:31:12 +0000551BUILTIN(ArraySlice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000553 Handle<Object> receiver = args.receiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100554 int len = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 int relative_start = 0;
556 int relative_end = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 if (receiver->IsJSArray()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 JSArray* array = JSArray::cast(*receiver);
Ben Murdochda12d292016-06-02 14:46:10 +0100561 if (V8_UNLIKELY(!array->HasFastElements() ||
562 !IsJSArrayFastElementMovingAllowed(isolate, array) ||
563 !isolate->IsArraySpeciesLookupChainIntact() ||
564 // If this is a subclass of Array, then call out to JS
565 !array->HasArrayPrototype(isolate))) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 AllowHeapAllocation allow_allocation;
567 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Steve Block9fac8402011-05-12 15:51:54 +0100568 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 len = Smi::cast(array->length())->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 } else if (receiver->IsJSObject() &&
571 GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
572 &len)) {
Ben Murdochc5610432016-08-08 18:44:38 +0100573 // Array.prototype.slice.call(arguments, ...) is quite a common idiom
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 // (notably more than 50% of invocations in Web apps).
575 // Treat it in C++ as well.
Ben Murdochc5610432016-08-08 18:44:38 +0100576 DCHECK(JSObject::cast(*receiver)->HasFastElements() ||
577 JSObject::cast(*receiver)->HasFastArgumentsElements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 } else {
579 AllowHeapAllocation allow_allocation;
580 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
581 }
Ben Murdochda12d292016-06-02 14:46:10 +0100582 DCHECK_LE(0, len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 int argument_count = args.length() - 1;
584 // Note carefully chosen defaults---if argument is missing,
585 // it's undefined which gets converted to 0 for relative_start
586 // and to len for relative_end.
587 relative_start = 0;
588 relative_end = len;
589 if (argument_count > 0) {
590 DisallowHeapAllocation no_gc;
591 if (!ClampedToInteger(args[1], &relative_start)) {
592 AllowHeapAllocation allow_allocation;
593 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
594 }
595 if (argument_count > 1) {
596 Object* end_arg = args[2];
597 // slice handles the end_arg specially
598 if (end_arg->IsUndefined()) {
599 relative_end = len;
600 } else if (!ClampedToInteger(end_arg, &relative_end)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000604 }
605 }
606
607 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000608 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
609 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000610
611 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 uint32_t actual_end =
613 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000614
Ben Murdochda12d292016-06-02 14:46:10 +0100615 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616 ElementsAccessor* accessor = object->GetElementsAccessor();
Ben Murdochda12d292016-06-02 14:46:10 +0100617 return *accessor->Slice(object, actual_start, actual_end);
Andrei Popescu402d9372010-02-26 13:31:12 +0000618}
619
620
621BUILTIN(ArraySplice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 Handle<Object> receiver = args.receiver();
Ben Murdochda12d292016-06-02 14:46:10 +0100624 if (V8_UNLIKELY(
625 !EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3) ||
626 // If this is a subclass of Array, then call out to JS.
627 !Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) ||
628 // If anything with @@species has been messed with, call out to JS.
629 !isolate->IsArraySpeciesLookupChainIntact())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block6ded16b2010-05-10 14:33:55 +0100631 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Andrei Popescu402d9372010-02-26 13:31:12 +0000633
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000634 int argument_count = args.length() - 1;
Steve Block6ded16b2010-05-10 14:33:55 +0100635 int relative_start = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636 if (argument_count > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638 if (!ClampedToInteger(args[1], &relative_start)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000639 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100641 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000642 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000643 int len = Smi::cast(array->length())->value();
644 // clip relative start to [0, len]
Steve Block6ded16b2010-05-10 14:33:55 +0100645 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
646 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000647
Steve Block1e0659c2011-05-24 12:43:12 +0100648 int actual_delete_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649 if (argument_count == 1) {
650 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
651 // given as a request to delete all the elements from the start.
652 // And it differs from the case of undefined delete count.
653 // This does not follow ECMA-262, but we do the same for compatibility.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 DCHECK(len - actual_start >= 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100655 actual_delete_count = len - actual_start;
656 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657 int delete_count = 0;
658 DisallowHeapAllocation no_gc;
659 if (argument_count > 1) {
660 if (!ClampedToInteger(args[2], &delete_count)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Steve Block1e0659c2011-05-24 12:43:12 +0100663 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000664 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000665 actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
Andrei Popescu402d9372010-02-26 13:31:12 +0000666 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
669 int new_length = len - actual_delete_count + add_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400671 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
672 AllowHeapAllocation allow_allocation;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400674 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000675 ElementsAccessor* accessor = array->GetElementsAccessor();
676 Handle<JSArray> result_array = accessor->Splice(
Ben Murdochda12d292016-06-02 14:46:10 +0100677 array, actual_start, actual_delete_count, &args, add_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000679}
680
681
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682// Array Concat -------------------------------------------------------------
Steve Block6ded16b2010-05-10 14:33:55 +0100683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684namespace {
685
686/**
687 * A simple visitor visits every element of Array's.
688 * The backend storage can be a fixed array for fast elements case,
689 * or a dictionary for sparse array. Since Dictionary is a subtype
690 * of FixedArray, the class can be used by both fast and slow cases.
691 * The second parameter of the constructor, fast_elements, specifies
692 * whether the storage is a FixedArray or Dictionary.
693 *
694 * An index limit is used to deal with the situation that a result array
695 * length overflows 32-bit non-negative integer.
696 */
697class ArrayConcatVisitor {
698 public:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100699 ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 bool fast_elements)
701 : isolate_(isolate),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100702 storage_(isolate->global_handles()->Create(*storage)),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000703 index_offset_(0u),
704 bit_field_(FastElementsField::encode(fast_elements) |
Ben Murdoch097c5b22016-05-18 11:27:45 +0100705 ExceedsLimitField::encode(false) |
706 IsFixedArrayField::encode(storage->IsFixedArray())) {
707 DCHECK(!(this->fast_elements() && !is_fixed_array()));
708 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709
710 ~ArrayConcatVisitor() { clear_storage(); }
711
Ben Murdochda12d292016-06-02 14:46:10 +0100712 MUST_USE_RESULT bool visit(uint32_t i, Handle<Object> elm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 uint32_t index = index_offset_ + i;
714
Ben Murdoch097c5b22016-05-18 11:27:45 +0100715 if (i >= JSObject::kMaxElementCount - index_offset_) {
716 set_exceeds_array_limit(true);
717 // Exception hasn't been thrown at this point. Return true to
718 // break out, and caller will throw. !visit would imply that
719 // there is already a pending exception.
720 return true;
721 }
722
Ben Murdochda12d292016-06-02 14:46:10 +0100723 if (!is_fixed_array()) {
724 LookupIterator it(isolate_, storage_, index, LookupIterator::OWN);
725 MAYBE_RETURN(
726 JSReceiver::CreateDataProperty(&it, elm, Object::THROW_ON_ERROR),
727 false);
728 return true;
729 }
730
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 if (fast_elements()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100732 if (index < static_cast<uint32_t>(storage_fixed_array()->length())) {
733 storage_fixed_array()->set(index, *elm);
734 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 }
736 // Our initial estimate of length was foiled, possibly by
737 // getters on the arrays increasing the length of later arrays
738 // during iteration.
739 // This shouldn't happen in anything but pathological cases.
740 SetDictionaryMode();
741 // Fall-through to dictionary mode.
742 }
743 DCHECK(!fast_elements());
744 Handle<SeededNumberDictionary> dict(
745 SeededNumberDictionary::cast(*storage_));
746 // The object holding this backing store has just been allocated, so
747 // it cannot yet be used as a prototype.
748 Handle<SeededNumberDictionary> result =
749 SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
750 if (!result.is_identical_to(dict)) {
751 // Dictionary needed to grow.
752 clear_storage();
753 set_storage(*result);
754 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100755 return true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000756 }
757
758 void increase_index_offset(uint32_t delta) {
759 if (JSObject::kMaxElementCount - index_offset_ < delta) {
760 index_offset_ = JSObject::kMaxElementCount;
761 } else {
762 index_offset_ += delta;
763 }
764 // If the initial length estimate was off (see special case in visit()),
765 // but the array blowing the limit didn't contain elements beyond the
766 // provided-for index range, go to dictionary mode now.
767 if (fast_elements() &&
768 index_offset_ >
769 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
770 SetDictionaryMode();
771 }
772 }
773
774 bool exceeds_array_limit() const {
775 return ExceedsLimitField::decode(bit_field_);
776 }
777
778 Handle<JSArray> ToArray() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100779 DCHECK(is_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000780 Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
781 Handle<Object> length =
782 isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
783 Handle<Map> map = JSObject::GetElementsTransitionMap(
784 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
785 array->set_map(*map);
786 array->set_length(*length);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100787 array->set_elements(*storage_fixed_array());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788 return array;
789 }
790
Ben Murdoch097c5b22016-05-18 11:27:45 +0100791 // Storage is either a FixedArray (if is_fixed_array()) or a JSReciever
792 // (otherwise)
793 Handle<FixedArray> storage_fixed_array() {
794 DCHECK(is_fixed_array());
795 return Handle<FixedArray>::cast(storage_);
796 }
797 Handle<JSReceiver> storage_jsreceiver() {
798 DCHECK(!is_fixed_array());
799 return Handle<JSReceiver>::cast(storage_);
800 }
801
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 private:
803 // Convert storage to dictionary mode.
804 void SetDictionaryMode() {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100805 DCHECK(fast_elements() && is_fixed_array());
806 Handle<FixedArray> current_storage = storage_fixed_array();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 Handle<SeededNumberDictionary> slow_storage(
808 SeededNumberDictionary::New(isolate_, current_storage->length()));
809 uint32_t current_length = static_cast<uint32_t>(current_storage->length());
Ben Murdochda12d292016-06-02 14:46:10 +0100810 FOR_WITH_HANDLE_SCOPE(
811 isolate_, uint32_t, i = 0, i, i < current_length, i++, {
812 Handle<Object> element(current_storage->get(i), isolate_);
813 if (!element->IsTheHole()) {
814 // The object holding this backing store has just been allocated, so
815 // it cannot yet be used as a prototype.
816 Handle<SeededNumberDictionary> new_storage =
817 SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
818 false);
819 if (!new_storage.is_identical_to(slow_storage)) {
820 slow_storage = loop_scope.CloseAndEscape(new_storage);
821 }
822 }
823 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 clear_storage();
825 set_storage(*slow_storage);
826 set_fast_elements(false);
827 }
828
Ben Murdochda12d292016-06-02 14:46:10 +0100829 inline void clear_storage() { GlobalHandles::Destroy(storage_.location()); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830
831 inline void set_storage(FixedArray* storage) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100832 DCHECK(is_fixed_array());
833 storage_ = isolate_->global_handles()->Create(storage);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 }
835
836 class FastElementsField : public BitField<bool, 0, 1> {};
837 class ExceedsLimitField : public BitField<bool, 1, 1> {};
Ben Murdoch097c5b22016-05-18 11:27:45 +0100838 class IsFixedArrayField : public BitField<bool, 2, 1> {};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000839
840 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
841 void set_fast_elements(bool fast) {
842 bit_field_ = FastElementsField::update(bit_field_, fast);
843 }
844 void set_exceeds_array_limit(bool exceeds) {
845 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
846 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100847 bool is_fixed_array() const { return IsFixedArrayField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848
849 Isolate* isolate_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100850 Handle<Object> storage_; // Always a global handle.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000851 // Index after last seen index. Always less than or equal to
852 // JSObject::kMaxElementCount.
853 uint32_t index_offset_;
854 uint32_t bit_field_;
855};
856
857
858uint32_t EstimateElementCount(Handle<JSArray> array) {
859 uint32_t length = static_cast<uint32_t>(array->length()->Number());
860 int element_count = 0;
861 switch (array->GetElementsKind()) {
862 case FAST_SMI_ELEMENTS:
863 case FAST_HOLEY_SMI_ELEMENTS:
864 case FAST_ELEMENTS:
865 case FAST_HOLEY_ELEMENTS: {
866 // Fast elements can't have lengths that are not representable by
867 // a 32-bit signed integer.
868 DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
869 int fast_length = static_cast<int>(length);
870 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
871 for (int i = 0; i < fast_length; i++) {
872 if (!elements->get(i)->IsTheHole()) element_count++;
873 }
874 break;
875 }
876 case FAST_DOUBLE_ELEMENTS:
877 case FAST_HOLEY_DOUBLE_ELEMENTS: {
878 // Fast elements can't have lengths that are not representable by
879 // a 32-bit signed integer.
880 DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
881 int fast_length = static_cast<int>(length);
882 if (array->elements()->IsFixedArray()) {
883 DCHECK(FixedArray::cast(array->elements())->length() == 0);
884 break;
885 }
886 Handle<FixedDoubleArray> elements(
887 FixedDoubleArray::cast(array->elements()));
888 for (int i = 0; i < fast_length; i++) {
889 if (!elements->is_the_hole(i)) element_count++;
890 }
891 break;
892 }
893 case DICTIONARY_ELEMENTS: {
894 Handle<SeededNumberDictionary> dictionary(
895 SeededNumberDictionary::cast(array->elements()));
896 int capacity = dictionary->Capacity();
897 for (int i = 0; i < capacity; i++) {
898 Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
899 if (dictionary->IsKey(*key)) {
900 element_count++;
901 }
902 }
903 break;
904 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000905#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
906
907 TYPED_ARRAYS(TYPED_ARRAY_CASE)
908#undef TYPED_ARRAY_CASE
909 // External arrays are always dense.
910 return length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100911 case NO_ELEMENTS:
912 return 0;
913 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
914 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
915 case FAST_STRING_WRAPPER_ELEMENTS:
916 case SLOW_STRING_WRAPPER_ELEMENTS:
917 UNREACHABLE();
918 return 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000919 }
920 // As an estimate, we assume that the prototype doesn't contain any
921 // inherited elements.
922 return element_count;
923}
924
925
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926// Used for sorting indices in a List<uint32_t>.
927int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
928 uint32_t a = *ap;
929 uint32_t b = *bp;
930 return (a == b) ? 0 : (a < b) ? -1 : 1;
931}
932
933
934void CollectElementIndices(Handle<JSObject> object, uint32_t range,
935 List<uint32_t>* indices) {
936 Isolate* isolate = object->GetIsolate();
937 ElementsKind kind = object->GetElementsKind();
938 switch (kind) {
939 case FAST_SMI_ELEMENTS:
940 case FAST_ELEMENTS:
941 case FAST_HOLEY_SMI_ELEMENTS:
942 case FAST_HOLEY_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +0100943 DisallowHeapAllocation no_gc;
944 FixedArray* elements = FixedArray::cast(object->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 uint32_t length = static_cast<uint32_t>(elements->length());
946 if (range < length) length = range;
947 for (uint32_t i = 0; i < length; i++) {
948 if (!elements->get(i)->IsTheHole()) {
949 indices->Add(i);
950 }
951 }
952 break;
953 }
954 case FAST_HOLEY_DOUBLE_ELEMENTS:
955 case FAST_DOUBLE_ELEMENTS: {
956 if (object->elements()->IsFixedArray()) {
957 DCHECK(object->elements()->length() == 0);
958 break;
959 }
960 Handle<FixedDoubleArray> elements(
961 FixedDoubleArray::cast(object->elements()));
962 uint32_t length = static_cast<uint32_t>(elements->length());
963 if (range < length) length = range;
964 for (uint32_t i = 0; i < length; i++) {
965 if (!elements->is_the_hole(i)) {
966 indices->Add(i);
967 }
968 }
969 break;
970 }
971 case DICTIONARY_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +0100972 DisallowHeapAllocation no_gc;
973 SeededNumberDictionary* dict =
974 SeededNumberDictionary::cast(object->elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975 uint32_t capacity = dict->Capacity();
Ben Murdochda12d292016-06-02 14:46:10 +0100976 Heap* heap = isolate->heap();
977 Object* undefined = heap->undefined_value();
978 Object* the_hole = heap->the_hole_value();
979 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
980 Object* k = dict->KeyAt(j);
981 if (k == undefined) continue;
982 if (k == the_hole) continue;
983 DCHECK(k->IsNumber());
984 uint32_t index = static_cast<uint32_t>(k->Number());
985 if (index < range) {
986 indices->Add(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000987 }
Ben Murdochda12d292016-06-02 14:46:10 +0100988 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000989 break;
990 }
991#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
992
993 TYPED_ARRAYS(TYPED_ARRAY_CASE)
994#undef TYPED_ARRAY_CASE
995 {
996 uint32_t length = static_cast<uint32_t>(
997 FixedArrayBase::cast(object->elements())->length());
998 if (range <= length) {
999 length = range;
1000 // We will add all indices, so we might as well clear it first
1001 // and avoid duplicates.
1002 indices->Clear();
1003 }
1004 for (uint32_t i = 0; i < length; i++) {
1005 indices->Add(i);
1006 }
1007 if (length == range) return; // All indices accounted for already.
1008 break;
1009 }
1010 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1011 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1012 ElementsAccessor* accessor = object->GetElementsAccessor();
1013 for (uint32_t i = 0; i < range; i++) {
1014 if (accessor->HasElement(object, i)) {
1015 indices->Add(i);
1016 }
1017 }
1018 break;
1019 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001020 case FAST_STRING_WRAPPER_ELEMENTS:
1021 case SLOW_STRING_WRAPPER_ELEMENTS: {
1022 DCHECK(object->IsJSValue());
1023 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
1024 DCHECK(js_value->value()->IsString());
1025 Handle<String> string(String::cast(js_value->value()), isolate);
1026 uint32_t length = static_cast<uint32_t>(string->length());
1027 uint32_t i = 0;
1028 uint32_t limit = Min(length, range);
1029 for (; i < limit; i++) {
1030 indices->Add(i);
1031 }
1032 ElementsAccessor* accessor = object->GetElementsAccessor();
1033 for (; i < range; i++) {
1034 if (accessor->HasElement(object, i)) {
1035 indices->Add(i);
1036 }
1037 }
1038 break;
1039 }
1040 case NO_ELEMENTS:
1041 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 }
1043
1044 PrototypeIterator iter(isolate, object);
1045 if (!iter.IsAtEnd()) {
1046 // The prototype will usually have no inherited element indices,
1047 // but we have to check.
1048 CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
1049 indices);
1050 }
1051}
1052
1053
1054bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
1055 uint32_t length, ArrayConcatVisitor* visitor) {
Ben Murdochda12d292016-06-02 14:46:10 +01001056 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, i = 0, i, i < length, ++i, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
1058 if (!maybe.IsJust()) return false;
1059 if (maybe.FromJust()) {
1060 Handle<Object> element_value;
Ben Murdochda12d292016-06-02 14:46:10 +01001061 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1062 isolate, element_value, JSReceiver::GetElement(isolate, receiver, i),
1063 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001064 if (!visitor->visit(i, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001065 }
Ben Murdochda12d292016-06-02 14:46:10 +01001066 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 visitor->increase_index_offset(length);
1068 return true;
1069}
1070
1071
1072/**
1073 * A helper function that visits "array" elements of a JSReceiver in numerical
1074 * order.
1075 *
1076 * The visitor argument called for each existing element in the array
1077 * with the element index and the element's value.
1078 * Afterwards it increments the base-index of the visitor by the array
1079 * length.
1080 * Returns false if any access threw an exception, otherwise true.
1081 */
1082bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
1083 ArrayConcatVisitor* visitor) {
1084 uint32_t length = 0;
1085
1086 if (receiver->IsJSArray()) {
1087 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
1088 length = static_cast<uint32_t>(array->length()->Number());
1089 } else {
1090 Handle<Object> val;
1091 Handle<Object> key = isolate->factory()->length_string();
1092 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1093 isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
1094 false);
1095 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
1096 Object::ToLength(isolate, val), false);
1097 // TODO(caitp): Support larger element indexes (up to 2^53-1).
1098 if (!val->ToUint32(&length)) {
1099 length = 0;
1100 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001101 // TODO(cbruni): handle other element kind as well
1102 return IterateElementsSlow(isolate, receiver, length, visitor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 }
1104
Ben Murdoch097c5b22016-05-18 11:27:45 +01001105 if (!HasOnlySimpleElements(isolate, *receiver)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001106 return IterateElementsSlow(isolate, receiver, length, visitor);
1107 }
1108 Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1109
1110 switch (array->GetElementsKind()) {
1111 case FAST_SMI_ELEMENTS:
1112 case FAST_ELEMENTS:
1113 case FAST_HOLEY_SMI_ELEMENTS:
1114 case FAST_HOLEY_ELEMENTS: {
1115 // Run through the elements FixedArray and use HasElement and GetElement
1116 // to check the prototype for missing elements.
1117 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1118 int fast_length = static_cast<int>(length);
Ben Murdochda12d292016-06-02 14:46:10 +01001119 DCHECK(fast_length <= elements->length());
1120 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 Handle<Object> element_value(elements->get(j), isolate);
1122 if (!element_value->IsTheHole()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001123 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001124 } else {
1125 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1126 if (!maybe.IsJust()) return false;
1127 if (maybe.FromJust()) {
1128 // Call GetElement on array, not its prototype, or getters won't
1129 // have the correct receiver.
1130 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001131 isolate, element_value,
1132 JSReceiver::GetElement(isolate, array, j), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001133 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134 }
1135 }
Ben Murdochda12d292016-06-02 14:46:10 +01001136 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137 break;
1138 }
1139 case FAST_HOLEY_DOUBLE_ELEMENTS:
1140 case FAST_DOUBLE_ELEMENTS: {
1141 // Empty array is FixedArray but not FixedDoubleArray.
1142 if (length == 0) break;
1143 // Run through the elements FixedArray and use HasElement and GetElement
1144 // to check the prototype for missing elements.
1145 if (array->elements()->IsFixedArray()) {
1146 DCHECK(array->elements()->length() == 0);
1147 break;
1148 }
1149 Handle<FixedDoubleArray> elements(
1150 FixedDoubleArray::cast(array->elements()));
1151 int fast_length = static_cast<int>(length);
1152 DCHECK(fast_length <= elements->length());
Ben Murdochda12d292016-06-02 14:46:10 +01001153 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < fast_length, j++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001154 if (!elements->is_the_hole(j)) {
1155 double double_value = elements->get_scalar(j);
1156 Handle<Object> element_value =
1157 isolate->factory()->NewNumber(double_value);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001158 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001159 } else {
1160 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1161 if (!maybe.IsJust()) return false;
1162 if (maybe.FromJust()) {
1163 // Call GetElement on array, not its prototype, or getters won't
1164 // have the correct receiver.
1165 Handle<Object> element_value;
1166 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001167 isolate, element_value,
1168 JSReceiver::GetElement(isolate, array, j), false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001169 if (!visitor->visit(j, element_value)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001170 }
1171 }
Ben Murdochda12d292016-06-02 14:46:10 +01001172 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173 break;
1174 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 case DICTIONARY_ELEMENTS: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001177 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1178 List<uint32_t> indices(dict->Capacity() / 2);
1179 // Collect all indices in the object and the prototypes less
1180 // than length. This might introduce duplicates in the indices list.
1181 CollectElementIndices(array, length, &indices);
1182 indices.Sort(&compareUInt32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 int n = indices.length();
Ben Murdochda12d292016-06-02 14:46:10 +01001184 FOR_WITH_HANDLE_SCOPE(isolate, int, j = 0, j, j < n, (void)0, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 uint32_t index = indices[j];
1186 Handle<Object> element;
1187 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
Ben Murdochda12d292016-06-02 14:46:10 +01001188 isolate, element, JSReceiver::GetElement(isolate, array, index),
1189 false);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001190 if (!visitor->visit(index, element)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001191 // Skip to next different index (i.e., omit duplicates).
1192 do {
1193 j++;
1194 } while (j < n && indices[j] == index);
Ben Murdochda12d292016-06-02 14:46:10 +01001195 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 break;
1197 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1199 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001200 FOR_WITH_HANDLE_SCOPE(
1201 isolate, uint32_t, index = 0, index, index < length, index++, {
1202 Handle<Object> element;
1203 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1204 isolate, element, JSReceiver::GetElement(isolate, array, index),
1205 false);
1206 if (!visitor->visit(index, element)) return false;
1207 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208 break;
1209 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001210 case NO_ELEMENTS:
1211 break;
1212#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
1213 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1214#undef TYPED_ARRAY_CASE
1215 return IterateElementsSlow(isolate, receiver, length, visitor);
1216 case FAST_STRING_WRAPPER_ELEMENTS:
1217 case SLOW_STRING_WRAPPER_ELEMENTS:
1218 // |array| is guaranteed to be an array or typed array.
1219 UNREACHABLE();
1220 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 }
1222 visitor->increase_index_offset(length);
1223 return true;
1224}
1225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1227 HandleScope handle_scope(isolate);
1228 if (!obj->IsJSReceiver()) return Just(false);
Ben Murdochc5610432016-08-08 18:44:38 +01001229 if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1230 // Slow path if @@isConcatSpreadable has been used.
1231 Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1232 Handle<Object> value;
1233 MaybeHandle<Object> maybeValue =
1234 i::Runtime::GetObjectProperty(isolate, obj, key);
1235 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1236 if (!value->IsUndefined()) return Just(value->BooleanValue());
1237 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 return Object::IsArray(obj);
1239}
1240
1241
Ben Murdoch097c5b22016-05-18 11:27:45 +01001242Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
1243 Isolate* isolate) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001244 int argument_count = args->length();
1245
Ben Murdoch097c5b22016-05-18 11:27:45 +01001246 bool is_array_species = *species == isolate->context()->array_function();
1247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001248 // Pass 1: estimate the length and number of elements of the result.
1249 // The actual length can be larger if any of the arguments have getters
1250 // that mutate other arguments (but will otherwise be precise).
1251 // The number of elements is precise if there are no inherited elements.
1252
1253 ElementsKind kind = FAST_SMI_ELEMENTS;
1254
1255 uint32_t estimate_result_length = 0;
1256 uint32_t estimate_nof_elements = 0;
Ben Murdochda12d292016-06-02 14:46:10 +01001257 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < argument_count, i++, {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001258 Handle<Object> obj((*args)[i], isolate);
1259 uint32_t length_estimate;
1260 uint32_t element_estimate;
1261 if (obj->IsJSArray()) {
1262 Handle<JSArray> array(Handle<JSArray>::cast(obj));
1263 length_estimate = static_cast<uint32_t>(array->length()->Number());
1264 if (length_estimate != 0) {
1265 ElementsKind array_kind =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001266 GetPackedElementsKind(array->GetElementsKind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001267 kind = GetMoreGeneralElementsKind(kind, array_kind);
1268 }
1269 element_estimate = EstimateElementCount(array);
1270 } else {
1271 if (obj->IsHeapObject()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001272 kind = GetMoreGeneralElementsKind(
1273 kind, obj->IsNumber() ? FAST_DOUBLE_ELEMENTS : FAST_ELEMENTS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 }
1275 length_estimate = 1;
1276 element_estimate = 1;
1277 }
1278 // Avoid overflows by capping at kMaxElementCount.
1279 if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1280 estimate_result_length = JSObject::kMaxElementCount;
1281 } else {
1282 estimate_result_length += length_estimate;
1283 }
1284 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1285 estimate_nof_elements = JSObject::kMaxElementCount;
1286 } else {
1287 estimate_nof_elements += element_estimate;
1288 }
Ben Murdochda12d292016-06-02 14:46:10 +01001289 });
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290
1291 // If estimated number of elements is more than half of length, a
1292 // fixed array (fast case) is more time and space-efficient than a
1293 // dictionary.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001294 bool fast_case =
1295 is_array_species && (estimate_nof_elements * 2) >= estimate_result_length;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001296
1297 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1298 Handle<FixedArrayBase> storage =
1299 isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1300 int j = 0;
1301 bool failure = false;
1302 if (estimate_result_length > 0) {
1303 Handle<FixedDoubleArray> double_storage =
1304 Handle<FixedDoubleArray>::cast(storage);
1305 for (int i = 0; i < argument_count; i++) {
1306 Handle<Object> obj((*args)[i], isolate);
1307 if (obj->IsSmi()) {
1308 double_storage->set(j, Smi::cast(*obj)->value());
1309 j++;
1310 } else if (obj->IsNumber()) {
1311 double_storage->set(j, obj->Number());
1312 j++;
1313 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001314 DisallowHeapAllocation no_gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001315 JSArray* array = JSArray::cast(*obj);
1316 uint32_t length = static_cast<uint32_t>(array->length()->Number());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001317 switch (array->GetElementsKind()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318 case FAST_HOLEY_DOUBLE_ELEMENTS:
1319 case FAST_DOUBLE_ELEMENTS: {
1320 // Empty array is FixedArray but not FixedDoubleArray.
1321 if (length == 0) break;
1322 FixedDoubleArray* elements =
1323 FixedDoubleArray::cast(array->elements());
1324 for (uint32_t i = 0; i < length; i++) {
1325 if (elements->is_the_hole(i)) {
1326 // TODO(jkummerow/verwaest): We could be a bit more clever
1327 // here: Check if there are no elements/getters on the
1328 // prototype chain, and if so, allow creation of a holey
1329 // result array.
1330 // Same thing below (holey smi case).
1331 failure = true;
1332 break;
1333 }
1334 double double_value = elements->get_scalar(i);
1335 double_storage->set(j, double_value);
1336 j++;
1337 }
1338 break;
1339 }
1340 case FAST_HOLEY_SMI_ELEMENTS:
1341 case FAST_SMI_ELEMENTS: {
Ben Murdochda12d292016-06-02 14:46:10 +01001342 Object* the_hole = isolate->heap()->the_hole_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 FixedArray* elements(FixedArray::cast(array->elements()));
1344 for (uint32_t i = 0; i < length; i++) {
1345 Object* element = elements->get(i);
Ben Murdochda12d292016-06-02 14:46:10 +01001346 if (element == the_hole) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001347 failure = true;
1348 break;
1349 }
1350 int32_t int_value = Smi::cast(element)->value();
1351 double_storage->set(j, int_value);
1352 j++;
1353 }
1354 break;
1355 }
1356 case FAST_HOLEY_ELEMENTS:
1357 case FAST_ELEMENTS:
1358 case DICTIONARY_ELEMENTS:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001359 case NO_ELEMENTS:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001360 DCHECK_EQ(0u, length);
1361 break;
1362 default:
1363 UNREACHABLE();
1364 }
1365 }
1366 if (failure) break;
1367 }
1368 }
1369 if (!failure) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001370 return *isolate->factory()->NewJSArrayWithElements(storage, kind, j);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001371 }
1372 // In case of failure, fall through.
1373 }
1374
Ben Murdoch097c5b22016-05-18 11:27:45 +01001375 Handle<Object> storage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001376 if (fast_case) {
1377 // The backing storage array must have non-existing elements to preserve
1378 // holes across concat operations.
1379 storage =
1380 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001381 } else if (is_array_species) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001382 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1383 uint32_t at_least_space_for =
1384 estimate_nof_elements + (estimate_nof_elements >> 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001385 storage = SeededNumberDictionary::New(isolate, at_least_space_for);
1386 } else {
1387 DCHECK(species->IsConstructor());
1388 Handle<Object> length(Smi::FromInt(0), isolate);
1389 Handle<Object> storage_object;
1390 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1391 isolate, storage_object,
1392 Execution::New(isolate, species, species, 1, &length));
1393 storage = storage_object;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001394 }
1395
1396 ArrayConcatVisitor visitor(isolate, storage, fast_case);
1397
1398 for (int i = 0; i < argument_count; i++) {
1399 Handle<Object> obj((*args)[i], isolate);
1400 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1401 MAYBE_RETURN(spreadable, isolate->heap()->exception());
1402 if (spreadable.FromJust()) {
1403 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1404 if (!IterateElements(isolate, object, &visitor)) {
1405 return isolate->heap()->exception();
1406 }
1407 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001408 if (!visitor.visit(0, obj)) return isolate->heap()->exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001409 visitor.increase_index_offset(1);
1410 }
1411 }
1412
1413 if (visitor.exceeds_array_limit()) {
1414 THROW_NEW_ERROR_RETURN_FAILURE(
1415 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1416 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001417
1418 if (is_array_species) {
1419 return *visitor.ToArray();
1420 } else {
1421 return *visitor.storage_jsreceiver();
1422 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001423}
1424
Ben Murdochc5610432016-08-08 18:44:38 +01001425bool IsSimpleArray(Isolate* isolate, Handle<JSArray> obj) {
1426 DisallowHeapAllocation no_gc;
1427 Map* map = obj->map();
1428 // If there is only the 'length' property we are fine.
1429 if (map->prototype() ==
1430 isolate->native_context()->initial_array_prototype() &&
1431 map->NumberOfOwnDescriptors() == 1) {
1432 return true;
1433 }
1434 // TODO(cbruni): slower lookup for array subclasses and support slow
1435 // @@IsConcatSpreadable lookup.
1436 return false;
1437}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438
1439MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
Ben Murdochc5610432016-08-08 18:44:38 +01001440 if (!isolate->IsIsConcatSpreadableLookupChainIntact()) {
1441 return MaybeHandle<JSArray>();
1442 }
Ben Murdochda12d292016-06-02 14:46:10 +01001443 // We shouldn't overflow when adding another len.
1444 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1445 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1446 STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt);
1447 USE(kHalfOfMaxInt);
1448
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001449 int n_arguments = args->length();
Steve Block6ded16b2010-05-10 14:33:55 +01001450 int result_len = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451 {
1452 DisallowHeapAllocation no_gc;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001453 // Iterate through all the arguments performing checks
1454 // and calculating total length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455 for (int i = 0; i < n_arguments; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001456 Object* arg = (*args)[i];
1457 if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
Ben Murdochda12d292016-06-02 14:46:10 +01001458 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001459 return MaybeHandle<JSArray>();
1460 }
Ben Murdochc5610432016-08-08 18:44:38 +01001461 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS.
1462 if (!JSObject::cast(arg)->HasFastElements()) {
1463 return MaybeHandle<JSArray>();
1464 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001465 Handle<JSArray> array(JSArray::cast(arg), isolate);
Ben Murdochc5610432016-08-08 18:44:38 +01001466 if (!IsSimpleArray(isolate, array)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001467 return MaybeHandle<JSArray>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001468 }
Ben Murdochda12d292016-06-02 14:46:10 +01001469 // The Array length is guaranted to be <= kHalfOfMaxInt thus we won't
1470 // overflow.
1471 result_len += Smi::cast(array->length())->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001472 DCHECK(result_len >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001473 // Throw an Error if we overflow the FixedArray limits
Ben Murdochc5610432016-08-08 18:44:38 +01001474 if (FixedArray::kMaxLength < result_len) {
1475 AllowHeapAllocation gc;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001476 THROW_NEW_ERROR(isolate,
1477 NewRangeError(MessageTemplate::kInvalidArrayLength),
1478 JSArray);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001479 }
Steve Block6ded16b2010-05-10 14:33:55 +01001480 }
Steve Block6ded16b2010-05-10 14:33:55 +01001481 }
Ben Murdochc5610432016-08-08 18:44:38 +01001482 return ElementsAccessor::Concat(isolate, args, n_arguments, result_len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001483}
Steve Block6ded16b2010-05-10 14:33:55 +01001484
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001485} // namespace
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001486
Ben Murdoch097c5b22016-05-18 11:27:45 +01001487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001488// ES6 22.1.3.1 Array.prototype.concat
1489BUILTIN(ArrayConcat) {
1490 HandleScope scope(isolate);
1491
Ben Murdoch097c5b22016-05-18 11:27:45 +01001492 Handle<Object> receiver = args.receiver();
1493 // TODO(bmeurer): Do we really care about the exact exception message here?
1494 if (receiver->IsNull() || receiver->IsUndefined()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 THROW_NEW_ERROR_RETURN_FAILURE(
1496 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1497 isolate->factory()->NewStringFromAsciiChecked(
1498 "Array.prototype.concat")));
1499 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001500 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1501 isolate, receiver, Object::ToObject(isolate, args.receiver()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001502 args[0] = *receiver;
1503
1504 Handle<JSArray> result_array;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001505
Ben Murdochda12d292016-06-02 14:46:10 +01001506 // Avoid a real species read to avoid extra lookups to the array constructor
1507 if (V8_LIKELY(receiver->IsJSArray() &&
1508 Handle<JSArray>::cast(receiver)->HasArrayPrototype(isolate) &&
1509 isolate->IsArraySpeciesLookupChainIntact())) {
1510 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1511 return *result_array;
1512 }
1513 if (isolate->has_pending_exception()) return isolate->heap()->exception();
1514 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001515 // Reading @@species happens before anything else with a side effect, so
1516 // we can do it here to determine whether to take the fast path.
1517 Handle<Object> species;
1518 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1519 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
Ben Murdochda12d292016-06-02 14:46:10 +01001520 if (*species == *isolate->array_function()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001521 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1522 return *result_array;
1523 }
1524 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001525 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001526 return Slow_ArrayConcat(&args, species, isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527}
1528
1529
Ben Murdoch097c5b22016-05-18 11:27:45 +01001530namespace {
1531
1532MUST_USE_RESULT Maybe<bool> FastAssign(Handle<JSReceiver> to,
1533 Handle<Object> next_source) {
1534 // Non-empty strings are the only non-JSReceivers that need to be handled
1535 // explicitly by Object.assign.
1536 if (!next_source->IsJSReceiver()) {
1537 return Just(!next_source->IsString() ||
1538 String::cast(*next_source)->length() == 0);
1539 }
1540
Ben Murdochc5610432016-08-08 18:44:38 +01001541 // If the target is deprecated, the object will be updated on first store. If
1542 // the source for that store equals the target, this will invalidate the
1543 // cached representation of the source. Preventively upgrade the target.
1544 // Do this on each iteration since any property load could cause deprecation.
1545 if (to->map()->is_deprecated()) {
1546 JSObject::MigrateInstance(Handle<JSObject>::cast(to));
1547 }
1548
Ben Murdoch097c5b22016-05-18 11:27:45 +01001549 Isolate* isolate = to->GetIsolate();
1550 Handle<Map> map(JSReceiver::cast(*next_source)->map(), isolate);
1551
1552 if (!map->IsJSObjectMap()) return Just(false);
1553 if (!map->OnlyHasSimpleProperties()) return Just(false);
1554
1555 Handle<JSObject> from = Handle<JSObject>::cast(next_source);
1556 if (from->elements() != isolate->heap()->empty_fixed_array()) {
1557 return Just(false);
1558 }
1559
1560 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
1561 int length = map->NumberOfOwnDescriptors();
1562
1563 bool stable = true;
1564
1565 for (int i = 0; i < length; i++) {
1566 Handle<Name> next_key(descriptors->GetKey(i), isolate);
1567 Handle<Object> prop_value;
1568 // Directly decode from the descriptor array if |from| did not change shape.
1569 if (stable) {
1570 PropertyDetails details = descriptors->GetDetails(i);
1571 if (!details.IsEnumerable()) continue;
1572 if (details.kind() == kData) {
1573 if (details.location() == kDescriptor) {
1574 prop_value = handle(descriptors->GetValue(i), isolate);
1575 } else {
1576 Representation representation = details.representation();
1577 FieldIndex index = FieldIndex::ForDescriptor(*map, i);
1578 prop_value = JSObject::FastPropertyAt(from, representation, index);
1579 }
1580 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001581 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1582 isolate, prop_value, JSReceiver::GetProperty(from, next_key),
1583 Nothing<bool>());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001584 stable = from->map() == *map;
1585 }
1586 } else {
1587 // If the map did change, do a slower lookup. We are still guaranteed that
1588 // the object has a simple shape, and that the key is a name.
Ben Murdochda12d292016-06-02 14:46:10 +01001589 LookupIterator it(from, next_key, from,
1590 LookupIterator::OWN_SKIP_INTERCEPTOR);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001591 if (!it.IsFound()) continue;
1592 DCHECK(it.state() == LookupIterator::DATA ||
1593 it.state() == LookupIterator::ACCESSOR);
1594 if (!it.IsEnumerable()) continue;
1595 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1596 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
1597 }
Ben Murdochda12d292016-06-02 14:46:10 +01001598 LookupIterator it(to, next_key, to);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001599 bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
1600 Maybe<bool> result = Object::SetProperty(
1601 &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
1602 if (result.IsNothing()) return result;
1603 if (stable && call_to_js) stable = from->map() == *map;
1604 }
1605
1606 return Just(true);
1607}
1608
1609} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001610
1611// ES6 19.1.2.1 Object.assign
1612BUILTIN(ObjectAssign) {
1613 HandleScope scope(isolate);
1614 Handle<Object> target = args.atOrUndefined(isolate, 1);
1615
1616 // 1. Let to be ? ToObject(target).
1617 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001618 Object::ToObject(isolate, target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001619 Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
1620 // 2. If only one argument was passed, return to.
1621 if (args.length() == 2) return *to;
1622 // 3. Let sources be the List of argument values starting with the
1623 // second argument.
1624 // 4. For each element nextSource of sources, in ascending index order,
1625 for (int i = 2; i < args.length(); ++i) {
1626 Handle<Object> next_source = args.at<Object>(i);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001627 Maybe<bool> fast_assign = FastAssign(to, next_source);
1628 if (fast_assign.IsNothing()) return isolate->heap()->exception();
1629 if (fast_assign.FromJust()) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001630 // 4a. If nextSource is undefined or null, let keys be an empty List.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001631 // 4b. Else,
1632 // 4b i. Let from be ToObject(nextSource).
Ben Murdoch097c5b22016-05-18 11:27:45 +01001633 // Only non-empty strings and JSReceivers have enumerable properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001634 Handle<JSReceiver> from =
1635 Object::ToObject(isolate, next_source).ToHandleChecked();
1636 // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
1637 Handle<FixedArray> keys;
1638 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001639 isolate, keys,
1640 JSReceiver::GetKeys(from, OWN_ONLY, ALL_PROPERTIES, KEEP_NUMBERS));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001641 // 4c. Repeat for each element nextKey of keys in List order,
1642 for (int j = 0; j < keys->length(); ++j) {
1643 Handle<Object> next_key(keys->get(j), isolate);
1644 // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
1645 PropertyDescriptor desc;
1646 Maybe<bool> found =
1647 JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
1648 if (found.IsNothing()) return isolate->heap()->exception();
1649 // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
1650 if (found.FromJust() && desc.enumerable()) {
1651 // 4c ii 1. Let propValue be ? Get(from, nextKey).
1652 Handle<Object> prop_value;
1653 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1654 isolate, prop_value,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001655 Runtime::GetObjectProperty(isolate, from, next_key));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001656 // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
1657 Handle<Object> status;
1658 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1659 isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
1660 prop_value, STRICT));
1661 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001662 }
Steve Block6ded16b2010-05-10 14:33:55 +01001663 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001664 // 5. Return to.
1665 return *to;
1666}
Steve Block6ded16b2010-05-10 14:33:55 +01001667
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001668
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669// ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
1670BUILTIN(ObjectCreate) {
1671 HandleScope scope(isolate);
1672 Handle<Object> prototype = args.atOrUndefined(isolate, 1);
1673 if (!prototype->IsNull() && !prototype->IsJSReceiver()) {
1674 THROW_NEW_ERROR_RETURN_FAILURE(
1675 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
1676 }
1677
1678 // Generate the map with the specified {prototype} based on the Object
1679 // function's initial map from the current native context.
1680 // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1681 // slack tracking for Object.create.
1682 Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
1683 isolate);
1684 if (map->prototype() != *prototype) {
1685 map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
1686 }
1687
1688 // Actually allocate the object.
1689 Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
1690
1691 // Define the properties if properties was specified and is not undefined.
1692 Handle<Object> properties = args.atOrUndefined(isolate, 2);
1693 if (!properties->IsUndefined()) {
1694 RETURN_FAILURE_ON_EXCEPTION(
1695 isolate, JSReceiver::DefineProperties(isolate, object, properties));
1696 }
1697
1698 return *object;
1699}
1700
Ben Murdochc5610432016-08-08 18:44:38 +01001701// ES6 section 19.1.2.3 Object.defineProperties
1702BUILTIN(ObjectDefineProperties) {
1703 HandleScope scope(isolate);
1704 DCHECK_EQ(3, args.length());
1705 Handle<Object> target = args.at<Object>(1);
1706 Handle<Object> properties = args.at<Object>(2);
1707
1708 Handle<Object> result;
1709 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1710 isolate, result,
1711 JSReceiver::DefineProperties(isolate, target, properties));
1712 return *result;
1713}
1714
1715// ES6 section 19.1.2.4 Object.defineProperty
1716BUILTIN(ObjectDefineProperty) {
1717 HandleScope scope(isolate);
1718 DCHECK_EQ(4, args.length());
1719 Handle<Object> target = args.at<Object>(1);
1720 Handle<Object> key = args.at<Object>(2);
1721 Handle<Object> attributes = args.at<Object>(3);
1722
1723 return JSReceiver::DefineProperty(isolate, target, key, attributes);
1724}
1725
1726namespace {
1727
1728template <AccessorComponent which_accessor>
1729Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
1730 Handle<Object> name, Handle<Object> accessor) {
1731 // 1. Let O be ? ToObject(this value).
1732 Handle<JSReceiver> receiver;
1733 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1734 Object::ConvertReceiver(isolate, object));
1735 // 2. If IsCallable(getter) is false, throw a TypeError exception.
1736 if (!accessor->IsCallable()) {
1737 MessageTemplate::Template message =
1738 which_accessor == ACCESSOR_GETTER
1739 ? MessageTemplate::kObjectGetterExpectingFunction
1740 : MessageTemplate::kObjectSetterExpectingFunction;
1741 THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
1742 }
1743 // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
1744 // [[Configurable]]: true}.
1745 PropertyDescriptor desc;
1746 if (which_accessor == ACCESSOR_GETTER) {
1747 desc.set_get(accessor);
1748 } else {
1749 DCHECK(which_accessor == ACCESSOR_SETTER);
1750 desc.set_set(accessor);
1751 }
1752 desc.set_enumerable(true);
1753 desc.set_configurable(true);
1754 // 4. Let key be ? ToPropertyKey(P).
1755 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1756 Object::ToPropertyKey(isolate, name));
1757 // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
1758 // To preserve legacy behavior, we ignore errors silently rather than
1759 // throwing an exception.
1760 Maybe<bool> success = JSReceiver::DefineOwnProperty(
1761 isolate, receiver, name, &desc, Object::DONT_THROW);
1762 MAYBE_RETURN(success, isolate->heap()->exception());
1763 // 6. Return undefined.
1764 return isolate->heap()->undefined_value();
1765}
1766
1767Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
1768 Handle<Object> key, AccessorComponent component) {
1769 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
1770 Object::ConvertReceiver(isolate, object));
1771 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1772 Object::ToPropertyKey(isolate, key));
1773 bool success = false;
1774 LookupIterator it = LookupIterator::PropertyOrElement(
1775 isolate, object, key, &success,
1776 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
1777 DCHECK(success);
1778
1779 for (; it.IsFound(); it.Next()) {
1780 switch (it.state()) {
1781 case LookupIterator::INTERCEPTOR:
1782 case LookupIterator::NOT_FOUND:
1783 case LookupIterator::TRANSITION:
1784 UNREACHABLE();
1785
1786 case LookupIterator::ACCESS_CHECK:
1787 if (it.HasAccess()) continue;
1788 isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
1789 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1790 return isolate->heap()->undefined_value();
1791
1792 case LookupIterator::JSPROXY:
1793 return isolate->heap()->undefined_value();
1794
1795 case LookupIterator::INTEGER_INDEXED_EXOTIC:
1796 return isolate->heap()->undefined_value();
1797 case LookupIterator::DATA:
1798 continue;
1799 case LookupIterator::ACCESSOR: {
1800 Handle<Object> maybe_pair = it.GetAccessors();
1801 if (maybe_pair->IsAccessorPair()) {
1802 return *AccessorPair::GetComponent(
1803 Handle<AccessorPair>::cast(maybe_pair), component);
1804 }
1805 }
1806 }
1807 }
1808
1809 return isolate->heap()->undefined_value();
1810}
1811
1812} // namespace
1813
1814// ES6 B.2.2.2 a.k.a.
1815// https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
1816BUILTIN(ObjectDefineGetter) {
1817 HandleScope scope(isolate);
1818 Handle<Object> object = args.at<Object>(0); // Receiver.
1819 Handle<Object> name = args.at<Object>(1);
1820 Handle<Object> getter = args.at<Object>(2);
1821 return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
1822}
1823
1824// ES6 B.2.2.3 a.k.a.
1825// https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
1826BUILTIN(ObjectDefineSetter) {
1827 HandleScope scope(isolate);
1828 Handle<Object> object = args.at<Object>(0); // Receiver.
1829 Handle<Object> name = args.at<Object>(1);
1830 Handle<Object> setter = args.at<Object>(2);
1831 return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
1832}
1833
1834// ES6 B.2.2.4 a.k.a.
1835// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
1836BUILTIN(ObjectLookupGetter) {
1837 HandleScope scope(isolate);
1838 Handle<Object> object = args.at<Object>(0);
1839 Handle<Object> name = args.at<Object>(1);
1840 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
1841}
1842
1843// ES6 B.2.2.5 a.k.a.
1844// https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
1845BUILTIN(ObjectLookupSetter) {
1846 HandleScope scope(isolate);
1847 Handle<Object> object = args.at<Object>(0);
1848 Handle<Object> name = args.at<Object>(1);
1849 return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
1850}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001851
1852// ES6 section 19.1.2.5 Object.freeze ( O )
1853BUILTIN(ObjectFreeze) {
1854 HandleScope scope(isolate);
1855 Handle<Object> object = args.atOrUndefined(isolate, 1);
1856 if (object->IsJSReceiver()) {
1857 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1858 FROZEN, Object::THROW_ON_ERROR),
1859 isolate->heap()->exception());
1860 }
1861 return *object;
1862}
1863
1864
Ben Murdochc5610432016-08-08 18:44:38 +01001865// ES section 19.1.2.9 Object.getPrototypeOf ( O )
1866BUILTIN(ObjectGetPrototypeOf) {
1867 HandleScope scope(isolate);
1868 Handle<Object> object = args.atOrUndefined(isolate, 1);
1869
1870 Handle<JSReceiver> receiver;
1871 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1872 isolate, receiver, Object::ToObject(isolate, object));
1873
1874 Handle<Object> prototype;
1875 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1876 isolate, prototype, JSReceiver::GetPrototype(isolate, receiver));
1877
1878 return *prototype;
1879}
1880
1881
Ben Murdoch097c5b22016-05-18 11:27:45 +01001882// ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
1883BUILTIN(ObjectGetOwnPropertyDescriptor) {
1884 HandleScope scope(isolate);
1885 // 1. Let obj be ? ToObject(O).
1886 Handle<Object> object = args.atOrUndefined(isolate, 1);
1887 Handle<JSReceiver> receiver;
1888 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1889 Object::ToObject(isolate, object));
1890 // 2. Let key be ? ToPropertyKey(P).
1891 Handle<Object> property = args.atOrUndefined(isolate, 2);
1892 Handle<Name> key;
1893 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
1894 Object::ToName(isolate, property));
1895 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
1896 PropertyDescriptor desc;
1897 Maybe<bool> found =
1898 JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
1899 MAYBE_RETURN(found, isolate->heap()->exception());
1900 // 4. Return FromPropertyDescriptor(desc).
1901 if (!found.FromJust()) return isolate->heap()->undefined_value();
1902 return *desc.ToObject(isolate);
1903}
1904
1905
1906namespace {
1907
1908Object* GetOwnPropertyKeys(Isolate* isolate,
1909 BuiltinArguments<BuiltinExtraArguments::kNone> args,
1910 PropertyFilter filter) {
1911 HandleScope scope(isolate);
1912 Handle<Object> object = args.atOrUndefined(isolate, 1);
1913 Handle<JSReceiver> receiver;
1914 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1915 Object::ToObject(isolate, object));
1916 Handle<FixedArray> keys;
1917 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1918 isolate, keys,
1919 JSReceiver::GetKeys(receiver, OWN_ONLY, filter, CONVERT_TO_STRING));
1920 return *isolate->factory()->NewJSArrayWithElements(keys);
1921}
1922
1923} // namespace
1924
1925
1926// ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
1927BUILTIN(ObjectGetOwnPropertyNames) {
1928 return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
1929}
1930
1931
1932// ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
1933BUILTIN(ObjectGetOwnPropertySymbols) {
1934 return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
1935}
1936
1937
1938// ES#sec-object.is Object.is ( value1, value2 )
1939BUILTIN(ObjectIs) {
1940 SealHandleScope shs(isolate);
1941 DCHECK_EQ(3, args.length());
1942 Handle<Object> value1 = args.at<Object>(1);
1943 Handle<Object> value2 = args.at<Object>(2);
1944 return isolate->heap()->ToBoolean(value1->SameValue(*value2));
1945}
1946
1947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001948// ES6 section 19.1.2.11 Object.isExtensible ( O )
1949BUILTIN(ObjectIsExtensible) {
1950 HandleScope scope(isolate);
1951 Handle<Object> object = args.atOrUndefined(isolate, 1);
1952 Maybe<bool> result =
1953 object->IsJSReceiver()
1954 ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
1955 : Just(false);
1956 MAYBE_RETURN(result, isolate->heap()->exception());
1957 return isolate->heap()->ToBoolean(result.FromJust());
1958}
1959
1960
1961// ES6 section 19.1.2.12 Object.isFrozen ( O )
1962BUILTIN(ObjectIsFrozen) {
1963 HandleScope scope(isolate);
1964 Handle<Object> object = args.atOrUndefined(isolate, 1);
1965 Maybe<bool> result = object->IsJSReceiver()
1966 ? JSReceiver::TestIntegrityLevel(
1967 Handle<JSReceiver>::cast(object), FROZEN)
1968 : Just(true);
1969 MAYBE_RETURN(result, isolate->heap()->exception());
1970 return isolate->heap()->ToBoolean(result.FromJust());
1971}
1972
1973
1974// ES6 section 19.1.2.13 Object.isSealed ( O )
1975BUILTIN(ObjectIsSealed) {
1976 HandleScope scope(isolate);
1977 Handle<Object> object = args.atOrUndefined(isolate, 1);
1978 Maybe<bool> result = object->IsJSReceiver()
1979 ? JSReceiver::TestIntegrityLevel(
1980 Handle<JSReceiver>::cast(object), SEALED)
1981 : Just(true);
1982 MAYBE_RETURN(result, isolate->heap()->exception());
1983 return isolate->heap()->ToBoolean(result.FromJust());
1984}
1985
1986
1987// ES6 section 19.1.2.14 Object.keys ( O )
1988BUILTIN(ObjectKeys) {
1989 HandleScope scope(isolate);
1990 Handle<Object> object = args.atOrUndefined(isolate, 1);
1991 Handle<JSReceiver> receiver;
1992 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001993 Object::ToObject(isolate, object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001994
Ben Murdoch097c5b22016-05-18 11:27:45 +01001995 Handle<FixedArray> keys;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001996 int enum_length = receiver->map()->EnumLength();
1997 if (enum_length != kInvalidEnumCacheSentinel &&
1998 JSObject::cast(*receiver)->elements() ==
1999 isolate->heap()->empty_fixed_array()) {
2000 DCHECK(receiver->IsJSObject());
2001 DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
2002 DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002003 DCHECK(!receiver->map()->has_hidden_prototype());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002004 DCHECK(JSObject::cast(*receiver)->HasFastProperties());
2005 if (enum_length == 0) {
2006 keys = isolate->factory()->empty_fixed_array();
2007 } else {
2008 Handle<FixedArray> cache(
2009 receiver->map()->instance_descriptors()->GetEnumCache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002010 keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002011 }
2012 } else {
2013 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2014 isolate, keys,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002015 JSReceiver::GetKeys(receiver, OWN_ONLY, ENUMERABLE_STRINGS,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002016 CONVERT_TO_STRING));
2017 }
2018 return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
2019}
2020
Ben Murdoch097c5b22016-05-18 11:27:45 +01002021BUILTIN(ObjectValues) {
2022 HandleScope scope(isolate);
2023 Handle<Object> object = args.atOrUndefined(isolate, 1);
2024 Handle<JSReceiver> receiver;
2025 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
2026 Object::ToObject(isolate, object));
2027 Handle<FixedArray> values;
2028 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2029 isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
2030 return *isolate->factory()->NewJSArrayWithElements(values);
2031}
2032
2033
2034BUILTIN(ObjectEntries) {
2035 HandleScope scope(isolate);
2036 Handle<Object> object = args.atOrUndefined(isolate, 1);
2037 Handle<JSReceiver> receiver;
2038 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
2039 Object::ToObject(isolate, object));
2040 Handle<FixedArray> entries;
2041 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2042 isolate, entries,
2043 JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
2044 return *isolate->factory()->NewJSArrayWithElements(entries);
2045}
2046
2047BUILTIN(ObjectGetOwnPropertyDescriptors) {
2048 HandleScope scope(isolate);
2049 Handle<Object> object = args.atOrUndefined(isolate, 1);
2050 Handle<Object> undefined = isolate->factory()->undefined_value();
2051
2052 Handle<JSReceiver> receiver;
2053 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
2054 Object::ToObject(isolate, object));
2055
2056 Handle<FixedArray> keys;
2057 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2058 isolate, keys, JSReceiver::GetKeys(receiver, OWN_ONLY, ALL_PROPERTIES,
2059 CONVERT_TO_STRING));
2060
Ben Murdochda12d292016-06-02 14:46:10 +01002061 Handle<JSObject> descriptors =
Ben Murdoch097c5b22016-05-18 11:27:45 +01002062 isolate->factory()->NewJSObject(isolate->object_function());
2063
2064 for (int i = 0; i < keys->length(); ++i) {
2065 Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
2066 PropertyDescriptor descriptor;
2067 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
2068 isolate, receiver, key, &descriptor);
2069 MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
2070
2071 Handle<Object> from_descriptor = did_get_descriptor.FromJust()
2072 ? descriptor.ToObject(isolate)
2073 : undefined;
2074
2075 LookupIterator it = LookupIterator::PropertyOrElement(
Ben Murdochda12d292016-06-02 14:46:10 +01002076 isolate, descriptors, key, descriptors, LookupIterator::OWN);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002077 Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
2078 Object::DONT_THROW);
2079 CHECK(success.FromJust());
2080 }
2081
2082 return *descriptors;
2083}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002084
2085// ES6 section 19.1.2.15 Object.preventExtensions ( O )
2086BUILTIN(ObjectPreventExtensions) {
2087 HandleScope scope(isolate);
2088 Handle<Object> object = args.atOrUndefined(isolate, 1);
2089 if (object->IsJSReceiver()) {
2090 MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
2091 Object::THROW_ON_ERROR),
2092 isolate->heap()->exception());
2093 }
2094 return *object;
2095}
2096
2097
2098// ES6 section 19.1.2.17 Object.seal ( O )
2099BUILTIN(ObjectSeal) {
2100 HandleScope scope(isolate);
2101 Handle<Object> object = args.atOrUndefined(isolate, 1);
2102 if (object->IsJSReceiver()) {
2103 MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
2104 SEALED, Object::THROW_ON_ERROR),
2105 isolate->heap()->exception());
2106 }
2107 return *object;
2108}
2109
Ben Murdochc5610432016-08-08 18:44:38 +01002110// ES6 section 18.2.6.4 encodeURI (uri)
2111BUILTIN(GlobalEncodeURI) {
2112 HandleScope scope(isolate);
2113 Handle<String> uri;
2114 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2115 isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2116
2117 return Uri::EncodeUri(isolate, uri);
2118}
2119
2120// ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
2121BUILTIN(GlobalEncodeURIComponent) {
2122 HandleScope scope(isolate);
2123 Handle<String> uriComponent;
2124 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2125 isolate, uriComponent,
2126 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2127
2128 return Uri::EncodeUriComponent(isolate, uriComponent);
2129}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002130
2131namespace {
2132
2133bool CodeGenerationFromStringsAllowed(Isolate* isolate,
2134 Handle<Context> context) {
2135 DCHECK(context->allow_code_gen_from_strings()->IsFalse());
2136 // Check with callback if set.
2137 AllowCodeGenerationFromStringsCallback callback =
2138 isolate->allow_code_gen_callback();
2139 if (callback == NULL) {
2140 // No callback set and code generation disallowed.
2141 return false;
2142 } else {
2143 // Callback set. Let it decide if code generation is allowed.
2144 VMState<EXTERNAL> state(isolate);
2145 return callback(v8::Utils::ToLocal(context));
2146 }
2147}
2148
2149
2150MaybeHandle<JSFunction> CompileString(Handle<Context> context,
2151 Handle<String> source,
2152 ParseRestriction restriction) {
2153 Isolate* const isolate = context->GetIsolate();
2154 Handle<Context> native_context(context->native_context(), isolate);
2155
2156 // Check if native context allows code generation from
2157 // strings. Throw an exception if it doesn't.
2158 if (native_context->allow_code_gen_from_strings()->IsFalse() &&
2159 !CodeGenerationFromStringsAllowed(isolate, native_context)) {
2160 Handle<Object> error_message =
2161 native_context->ErrorMessageForCodeGenerationFromStrings();
2162 THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
2163 error_message),
2164 JSFunction);
2165 }
2166
2167 // Compile source string in the native context.
Ben Murdochc5610432016-08-08 18:44:38 +01002168 int eval_scope_position = 0;
2169 int eval_position = RelocInfo::kNoPosition;
2170 Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002171 return Compiler::GetFunctionFromEval(source, outer_info, native_context,
Ben Murdochc5610432016-08-08 18:44:38 +01002172 SLOPPY, restriction, eval_scope_position,
2173 eval_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002174}
2175
2176} // namespace
2177
2178
2179// ES6 section 18.2.1 eval (x)
2180BUILTIN(GlobalEval) {
2181 HandleScope scope(isolate);
2182 Handle<Object> x = args.atOrUndefined(isolate, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002183 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002184 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
2185 if (!x->IsString()) return *x;
2186 Handle<JSFunction> function;
2187 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2188 isolate, function,
2189 CompileString(handle(target->native_context(), isolate),
2190 Handle<String>::cast(x), NO_PARSE_RESTRICTION));
2191 Handle<Object> result;
2192 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2193 isolate, result,
2194 Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
2195 return *result;
2196}
2197
2198
Ben Murdochda12d292016-06-02 14:46:10 +01002199// -----------------------------------------------------------------------------
2200// ES6 section 20.2.2 Function Properties of the Math Object
2201
2202
2203// ES6 section 20.2.2.2 Math.acos ( x )
2204BUILTIN(MathAcos) {
2205 HandleScope scope(isolate);
2206 DCHECK_EQ(2, args.length());
2207 Handle<Object> x = args.at<Object>(1);
2208 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2209 return *isolate->factory()->NewHeapNumber(std::acos(x->Number()));
2210}
2211
2212
2213// ES6 section 20.2.2.4 Math.asin ( x )
2214BUILTIN(MathAsin) {
2215 HandleScope scope(isolate);
2216 DCHECK_EQ(2, args.length());
2217 Handle<Object> x = args.at<Object>(1);
2218 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2219 return *isolate->factory()->NewHeapNumber(std::asin(x->Number()));
2220}
2221
2222
2223// ES6 section 20.2.2.6 Math.atan ( x )
2224BUILTIN(MathAtan) {
2225 HandleScope scope(isolate);
2226 DCHECK_EQ(2, args.length());
2227 Handle<Object> x = args.at<Object>(1);
2228 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2229 return *isolate->factory()->NewHeapNumber(std::atan(x->Number()));
2230}
2231
2232namespace {
2233
2234void Generate_MathRoundingOperation(
Ben Murdochc5610432016-08-08 18:44:38 +01002235 CodeStubAssembler* assembler,
2236 compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
2237 typedef CodeStubAssembler::Label Label;
Ben Murdochda12d292016-06-02 14:46:10 +01002238 typedef compiler::Node Node;
Ben Murdochc5610432016-08-08 18:44:38 +01002239 typedef CodeStubAssembler::Variable Variable;
Ben Murdochda12d292016-06-02 14:46:10 +01002240
2241 Node* context = assembler->Parameter(4);
2242
2243 // We might need to loop once for ToNumber conversion.
2244 Variable var_x(assembler, MachineRepresentation::kTagged);
2245 Label loop(assembler, &var_x);
2246 var_x.Bind(assembler->Parameter(1));
2247 assembler->Goto(&loop);
2248 assembler->Bind(&loop);
2249 {
2250 // Load the current {x} value.
2251 Node* x = var_x.value();
2252
2253 // Check if {x} is a Smi or a HeapObject.
2254 Label if_xissmi(assembler), if_xisnotsmi(assembler);
2255 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2256
2257 assembler->Bind(&if_xissmi);
2258 {
2259 // Nothing to do when {x} is a Smi.
2260 assembler->Return(x);
2261 }
2262
2263 assembler->Bind(&if_xisnotsmi);
2264 {
2265 // Check if {x} is a HeapNumber.
2266 Label if_xisheapnumber(assembler),
2267 if_xisnotheapnumber(assembler, Label::kDeferred);
2268 assembler->Branch(
2269 assembler->WordEqual(assembler->LoadMap(x),
2270 assembler->HeapNumberMapConstant()),
2271 &if_xisheapnumber, &if_xisnotheapnumber);
2272
2273 assembler->Bind(&if_xisheapnumber);
2274 {
2275 Node* x_value = assembler->LoadHeapNumberValue(x);
2276 Node* value = (assembler->*float64op)(x_value);
2277 Node* result = assembler->ChangeFloat64ToTagged(value);
2278 assembler->Return(result);
2279 }
2280
2281 assembler->Bind(&if_xisnotheapnumber);
2282 {
2283 // Need to convert {x} to a Number first.
2284 Callable callable =
2285 CodeFactory::NonNumberToNumber(assembler->isolate());
2286 var_x.Bind(assembler->CallStub(callable, context, x));
2287 assembler->Goto(&loop);
2288 }
2289 }
2290 }
2291}
2292
2293} // namespace
2294
2295// ES6 section 20.2.2.10 Math.ceil ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002296void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
2297 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
Ben Murdochda12d292016-06-02 14:46:10 +01002298}
2299
2300// ES6 section 20.2.2.11 Math.clz32 ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002301void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
2302 typedef CodeStubAssembler::Label Label;
Ben Murdochda12d292016-06-02 14:46:10 +01002303 typedef compiler::Node Node;
Ben Murdochc5610432016-08-08 18:44:38 +01002304 typedef CodeStubAssembler::Variable Variable;
Ben Murdochda12d292016-06-02 14:46:10 +01002305
2306 Node* context = assembler->Parameter(4);
2307
2308 // Shared entry point for the clz32 operation.
2309 Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
2310 Label do_clz32(assembler);
2311
2312 // We might need to loop once for ToNumber conversion.
2313 Variable var_x(assembler, MachineRepresentation::kTagged);
2314 Label loop(assembler, &var_x);
2315 var_x.Bind(assembler->Parameter(1));
2316 assembler->Goto(&loop);
2317 assembler->Bind(&loop);
2318 {
2319 // Load the current {x} value.
2320 Node* x = var_x.value();
2321
2322 // Check if {x} is a Smi or a HeapObject.
2323 Label if_xissmi(assembler), if_xisnotsmi(assembler);
2324 assembler->Branch(assembler->WordIsSmi(x), &if_xissmi, &if_xisnotsmi);
2325
2326 assembler->Bind(&if_xissmi);
2327 {
2328 var_clz32_x.Bind(assembler->SmiToWord32(x));
2329 assembler->Goto(&do_clz32);
2330 }
2331
2332 assembler->Bind(&if_xisnotsmi);
2333 {
2334 // Check if {x} is a HeapNumber.
2335 Label if_xisheapnumber(assembler),
2336 if_xisnotheapnumber(assembler, Label::kDeferred);
2337 assembler->Branch(
2338 assembler->WordEqual(assembler->LoadMap(x),
2339 assembler->HeapNumberMapConstant()),
2340 &if_xisheapnumber, &if_xisnotheapnumber);
2341
2342 assembler->Bind(&if_xisheapnumber);
2343 {
2344 var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
2345 assembler->Goto(&do_clz32);
2346 }
2347
2348 assembler->Bind(&if_xisnotheapnumber);
2349 {
2350 // Need to convert {x} to a Number first.
2351 Callable callable =
2352 CodeFactory::NonNumberToNumber(assembler->isolate());
2353 var_x.Bind(assembler->CallStub(callable, context, x));
2354 assembler->Goto(&loop);
2355 }
2356 }
2357 }
2358
2359 assembler->Bind(&do_clz32);
2360 {
2361 Node* x_value = var_clz32_x.value();
2362 Node* value = assembler->Word32Clz(x_value);
2363 Node* result = assembler->ChangeInt32ToTagged(value);
2364 assembler->Return(result);
2365 }
2366}
2367
2368// ES6 section 20.2.2.16 Math.floor ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002369void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
2370 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
Ben Murdochda12d292016-06-02 14:46:10 +01002371}
2372
2373// ES6 section 20.2.2.17 Math.fround ( x )
2374BUILTIN(MathFround) {
2375 HandleScope scope(isolate);
2376 DCHECK_EQ(2, args.length());
2377 Handle<Object> x = args.at<Object>(1);
2378 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2379 float x32 = DoubleToFloat32(x->Number());
2380 return *isolate->factory()->NewNumber(x32);
2381}
2382
2383// ES6 section 20.2.2.19 Math.imul ( x, y )
2384BUILTIN(MathImul) {
2385 HandleScope scope(isolate);
2386 DCHECK_EQ(3, args.length());
2387 Handle<Object> x = args.at<Object>(1);
2388 Handle<Object> y = args.at<Object>(2);
2389 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
2390 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, y, Object::ToNumber(y));
2391 int product = static_cast<int>(NumberToUint32(*x) * NumberToUint32(*y));
2392 return *isolate->factory()->NewNumberFromInt(product);
2393}
2394
2395// ES6 section 20.2.2.28 Math.round ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002396void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
2397 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
Ben Murdochda12d292016-06-02 14:46:10 +01002398}
2399
2400// ES6 section 20.2.2.32 Math.sqrt ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002401void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01002402 using compiler::Node;
2403
2404 Node* x = assembler->Parameter(1);
2405 Node* context = assembler->Parameter(4);
2406 Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
2407 Node* value = assembler->Float64Sqrt(x_value);
2408 Node* result = assembler->ChangeFloat64ToTagged(value);
2409 assembler->Return(result);
2410}
2411
2412// ES6 section 20.2.2.35 Math.trunc ( x )
Ben Murdochc5610432016-08-08 18:44:38 +01002413void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
2414 Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
2415}
2416
2417// -----------------------------------------------------------------------------
2418// ES6 section 19.2 Function Objects
2419
2420// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
2421void Builtins::Generate_FunctionPrototypeHasInstance(
2422 CodeStubAssembler* assembler) {
2423 using compiler::Node;
2424
2425 Node* f = assembler->Parameter(0);
2426 Node* v = assembler->Parameter(1);
2427 Node* context = assembler->Parameter(4);
2428 Node* result = assembler->OrdinaryHasInstance(context, f, v);
2429 assembler->Return(result);
2430}
2431
2432// -----------------------------------------------------------------------------
2433// ES6 section 25.3 Generator Objects
2434
2435namespace {
2436
2437void Generate_GeneratorPrototypeResume(
2438 CodeStubAssembler* assembler, JSGeneratorObject::ResumeMode resume_mode,
2439 char const* const method_name) {
2440 typedef CodeStubAssembler::Label Label;
2441 typedef compiler::Node Node;
2442
2443 Node* receiver = assembler->Parameter(0);
2444 Node* value = assembler->Parameter(1);
2445 Node* context = assembler->Parameter(4);
2446 Node* closed = assembler->SmiConstant(
2447 Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
2448
2449 // Check if the {receiver} is actually a JSGeneratorObject.
2450 Label if_receiverisincompatible(assembler, Label::kDeferred);
2451 assembler->GotoIf(assembler->WordIsSmi(receiver), &if_receiverisincompatible);
2452 Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
2453 assembler->GotoUnless(assembler->Word32Equal(
2454 receiver_instance_type,
2455 assembler->Int32Constant(JS_GENERATOR_OBJECT_TYPE)),
2456 &if_receiverisincompatible);
2457
2458 // Check if the {receiver} is running or already closed.
2459 Node* receiver_continuation = assembler->LoadObjectField(
2460 receiver, JSGeneratorObject::kContinuationOffset);
2461 Label if_receiverisclosed(assembler, Label::kDeferred),
2462 if_receiverisrunning(assembler, Label::kDeferred);
2463 assembler->GotoIf(assembler->SmiEqual(receiver_continuation, closed),
2464 &if_receiverisclosed);
2465 DCHECK_LT(JSGeneratorObject::kGeneratorExecuting,
2466 JSGeneratorObject::kGeneratorClosed);
2467 assembler->GotoIf(assembler->SmiLessThan(receiver_continuation, closed),
2468 &if_receiverisrunning);
2469
2470 // Resume the {receiver} using our trampoline.
2471 Node* result = assembler->CallStub(
2472 CodeFactory::ResumeGenerator(assembler->isolate()), context, value,
2473 receiver, assembler->SmiConstant(Smi::FromInt(resume_mode)));
2474 assembler->Return(result);
2475
2476 assembler->Bind(&if_receiverisincompatible);
2477 {
2478 // The {receiver} is not a valid JSGeneratorObject.
2479 Node* result = assembler->CallRuntime(
2480 Runtime::kThrowIncompatibleMethodReceiver, context,
2481 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
2482 method_name, TENURED)),
2483 receiver);
2484 assembler->Return(result); // Never reached.
2485 }
2486
2487 assembler->Bind(&if_receiverisclosed);
2488 {
2489 // The {receiver} is closed already.
2490 Node* result = nullptr;
2491 switch (resume_mode) {
2492 case JSGeneratorObject::kNext:
2493 result = assembler->CallRuntime(Runtime::kCreateIterResultObject,
2494 context, assembler->UndefinedConstant(),
2495 assembler->BooleanConstant(true));
2496 break;
2497 case JSGeneratorObject::kReturn:
2498 result =
2499 assembler->CallRuntime(Runtime::kCreateIterResultObject, context,
2500 value, assembler->BooleanConstant(true));
2501 break;
2502 case JSGeneratorObject::kThrow:
2503 result = assembler->CallRuntime(Runtime::kThrow, context, value);
2504 break;
2505 }
2506 assembler->Return(result);
2507 }
2508
2509 assembler->Bind(&if_receiverisrunning);
2510 {
2511 Node* result =
2512 assembler->CallRuntime(Runtime::kThrowGeneratorRunning, context);
2513 assembler->Return(result); // Never reached.
2514 }
2515}
2516
2517} // namespace
2518
2519// ES6 section 25.3.1.2 Generator.prototype.next ( value )
2520void Builtins::Generate_GeneratorPrototypeNext(CodeStubAssembler* assembler) {
2521 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kNext,
2522 "[Generator].prototype.next");
2523}
2524
2525// ES6 section 25.3.1.3 Generator.prototype.return ( value )
2526void Builtins::Generate_GeneratorPrototypeReturn(CodeStubAssembler* assembler) {
2527 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kReturn,
2528 "[Generator].prototype.return");
2529}
2530
2531// ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
2532void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) {
2533 Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow,
2534 "[Generator].prototype.throw");
Ben Murdochda12d292016-06-02 14:46:10 +01002535}
2536
2537// -----------------------------------------------------------------------------
2538// ES6 section 26.1 The Reflect Object
2539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002540// ES6 section 26.1.3 Reflect.defineProperty
2541BUILTIN(ReflectDefineProperty) {
2542 HandleScope scope(isolate);
2543 DCHECK_EQ(4, args.length());
2544 Handle<Object> target = args.at<Object>(1);
2545 Handle<Object> key = args.at<Object>(2);
2546 Handle<Object> attributes = args.at<Object>(3);
2547
2548 if (!target->IsJSReceiver()) {
2549 THROW_NEW_ERROR_RETURN_FAILURE(
2550 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2551 isolate->factory()->NewStringFromAsciiChecked(
2552 "Reflect.defineProperty")));
2553 }
2554
2555 Handle<Name> name;
2556 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2557 Object::ToName(isolate, key));
2558
2559 PropertyDescriptor desc;
2560 if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
2561 return isolate->heap()->exception();
2562 }
2563
2564 Maybe<bool> result =
2565 JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
2566 name, &desc, Object::DONT_THROW);
2567 MAYBE_RETURN(result, isolate->heap()->exception());
2568 return *isolate->factory()->ToBoolean(result.FromJust());
2569}
2570
2571
2572// ES6 section 26.1.4 Reflect.deleteProperty
2573BUILTIN(ReflectDeleteProperty) {
2574 HandleScope scope(isolate);
2575 DCHECK_EQ(3, args.length());
2576 Handle<Object> target = args.at<Object>(1);
2577 Handle<Object> key = args.at<Object>(2);
2578
2579 if (!target->IsJSReceiver()) {
2580 THROW_NEW_ERROR_RETURN_FAILURE(
2581 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2582 isolate->factory()->NewStringFromAsciiChecked(
2583 "Reflect.deleteProperty")));
2584 }
2585
2586 Handle<Name> name;
2587 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2588 Object::ToName(isolate, key));
2589
2590 Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
2591 Handle<JSReceiver>::cast(target), name, SLOPPY);
2592 MAYBE_RETURN(result, isolate->heap()->exception());
2593 return *isolate->factory()->ToBoolean(result.FromJust());
2594}
2595
2596
2597// ES6 section 26.1.6 Reflect.get
2598BUILTIN(ReflectGet) {
2599 HandleScope scope(isolate);
2600 Handle<Object> target = args.atOrUndefined(isolate, 1);
2601 Handle<Object> key = args.atOrUndefined(isolate, 2);
2602 Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
2603
2604 if (!target->IsJSReceiver()) {
2605 THROW_NEW_ERROR_RETURN_FAILURE(
2606 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2607 isolate->factory()->NewStringFromAsciiChecked(
2608 "Reflect.get")));
2609 }
2610
2611 Handle<Name> name;
2612 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2613 Object::ToName(isolate, key));
2614
2615 Handle<Object> result;
2616 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2617 isolate, result, Object::GetPropertyOrElement(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002618 receiver, name, Handle<JSReceiver>::cast(target)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002619
2620 return *result;
2621}
2622
2623
2624// ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
2625BUILTIN(ReflectGetOwnPropertyDescriptor) {
2626 HandleScope scope(isolate);
2627 DCHECK_EQ(3, args.length());
2628 Handle<Object> target = args.at<Object>(1);
2629 Handle<Object> key = args.at<Object>(2);
2630
2631 if (!target->IsJSReceiver()) {
2632 THROW_NEW_ERROR_RETURN_FAILURE(
2633 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2634 isolate->factory()->NewStringFromAsciiChecked(
2635 "Reflect.getOwnPropertyDescriptor")));
2636 }
2637
2638 Handle<Name> name;
2639 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2640 Object::ToName(isolate, key));
2641
2642 PropertyDescriptor desc;
2643 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
2644 isolate, Handle<JSReceiver>::cast(target), name, &desc);
2645 MAYBE_RETURN(found, isolate->heap()->exception());
2646 if (!found.FromJust()) return isolate->heap()->undefined_value();
2647 return *desc.ToObject(isolate);
2648}
2649
2650
2651// ES6 section 26.1.8 Reflect.getPrototypeOf
2652BUILTIN(ReflectGetPrototypeOf) {
2653 HandleScope scope(isolate);
2654 DCHECK_EQ(2, args.length());
2655 Handle<Object> target = args.at<Object>(1);
2656
2657 if (!target->IsJSReceiver()) {
2658 THROW_NEW_ERROR_RETURN_FAILURE(
2659 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2660 isolate->factory()->NewStringFromAsciiChecked(
2661 "Reflect.getPrototypeOf")));
2662 }
2663 Handle<Object> prototype;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002664 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(target);
2665 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2666 isolate, prototype, JSReceiver::GetPrototype(isolate, receiver));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002667 return *prototype;
2668}
2669
2670
2671// ES6 section 26.1.9 Reflect.has
2672BUILTIN(ReflectHas) {
2673 HandleScope scope(isolate);
2674 DCHECK_EQ(3, args.length());
2675 Handle<Object> target = args.at<Object>(1);
2676 Handle<Object> key = args.at<Object>(2);
2677
2678 if (!target->IsJSReceiver()) {
2679 THROW_NEW_ERROR_RETURN_FAILURE(
2680 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2681 isolate->factory()->NewStringFromAsciiChecked(
2682 "Reflect.has")));
2683 }
2684
2685 Handle<Name> name;
2686 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2687 Object::ToName(isolate, key));
2688
2689 Maybe<bool> result =
2690 JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
2691 return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
2692 : isolate->heap()->exception();
2693}
2694
2695
2696// ES6 section 26.1.10 Reflect.isExtensible
2697BUILTIN(ReflectIsExtensible) {
2698 HandleScope scope(isolate);
2699 DCHECK_EQ(2, args.length());
2700 Handle<Object> target = args.at<Object>(1);
2701
2702 if (!target->IsJSReceiver()) {
2703 THROW_NEW_ERROR_RETURN_FAILURE(
2704 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2705 isolate->factory()->NewStringFromAsciiChecked(
2706 "Reflect.isExtensible")));
2707 }
2708
2709 Maybe<bool> result =
2710 JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
2711 MAYBE_RETURN(result, isolate->heap()->exception());
2712 return *isolate->factory()->ToBoolean(result.FromJust());
2713}
2714
2715
2716// ES6 section 26.1.11 Reflect.ownKeys
2717BUILTIN(ReflectOwnKeys) {
2718 HandleScope scope(isolate);
2719 DCHECK_EQ(2, args.length());
2720 Handle<Object> target = args.at<Object>(1);
2721
2722 if (!target->IsJSReceiver()) {
2723 THROW_NEW_ERROR_RETURN_FAILURE(
2724 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2725 isolate->factory()->NewStringFromAsciiChecked(
2726 "Reflect.ownKeys")));
2727 }
2728
2729 Handle<FixedArray> keys;
2730 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002731 isolate, keys,
2732 JSReceiver::GetKeys(Handle<JSReceiver>::cast(target), OWN_ONLY,
2733 ALL_PROPERTIES, CONVERT_TO_STRING));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002734 return *isolate->factory()->NewJSArrayWithElements(keys);
2735}
2736
2737
2738// ES6 section 26.1.12 Reflect.preventExtensions
2739BUILTIN(ReflectPreventExtensions) {
2740 HandleScope scope(isolate);
2741 DCHECK_EQ(2, args.length());
2742 Handle<Object> target = args.at<Object>(1);
2743
2744 if (!target->IsJSReceiver()) {
2745 THROW_NEW_ERROR_RETURN_FAILURE(
2746 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2747 isolate->factory()->NewStringFromAsciiChecked(
2748 "Reflect.preventExtensions")));
2749 }
2750
2751 Maybe<bool> result = JSReceiver::PreventExtensions(
2752 Handle<JSReceiver>::cast(target), Object::DONT_THROW);
2753 MAYBE_RETURN(result, isolate->heap()->exception());
2754 return *isolate->factory()->ToBoolean(result.FromJust());
2755}
2756
2757
2758// ES6 section 26.1.13 Reflect.set
2759BUILTIN(ReflectSet) {
2760 HandleScope scope(isolate);
2761 Handle<Object> target = args.atOrUndefined(isolate, 1);
2762 Handle<Object> key = args.atOrUndefined(isolate, 2);
2763 Handle<Object> value = args.atOrUndefined(isolate, 3);
2764 Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
2765
2766 if (!target->IsJSReceiver()) {
2767 THROW_NEW_ERROR_RETURN_FAILURE(
2768 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2769 isolate->factory()->NewStringFromAsciiChecked(
2770 "Reflect.set")));
2771 }
2772
2773 Handle<Name> name;
2774 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
2775 Object::ToName(isolate, key));
2776
2777 LookupIterator it = LookupIterator::PropertyOrElement(
2778 isolate, receiver, name, Handle<JSReceiver>::cast(target));
2779 Maybe<bool> result = Object::SetSuperProperty(
2780 &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
2781 MAYBE_RETURN(result, isolate->heap()->exception());
2782 return *isolate->factory()->ToBoolean(result.FromJust());
2783}
2784
2785
2786// ES6 section 26.1.14 Reflect.setPrototypeOf
2787BUILTIN(ReflectSetPrototypeOf) {
2788 HandleScope scope(isolate);
2789 DCHECK_EQ(3, args.length());
2790 Handle<Object> target = args.at<Object>(1);
2791 Handle<Object> proto = args.at<Object>(2);
2792
2793 if (!target->IsJSReceiver()) {
2794 THROW_NEW_ERROR_RETURN_FAILURE(
2795 isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
2796 isolate->factory()->NewStringFromAsciiChecked(
2797 "Reflect.setPrototypeOf")));
2798 }
2799
2800 if (!proto->IsJSReceiver() && !proto->IsNull()) {
2801 THROW_NEW_ERROR_RETURN_FAILURE(
2802 isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2803 }
2804
2805 Maybe<bool> result = JSReceiver::SetPrototype(
2806 Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2807 MAYBE_RETURN(result, isolate->heap()->exception());
2808 return *isolate->factory()->ToBoolean(result.FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002809}
2810
2811
Steve Blocka7e24c12009-10-30 11:49:00 +00002812// -----------------------------------------------------------------------------
Ben Murdoch097c5b22016-05-18 11:27:45 +01002813// ES6 section 19.3 Boolean Objects
2814
2815
2816// ES6 section 19.3.1.1 Boolean ( value ) for the [[Call]] case.
2817BUILTIN(BooleanConstructor) {
2818 HandleScope scope(isolate);
2819 Handle<Object> value = args.atOrUndefined(isolate, 1);
2820 return isolate->heap()->ToBoolean(value->BooleanValue());
2821}
2822
2823
2824// ES6 section 19.3.1.1 Boolean ( value ) for the [[Construct]] case.
2825BUILTIN(BooleanConstructor_ConstructStub) {
2826 HandleScope scope(isolate);
2827 Handle<Object> value = args.atOrUndefined(isolate, 1);
2828 Handle<JSFunction> target = args.target<JSFunction>();
2829 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2830 DCHECK(*target == target->native_context()->boolean_function());
2831 Handle<JSObject> result;
2832 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2833 JSObject::New(target, new_target));
2834 Handle<JSValue>::cast(result)->set_value(
2835 isolate->heap()->ToBoolean(value->BooleanValue()));
2836 return *result;
2837}
2838
2839
2840// ES6 section 19.3.3.2 Boolean.prototype.toString ( )
2841BUILTIN(BooleanPrototypeToString) {
2842 HandleScope scope(isolate);
2843 Handle<Object> receiver = args.receiver();
2844 if (receiver->IsJSValue()) {
2845 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
2846 }
2847 if (!receiver->IsBoolean()) {
2848 THROW_NEW_ERROR_RETURN_FAILURE(
2849 isolate, NewTypeError(MessageTemplate::kNotGeneric,
2850 isolate->factory()->NewStringFromAsciiChecked(
2851 "Boolean.prototype.toString")));
2852 }
2853 return Handle<Oddball>::cast(receiver)->to_string();
2854}
2855
2856
2857// ES6 section 19.3.3.3 Boolean.prototype.valueOf ( )
2858BUILTIN(BooleanPrototypeValueOf) {
2859 HandleScope scope(isolate);
2860 Handle<Object> receiver = args.receiver();
2861 if (receiver->IsJSValue()) {
2862 receiver = handle(Handle<JSValue>::cast(receiver)->value(), isolate);
2863 }
2864 if (!receiver->IsBoolean()) {
2865 THROW_NEW_ERROR_RETURN_FAILURE(
2866 isolate, NewTypeError(MessageTemplate::kNotGeneric,
2867 isolate->factory()->NewStringFromAsciiChecked(
2868 "Boolean.prototype.valueOf")));
2869 }
2870 return *receiver;
2871}
2872
2873
2874// -----------------------------------------------------------------------------
2875// ES6 section 24.2 DataView Objects
2876
2877
2878// ES6 section 24.2.2 The DataView Constructor for the [[Call]] case.
2879BUILTIN(DataViewConstructor) {
2880 HandleScope scope(isolate);
2881 THROW_NEW_ERROR_RETURN_FAILURE(
2882 isolate,
2883 NewTypeError(MessageTemplate::kConstructorNotFunction,
2884 isolate->factory()->NewStringFromAsciiChecked("DataView")));
2885}
2886
2887
2888// ES6 section 24.2.2 The DataView Constructor for the [[Construct]] case.
2889BUILTIN(DataViewConstructor_ConstructStub) {
2890 HandleScope scope(isolate);
2891 Handle<JSFunction> target = args.target<JSFunction>();
2892 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2893 Handle<Object> buffer = args.atOrUndefined(isolate, 1);
2894 Handle<Object> byte_offset = args.atOrUndefined(isolate, 2);
2895 Handle<Object> byte_length = args.atOrUndefined(isolate, 3);
2896
2897 // 2. If Type(buffer) is not Object, throw a TypeError exception.
2898 // 3. If buffer does not have an [[ArrayBufferData]] internal slot, throw a
2899 // TypeError exception.
2900 if (!buffer->IsJSArrayBuffer()) {
2901 THROW_NEW_ERROR_RETURN_FAILURE(
2902 isolate, NewTypeError(MessageTemplate::kDataViewNotArrayBuffer));
2903 }
2904 Handle<JSArrayBuffer> array_buffer = Handle<JSArrayBuffer>::cast(buffer);
2905
2906 // 4. Let numberOffset be ? ToNumber(byteOffset).
2907 Handle<Object> number_offset;
2908 if (byte_offset->IsUndefined()) {
2909 // We intentionally violate the specification at this point to allow
2910 // for new DataView(buffer) invocations to be equivalent to the full
2911 // new DataView(buffer, 0) invocation.
2912 number_offset = handle(Smi::FromInt(0), isolate);
2913 } else {
2914 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_offset,
2915 Object::ToNumber(byte_offset));
2916 }
2917
2918 // 5. Let offset be ToInteger(numberOffset).
2919 Handle<Object> offset;
2920 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, offset,
2921 Object::ToInteger(isolate, number_offset));
2922
2923 // 6. If numberOffset ≠ offset or offset < 0, throw a RangeError exception.
2924 if (number_offset->Number() != offset->Number() || offset->Number() < 0.0) {
2925 THROW_NEW_ERROR_RETURN_FAILURE(
2926 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2927 }
2928
2929 // 7. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
2930 // We currently violate the specification at this point.
2931
2932 // 8. Let bufferByteLength be the value of buffer's [[ArrayBufferByteLength]]
2933 // internal slot.
2934 double const buffer_byte_length = array_buffer->byte_length()->Number();
2935
2936 // 9. If offset > bufferByteLength, throw a RangeError exception
2937 if (offset->Number() > buffer_byte_length) {
2938 THROW_NEW_ERROR_RETURN_FAILURE(
2939 isolate, NewRangeError(MessageTemplate::kInvalidDataViewOffset));
2940 }
2941
2942 Handle<Object> view_byte_length;
2943 if (byte_length->IsUndefined()) {
2944 // 10. If byteLength is undefined, then
2945 // a. Let viewByteLength be bufferByteLength - offset.
2946 view_byte_length =
2947 isolate->factory()->NewNumber(buffer_byte_length - offset->Number());
2948 } else {
2949 // 11. Else,
2950 // a. Let viewByteLength be ? ToLength(byteLength).
2951 // b. If offset+viewByteLength > bufferByteLength, throw a RangeError
2952 // exception
2953 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2954 isolate, view_byte_length, Object::ToLength(isolate, byte_length));
2955 if (offset->Number() + view_byte_length->Number() > buffer_byte_length) {
2956 THROW_NEW_ERROR_RETURN_FAILURE(
2957 isolate, NewRangeError(MessageTemplate::kInvalidDataViewLength));
2958 }
2959 }
2960
2961 // 12. Let O be ? OrdinaryCreateFromConstructor(NewTarget,
2962 // "%DataViewPrototype%", «[[DataView]], [[ViewedArrayBuffer]],
2963 // [[ByteLength]], [[ByteOffset]]»).
2964 // 13. Set O's [[DataView]] internal slot to true.
2965 Handle<JSObject> result;
2966 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2967 JSObject::New(target, new_target));
2968 for (int i = 0; i < ArrayBufferView::kInternalFieldCount; ++i) {
2969 Handle<JSDataView>::cast(result)->SetInternalField(i, Smi::FromInt(0));
2970 }
2971
2972 // 14. Set O's [[ViewedArrayBuffer]] internal slot to buffer.
2973 Handle<JSDataView>::cast(result)->set_buffer(*array_buffer);
2974
2975 // 15. Set O's [[ByteLength]] internal slot to viewByteLength.
2976 Handle<JSDataView>::cast(result)->set_byte_length(*view_byte_length);
2977
2978 // 16. Set O's [[ByteOffset]] internal slot to offset.
2979 Handle<JSDataView>::cast(result)->set_byte_offset(*offset);
2980
2981 // 17. Return O.
2982 return *result;
2983}
2984
2985
2986// -----------------------------------------------------------------------------
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002987// ES6 section 20.3 Date Objects
Steve Block44f0eee2011-05-26 01:26:41 +01002988
2989
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002990namespace {
2991
2992// ES6 section 20.3.1.1 Time Values and Time Range
2993const double kMinYear = -1000000.0;
2994const double kMaxYear = -kMinYear;
2995const double kMinMonth = -10000000.0;
2996const double kMaxMonth = -kMinMonth;
2997
2998
2999// 20.3.1.2 Day Number and Time within Day
3000const double kMsPerDay = 86400000.0;
3001
3002
3003// ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
3004const double kMsPerSecond = 1000.0;
3005const double kMsPerMinute = 60000.0;
3006const double kMsPerHour = 3600000.0;
3007
3008
3009// ES6 section 20.3.1.14 MakeDate (day, time)
3010double MakeDate(double day, double time) {
3011 if (std::isfinite(day) && std::isfinite(time)) {
3012 return time + day * kMsPerDay;
3013 }
3014 return std::numeric_limits<double>::quiet_NaN();
Steve Block44f0eee2011-05-26 01:26:41 +01003015}
3016
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003017
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003018// ES6 section 20.3.1.13 MakeDay (year, month, date)
3019double MakeDay(double year, double month, double date) {
3020 if ((kMinYear <= year && year <= kMaxYear) &&
3021 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
3022 int y = FastD2I(year);
3023 int m = FastD2I(month);
3024 y += m / 12;
3025 m %= 12;
3026 if (m < 0) {
3027 m += 12;
3028 y -= 1;
3029 }
3030 DCHECK_LE(0, m);
3031 DCHECK_LT(m, 12);
3032
3033 // kYearDelta is an arbitrary number such that:
3034 // a) kYearDelta = -1 (mod 400)
3035 // b) year + kYearDelta > 0 for years in the range defined by
3036 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
3037 // Jan 1 1970. This is required so that we don't run into integer
3038 // division of negative numbers.
3039 // c) there shouldn't be an overflow for 32-bit integers in the following
3040 // operations.
3041 static const int kYearDelta = 399999;
3042 static const int kBaseDay =
3043 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
3044 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
3045 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
3046 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
3047 kBaseDay;
3048 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
3049 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151,
3050 181, 212, 243, 273, 304, 334};
3051 day_from_year += kDayFromMonth[m];
3052 } else {
3053 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152,
3054 182, 213, 244, 274, 305, 335};
3055 day_from_year += kDayFromMonth[m];
3056 }
3057 return static_cast<double>(day_from_year - 1) + date;
3058 }
3059 return std::numeric_limits<double>::quiet_NaN();
3060}
3061
3062
3063// ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
3064double MakeTime(double hour, double min, double sec, double ms) {
3065 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
3066 std::isfinite(ms)) {
3067 double const h = DoubleToInteger(hour);
3068 double const m = DoubleToInteger(min);
3069 double const s = DoubleToInteger(sec);
3070 double const milli = DoubleToInteger(ms);
3071 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
3072 }
3073 return std::numeric_limits<double>::quiet_NaN();
3074}
3075
3076
3077// ES6 section 20.3.1.15 TimeClip (time)
3078double TimeClip(double time) {
3079 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
3080 return DoubleToInteger(time) + 0.0;
3081 }
3082 return std::numeric_limits<double>::quiet_NaN();
3083}
3084
3085
3086const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
3087 "Thu", "Fri", "Sat"};
3088const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
3089 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
3090
3091
3092// ES6 section 20.3.1.16 Date Time String Format
3093double ParseDateTimeString(Handle<String> str) {
3094 Isolate* const isolate = str->GetIsolate();
3095 str = String::Flatten(str);
3096 // TODO(bmeurer): Change DateParser to not use the FixedArray.
3097 Handle<FixedArray> tmp =
3098 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
3099 DisallowHeapAllocation no_gc;
3100 String::FlatContent str_content = str->GetFlatContent();
3101 bool result;
3102 if (str_content.IsOneByte()) {
3103 result = DateParser::Parse(str_content.ToOneByteVector(), *tmp,
3104 isolate->unicode_cache());
3105 } else {
3106 result = DateParser::Parse(str_content.ToUC16Vector(), *tmp,
3107 isolate->unicode_cache());
3108 }
3109 if (!result) return std::numeric_limits<double>::quiet_NaN();
3110 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
3111 tmp->get(2)->Number());
3112 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
3113 tmp->get(5)->Number(), tmp->get(6)->Number());
3114 double date = MakeDate(day, time);
3115 if (tmp->get(7)->IsNull()) {
3116 if (!std::isnan(date)) {
3117 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
3118 }
3119 } else {
3120 date -= tmp->get(7)->Number() * 1000.0;
3121 }
3122 return date;
3123}
3124
3125
3126enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
3127
3128
3129// ES6 section 20.3.4.41.1 ToDateString(tv)
3130void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
3131 ToDateStringMode mode = kDateAndTime) {
3132 if (std::isnan(time_val)) {
3133 SNPrintF(str, "Invalid Date");
3134 return;
3135 }
3136 int64_t time_ms = static_cast<int64_t>(time_val);
3137 int64_t local_time_ms = date_cache->ToLocal(time_ms);
3138 int year, month, day, weekday, hour, min, sec, ms;
3139 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
3140 &min, &sec, &ms);
3141 int timezone_offset = -date_cache->TimezoneOffset(time_ms);
3142 int timezone_hour = std::abs(timezone_offset) / 60;
3143 int timezone_min = std::abs(timezone_offset) % 60;
3144 const char* local_timezone = date_cache->LocalTimezone(time_ms);
3145 switch (mode) {
3146 case kDateOnly:
3147 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
3148 kShortMonths[month], day, year);
3149 return;
3150 case kTimeOnly:
3151 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
3152 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
3153 local_timezone);
3154 return;
3155 case kDateAndTime:
3156 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
3157 kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
3158 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
3159 timezone_min, local_timezone);
3160 return;
3161 }
3162 UNREACHABLE();
3163}
3164
3165
3166Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
3167 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
3168 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
3169 Isolate* const isolate = date->GetIsolate();
3170 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
3171 } else {
3172 time_val = std::numeric_limits<double>::quiet_NaN();
3173 }
3174 return *JSDate::SetValue(date, TimeClip(time_val));
3175}
3176
3177} // namespace
3178
3179
3180// ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
3181BUILTIN(DateConstructor) {
3182 HandleScope scope(isolate);
3183 double const time_val = JSDate::CurrentTimeValue(isolate);
3184 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01003185 ToDateString(time_val, ArrayVector(buffer), isolate->date_cache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003186 Handle<String> result;
3187 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3188 isolate, result,
3189 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3190 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003191}
3192
3193
3194// ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
3195BUILTIN(DateConstructor_ConstructStub) {
3196 HandleScope scope(isolate);
3197 int const argc = args.length() - 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +01003198 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003199 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3200 double time_val;
3201 if (argc == 0) {
3202 time_val = JSDate::CurrentTimeValue(isolate);
3203 } else if (argc == 1) {
3204 Handle<Object> value = args.at<Object>(1);
3205 if (value->IsJSDate()) {
3206 time_val = Handle<JSDate>::cast(value)->value()->Number();
3207 } else {
3208 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
3209 Object::ToPrimitive(value));
3210 if (value->IsString()) {
3211 time_val = ParseDateTimeString(Handle<String>::cast(value));
3212 } else {
3213 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
3214 Object::ToNumber(value));
3215 time_val = value->Number();
3216 }
3217 }
3218 } else {
3219 Handle<Object> year_object;
3220 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3221 Object::ToNumber(args.at<Object>(1)));
3222 Handle<Object> month_object;
3223 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3224 Object::ToNumber(args.at<Object>(2)));
3225 double year = year_object->Number();
3226 double month = month_object->Number();
3227 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3228 if (argc >= 3) {
3229 Handle<Object> date_object;
3230 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
3231 Object::ToNumber(args.at<Object>(3)));
3232 date = date_object->Number();
3233 if (argc >= 4) {
3234 Handle<Object> hours_object;
3235 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3236 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3237 hours = hours_object->Number();
3238 if (argc >= 5) {
3239 Handle<Object> minutes_object;
3240 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3241 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3242 minutes = minutes_object->Number();
3243 if (argc >= 6) {
3244 Handle<Object> seconds_object;
3245 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3246 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
3247 seconds = seconds_object->Number();
3248 if (argc >= 7) {
3249 Handle<Object> ms_object;
3250 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3251 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3252 ms = ms_object->Number();
3253 }
3254 }
3255 }
3256 }
3257 }
3258 if (!std::isnan(year)) {
3259 double const y = DoubleToInteger(year);
3260 if (0.0 <= y && y <= 99) year = 1900 + y;
3261 }
3262 double const day = MakeDay(year, month, date);
3263 double const time = MakeTime(hours, minutes, seconds, ms);
3264 time_val = MakeDate(day, time);
3265 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
3266 time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
3267 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
3268 } else {
3269 time_val = std::numeric_limits<double>::quiet_NaN();
3270 }
3271 }
3272 Handle<JSDate> result;
3273 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3274 JSDate::New(target, new_target, time_val));
3275 return *result;
3276}
3277
3278
3279// ES6 section 20.3.3.1 Date.now ( )
3280BUILTIN(DateNow) {
3281 HandleScope scope(isolate);
3282 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
3283}
3284
3285
3286// ES6 section 20.3.3.2 Date.parse ( string )
3287BUILTIN(DateParse) {
3288 HandleScope scope(isolate);
3289 Handle<String> string;
3290 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3291 isolate, string,
3292 Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
3293 return *isolate->factory()->NewNumber(ParseDateTimeString(string));
3294}
3295
3296
3297// ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
3298BUILTIN(DateUTC) {
3299 HandleScope scope(isolate);
3300 int const argc = args.length() - 1;
3301 double year = std::numeric_limits<double>::quiet_NaN();
3302 double month = std::numeric_limits<double>::quiet_NaN();
3303 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
3304 if (argc >= 1) {
3305 Handle<Object> year_object;
3306 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
3307 Object::ToNumber(args.at<Object>(1)));
3308 year = year_object->Number();
3309 if (argc >= 2) {
3310 Handle<Object> month_object;
3311 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
3312 Object::ToNumber(args.at<Object>(2)));
3313 month = month_object->Number();
3314 if (argc >= 3) {
3315 Handle<Object> date_object;
3316 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3317 isolate, date_object, Object::ToNumber(args.at<Object>(3)));
3318 date = date_object->Number();
3319 if (argc >= 4) {
3320 Handle<Object> hours_object;
3321 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3322 isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
3323 hours = hours_object->Number();
3324 if (argc >= 5) {
3325 Handle<Object> minutes_object;
3326 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3327 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
3328 minutes = minutes_object->Number();
3329 if (argc >= 6) {
3330 Handle<Object> seconds_object;
3331 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3332 isolate, seconds_object,
3333 Object::ToNumber(args.at<Object>(6)));
3334 seconds = seconds_object->Number();
3335 if (argc >= 7) {
3336 Handle<Object> ms_object;
3337 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3338 isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
3339 ms = ms_object->Number();
3340 }
3341 }
3342 }
3343 }
3344 }
3345 }
3346 }
3347 if (!std::isnan(year)) {
3348 double const y = DoubleToInteger(year);
3349 if (0.0 <= y && y <= 99) year = 1900 + y;
3350 }
3351 double const day = MakeDay(year, month, date);
3352 double const time = MakeTime(hours, minutes, seconds, ms);
3353 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
3354}
3355
3356
3357// ES6 section 20.3.4.20 Date.prototype.setDate ( date )
3358BUILTIN(DatePrototypeSetDate) {
3359 HandleScope scope(isolate);
3360 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
3361 Handle<Object> value = args.atOrUndefined(isolate, 1);
3362 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3363 double time_val = date->value()->Number();
3364 if (!std::isnan(time_val)) {
3365 int64_t const time_ms = static_cast<int64_t>(time_val);
3366 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3367 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3368 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3369 int year, month, day;
3370 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3371 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3372 }
3373 return SetLocalDateValue(date, time_val);
3374}
3375
3376
3377// ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
3378BUILTIN(DatePrototypeSetFullYear) {
3379 HandleScope scope(isolate);
3380 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
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 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3389 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3390 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3391 int year, month, day;
3392 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3393 m = month;
3394 dt = day;
3395 }
3396 if (argc >= 2) {
3397 Handle<Object> month = args.at<Object>(2);
3398 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3399 m = month->Number();
3400 if (argc >= 3) {
3401 Handle<Object> date = args.at<Object>(3);
3402 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3403 dt = date->Number();
3404 }
3405 }
3406 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3407 return SetLocalDateValue(date, time_val);
3408}
3409
3410
3411// ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
3412BUILTIN(DatePrototypeSetHours) {
3413 HandleScope scope(isolate);
3414 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
3415 int const argc = args.length() - 1;
3416 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3417 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3418 double h = hour->Number();
3419 double time_val = date->value()->Number();
3420 if (!std::isnan(time_val)) {
3421 int64_t const time_ms = static_cast<int64_t>(time_val);
3422 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3423 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3424 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3425 double m = (time_within_day / (60 * 1000)) % 60;
3426 double s = (time_within_day / 1000) % 60;
3427 double milli = time_within_day % 1000;
3428 if (argc >= 2) {
3429 Handle<Object> min = args.at<Object>(2);
3430 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3431 m = min->Number();
3432 if (argc >= 3) {
3433 Handle<Object> sec = args.at<Object>(3);
3434 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3435 s = sec->Number();
3436 if (argc >= 4) {
3437 Handle<Object> ms = args.at<Object>(4);
3438 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3439 milli = ms->Number();
3440 }
3441 }
3442 }
3443 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3444 }
3445 return SetLocalDateValue(date, time_val);
3446}
3447
3448
3449// ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
3450BUILTIN(DatePrototypeSetMilliseconds) {
3451 HandleScope scope(isolate);
3452 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
3453 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3454 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3455 double time_val = date->value()->Number();
3456 if (!std::isnan(time_val)) {
3457 int64_t const time_ms = static_cast<int64_t>(time_val);
3458 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3459 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3460 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3461 int h = time_within_day / (60 * 60 * 1000);
3462 int m = (time_within_day / (60 * 1000)) % 60;
3463 int s = (time_within_day / 1000) % 60;
3464 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3465 }
3466 return SetLocalDateValue(date, time_val);
3467}
3468
3469
3470// ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
3471BUILTIN(DatePrototypeSetMinutes) {
3472 HandleScope scope(isolate);
3473 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
3474 int const argc = args.length() - 1;
3475 Handle<Object> min = args.atOrUndefined(isolate, 1);
3476 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3477 double time_val = date->value()->Number();
3478 if (!std::isnan(time_val)) {
3479 int64_t const time_ms = static_cast<int64_t>(time_val);
3480 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3481 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3482 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3483 int h = time_within_day / (60 * 60 * 1000);
3484 double m = min->Number();
3485 double s = (time_within_day / 1000) % 60;
3486 double milli = time_within_day % 1000;
3487 if (argc >= 2) {
3488 Handle<Object> sec = args.at<Object>(2);
3489 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3490 s = sec->Number();
3491 if (argc >= 3) {
3492 Handle<Object> ms = args.at<Object>(3);
3493 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3494 milli = ms->Number();
3495 }
3496 }
3497 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3498 }
3499 return SetLocalDateValue(date, time_val);
3500}
3501
3502
3503// ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
3504BUILTIN(DatePrototypeSetMonth) {
3505 HandleScope scope(isolate);
3506 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
3507 int const argc = args.length() - 1;
3508 Handle<Object> month = args.atOrUndefined(isolate, 1);
3509 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3510 double time_val = date->value()->Number();
3511 if (!std::isnan(time_val)) {
3512 int64_t const time_ms = static_cast<int64_t>(time_val);
3513 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3514 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3515 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3516 int year, unused, day;
3517 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3518 double m = month->Number();
3519 double dt = day;
3520 if (argc >= 2) {
3521 Handle<Object> date = args.at<Object>(2);
3522 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3523 dt = date->Number();
3524 }
3525 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3526 }
3527 return SetLocalDateValue(date, time_val);
3528}
3529
3530
3531// ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
3532BUILTIN(DatePrototypeSetSeconds) {
3533 HandleScope scope(isolate);
3534 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
3535 int const argc = args.length() - 1;
3536 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3537 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3538 double time_val = date->value()->Number();
3539 if (!std::isnan(time_val)) {
3540 int64_t const time_ms = static_cast<int64_t>(time_val);
3541 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3542 int day = isolate->date_cache()->DaysFromTime(local_time_ms);
3543 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
3544 int h = time_within_day / (60 * 60 * 1000);
3545 double m = (time_within_day / (60 * 1000)) % 60;
3546 double s = sec->Number();
3547 double milli = time_within_day % 1000;
3548 if (argc >= 2) {
3549 Handle<Object> ms = args.at<Object>(2);
3550 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3551 milli = ms->Number();
3552 }
3553 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3554 }
3555 return SetLocalDateValue(date, time_val);
3556}
3557
3558
3559// ES6 section 20.3.4.27 Date.prototype.setTime ( time )
3560BUILTIN(DatePrototypeSetTime) {
3561 HandleScope scope(isolate);
3562 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
3563 Handle<Object> value = args.atOrUndefined(isolate, 1);
3564 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3565 return *JSDate::SetValue(date, TimeClip(value->Number()));
3566}
3567
3568
3569// ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
3570BUILTIN(DatePrototypeSetUTCDate) {
3571 HandleScope scope(isolate);
3572 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
3573 Handle<Object> value = args.atOrUndefined(isolate, 1);
3574 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
3575 if (std::isnan(date->value()->Number())) return date->value();
3576 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3577 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3578 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3579 int year, month, day;
3580 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3581 double const time_val =
3582 MakeDate(MakeDay(year, month, value->Number()), time_within_day);
3583 return *JSDate::SetValue(date, TimeClip(time_val));
3584}
3585
3586
3587// ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
3588BUILTIN(DatePrototypeSetUTCFullYear) {
3589 HandleScope scope(isolate);
3590 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
3591 int const argc = args.length() - 1;
3592 Handle<Object> year = args.atOrUndefined(isolate, 1);
3593 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3594 double y = year->Number(), m = 0.0, dt = 1.0;
3595 int time_within_day = 0;
3596 if (!std::isnan(date->value()->Number())) {
3597 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3598 int const days = isolate->date_cache()->DaysFromTime(time_ms);
3599 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3600 int year, month, day;
3601 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3602 m = month;
3603 dt = day;
3604 }
3605 if (argc >= 2) {
3606 Handle<Object> month = args.at<Object>(2);
3607 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3608 m = month->Number();
3609 if (argc >= 3) {
3610 Handle<Object> date = args.at<Object>(3);
3611 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3612 dt = date->Number();
3613 }
3614 }
3615 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3616 return *JSDate::SetValue(date, TimeClip(time_val));
3617}
3618
3619
3620// ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
3621BUILTIN(DatePrototypeSetUTCHours) {
3622 HandleScope scope(isolate);
3623 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
3624 int const argc = args.length() - 1;
3625 Handle<Object> hour = args.atOrUndefined(isolate, 1);
3626 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
3627 double h = hour->Number();
3628 double time_val = date->value()->Number();
3629 if (!std::isnan(time_val)) {
3630 int64_t const time_ms = static_cast<int64_t>(time_val);
3631 int day = isolate->date_cache()->DaysFromTime(time_ms);
3632 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3633 double m = (time_within_day / (60 * 1000)) % 60;
3634 double s = (time_within_day / 1000) % 60;
3635 double milli = time_within_day % 1000;
3636 if (argc >= 2) {
3637 Handle<Object> min = args.at<Object>(2);
3638 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3639 m = min->Number();
3640 if (argc >= 3) {
3641 Handle<Object> sec = args.at<Object>(3);
3642 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3643 s = sec->Number();
3644 if (argc >= 4) {
3645 Handle<Object> ms = args.at<Object>(4);
3646 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3647 milli = ms->Number();
3648 }
3649 }
3650 }
3651 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3652 }
3653 return *JSDate::SetValue(date, TimeClip(time_val));
3654}
3655
3656
3657// ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
3658BUILTIN(DatePrototypeSetUTCMilliseconds) {
3659 HandleScope scope(isolate);
3660 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
3661 Handle<Object> ms = args.atOrUndefined(isolate, 1);
3662 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3663 double time_val = date->value()->Number();
3664 if (!std::isnan(time_val)) {
3665 int64_t const time_ms = static_cast<int64_t>(time_val);
3666 int day = isolate->date_cache()->DaysFromTime(time_ms);
3667 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3668 int h = time_within_day / (60 * 60 * 1000);
3669 int m = (time_within_day / (60 * 1000)) % 60;
3670 int s = (time_within_day / 1000) % 60;
3671 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
3672 }
3673 return *JSDate::SetValue(date, TimeClip(time_val));
3674}
3675
3676
3677// ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
3678BUILTIN(DatePrototypeSetUTCMinutes) {
3679 HandleScope scope(isolate);
3680 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
3681 int const argc = args.length() - 1;
3682 Handle<Object> min = args.atOrUndefined(isolate, 1);
3683 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
3684 double time_val = date->value()->Number();
3685 if (!std::isnan(time_val)) {
3686 int64_t const time_ms = static_cast<int64_t>(time_val);
3687 int day = isolate->date_cache()->DaysFromTime(time_ms);
3688 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3689 int h = time_within_day / (60 * 60 * 1000);
3690 double m = min->Number();
3691 double s = (time_within_day / 1000) % 60;
3692 double milli = time_within_day % 1000;
3693 if (argc >= 2) {
3694 Handle<Object> sec = args.at<Object>(2);
3695 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3696 s = sec->Number();
3697 if (argc >= 3) {
3698 Handle<Object> ms = args.at<Object>(3);
3699 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3700 milli = ms->Number();
3701 }
3702 }
3703 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3704 }
3705 return *JSDate::SetValue(date, TimeClip(time_val));
3706}
3707
3708
3709// ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
3710BUILTIN(DatePrototypeSetUTCMonth) {
3711 HandleScope scope(isolate);
3712 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
3713 int const argc = args.length() - 1;
3714 Handle<Object> month = args.atOrUndefined(isolate, 1);
3715 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
3716 double time_val = date->value()->Number();
3717 if (!std::isnan(time_val)) {
3718 int64_t const time_ms = static_cast<int64_t>(time_val);
3719 int days = isolate->date_cache()->DaysFromTime(time_ms);
3720 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
3721 int year, unused, day;
3722 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
3723 double m = month->Number();
3724 double dt = day;
3725 if (argc >= 2) {
3726 Handle<Object> date = args.at<Object>(2);
3727 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
3728 dt = date->Number();
3729 }
3730 time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
3731 }
3732 return *JSDate::SetValue(date, TimeClip(time_val));
3733}
3734
3735
3736// ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
3737BUILTIN(DatePrototypeSetUTCSeconds) {
3738 HandleScope scope(isolate);
3739 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
3740 int const argc = args.length() - 1;
3741 Handle<Object> sec = args.atOrUndefined(isolate, 1);
3742 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
3743 double time_val = date->value()->Number();
3744 if (!std::isnan(time_val)) {
3745 int64_t const time_ms = static_cast<int64_t>(time_val);
3746 int day = isolate->date_cache()->DaysFromTime(time_ms);
3747 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
3748 int h = time_within_day / (60 * 60 * 1000);
3749 double m = (time_within_day / (60 * 1000)) % 60;
3750 double s = sec->Number();
3751 double milli = time_within_day % 1000;
3752 if (argc >= 2) {
3753 Handle<Object> ms = args.at<Object>(2);
3754 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
3755 milli = ms->Number();
3756 }
3757 time_val = MakeDate(day, MakeTime(h, m, s, milli));
3758 }
3759 return *JSDate::SetValue(date, TimeClip(time_val));
3760}
3761
3762
3763// ES6 section 20.3.4.35 Date.prototype.toDateString ( )
3764BUILTIN(DatePrototypeToDateString) {
3765 HandleScope scope(isolate);
3766 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
3767 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01003768 ToDateString(date->value()->Number(), ArrayVector(buffer),
3769 isolate->date_cache(), kDateOnly);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003770 Handle<String> result;
3771 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3772 isolate, result,
3773 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3774 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003775}
3776
3777
3778// ES6 section 20.3.4.36 Date.prototype.toISOString ( )
3779BUILTIN(DatePrototypeToISOString) {
3780 HandleScope scope(isolate);
3781 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
3782 double const time_val = date->value()->Number();
3783 if (std::isnan(time_val)) {
3784 THROW_NEW_ERROR_RETURN_FAILURE(
3785 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
3786 }
3787 int64_t const time_ms = static_cast<int64_t>(time_val);
3788 int year, month, day, weekday, hour, min, sec, ms;
3789 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3790 &hour, &min, &sec, &ms);
3791 char buffer[128];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003792 if (year >= 0 && year <= 9999) {
Ben Murdochc5610432016-08-08 18:44:38 +01003793 SNPrintF(ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
3794 month + 1, day, hour, min, sec, ms);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003795 } else if (year < 0) {
Ben Murdochc5610432016-08-08 18:44:38 +01003796 SNPrintF(ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year,
3797 month + 1, day, hour, min, sec, ms);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003798 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01003799 SNPrintF(ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
3800 month + 1, day, hour, min, sec, ms);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003801 }
Ben Murdochc5610432016-08-08 18:44:38 +01003802 return *isolate->factory()->NewStringFromAsciiChecked(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003803}
3804
3805
3806// ES6 section 20.3.4.41 Date.prototype.toString ( )
3807BUILTIN(DatePrototypeToString) {
3808 HandleScope scope(isolate);
3809 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
3810 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01003811 ToDateString(date->value()->Number(), ArrayVector(buffer),
3812 isolate->date_cache());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003813 Handle<String> result;
3814 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3815 isolate, result,
3816 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3817 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003818}
3819
3820
3821// ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
3822BUILTIN(DatePrototypeToTimeString) {
3823 HandleScope scope(isolate);
3824 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
3825 char buffer[128];
Ben Murdochc5610432016-08-08 18:44:38 +01003826 ToDateString(date->value()->Number(), ArrayVector(buffer),
3827 isolate->date_cache(), kTimeOnly);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003828 Handle<String> result;
3829 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3830 isolate, result,
3831 isolate->factory()->NewStringFromUtf8(CStrVector(buffer)));
3832 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003833}
3834
3835
3836// ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
3837BUILTIN(DatePrototypeToUTCString) {
3838 HandleScope scope(isolate);
3839 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
3840 double const time_val = date->value()->Number();
3841 if (std::isnan(time_val)) {
3842 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
3843 }
3844 char buffer[128];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003845 int64_t time_ms = static_cast<int64_t>(time_val);
3846 int year, month, day, weekday, hour, min, sec, ms;
3847 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
3848 &hour, &min, &sec, &ms);
Ben Murdochc5610432016-08-08 18:44:38 +01003849 SNPrintF(ArrayVector(buffer), "%s, %02d %s %4d %02d:%02d:%02d GMT",
3850 kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min,
3851 sec);
3852 return *isolate->factory()->NewStringFromAsciiChecked(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003853}
3854
3855
3856// ES6 section 20.3.4.44 Date.prototype.valueOf ( )
3857BUILTIN(DatePrototypeValueOf) {
3858 HandleScope scope(isolate);
3859 CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
3860 return date->value();
3861}
3862
3863
3864// ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
3865BUILTIN(DatePrototypeToPrimitive) {
3866 HandleScope scope(isolate);
3867 DCHECK_EQ(2, args.length());
3868 CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
3869 Handle<Object> hint = args.at<Object>(1);
3870 Handle<Object> result;
3871 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3872 JSDate::ToPrimitive(receiver, hint));
3873 return *result;
3874}
3875
3876
3877// ES6 section B.2.4.1 Date.prototype.getYear ( )
3878BUILTIN(DatePrototypeGetYear) {
3879 HandleScope scope(isolate);
3880 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
3881 double time_val = date->value()->Number();
3882 if (std::isnan(time_val)) return date->value();
3883 int64_t time_ms = static_cast<int64_t>(time_val);
3884 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3885 int days = isolate->date_cache()->DaysFromTime(local_time_ms);
3886 int year, month, day;
3887 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3888 return Smi::FromInt(year - 1900);
3889}
3890
3891
3892// ES6 section B.2.4.2 Date.prototype.setYear ( year )
3893BUILTIN(DatePrototypeSetYear) {
3894 HandleScope scope(isolate);
3895 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
3896 Handle<Object> year = args.atOrUndefined(isolate, 1);
3897 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
3898 double m = 0.0, dt = 1.0, y = year->Number();
3899 if (0.0 <= y && y <= 99.0) {
3900 y = 1900.0 + DoubleToInteger(y);
3901 }
3902 int time_within_day = 0;
3903 if (!std::isnan(date->value()->Number())) {
3904 int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
3905 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
3906 int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
3907 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
3908 int year, month, day;
3909 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
3910 m = month;
3911 dt = day;
3912 }
3913 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
3914 return SetLocalDateValue(date, time_val);
3915}
3916
3917
3918// static
3919void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
3920 Generate_DatePrototype_GetField(masm, JSDate::kDay);
3921}
3922
3923
3924// static
3925void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
3926 Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
3927}
3928
3929
3930// static
3931void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
3932 Generate_DatePrototype_GetField(masm, JSDate::kYear);
3933}
3934
3935
3936// static
3937void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
3938 Generate_DatePrototype_GetField(masm, JSDate::kHour);
3939}
3940
3941
3942// static
3943void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
3944 Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
3945}
3946
3947
3948// static
3949void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
3950 Generate_DatePrototype_GetField(masm, JSDate::kMinute);
3951}
3952
3953
3954// static
3955void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
3956 Generate_DatePrototype_GetField(masm, JSDate::kMonth);
3957}
3958
3959
3960// static
3961void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
3962 Generate_DatePrototype_GetField(masm, JSDate::kSecond);
3963}
3964
3965
3966// static
3967void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
3968 Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
3969}
3970
3971
3972// static
3973void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
3974 Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
3975}
3976
3977
3978// static
3979void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
3980 Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
3981}
3982
3983
3984// static
3985void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
3986 Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
3987}
3988
3989
3990// static
3991void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
3992 Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
3993}
3994
3995
3996// static
3997void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
3998 Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
3999}
4000
4001
4002// static
4003void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
4004 Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
4005}
4006
4007
4008// static
4009void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
4010 Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
4011}
4012
4013
4014// static
4015void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
4016 Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
4017}
4018
4019
4020// static
4021void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
4022 Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
4023}
4024
4025
4026namespace {
4027
4028// ES6 section 19.2.1.1.1 CreateDynamicFunction
4029MaybeHandle<JSFunction> CreateDynamicFunction(
4030 Isolate* isolate,
4031 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,
4032 const char* token) {
4033 // Compute number of arguments, ignoring the receiver.
4034 DCHECK_LE(1, args.length());
4035 int const argc = args.length() - 1;
4036
4037 // Build the source string.
4038 Handle<String> source;
4039 {
4040 IncrementalStringBuilder builder(isolate);
4041 builder.AppendCharacter('(');
4042 builder.AppendCString(token);
4043 builder.AppendCharacter('(');
4044 bool parenthesis_in_arg_string = false;
4045 if (argc > 1) {
4046 for (int i = 1; i < argc; ++i) {
4047 if (i > 1) builder.AppendCharacter(',');
4048 Handle<String> param;
4049 ASSIGN_RETURN_ON_EXCEPTION(
4050 isolate, param, Object::ToString(isolate, args.at<Object>(i)),
4051 JSFunction);
4052 param = String::Flatten(param);
4053 builder.AppendString(param);
4054 // If the formal parameters string include ) - an illegal
4055 // character - it may make the combined function expression
4056 // compile. We avoid this problem by checking for this early on.
4057 DisallowHeapAllocation no_gc; // Ensure vectors stay valid.
4058 String::FlatContent param_content = param->GetFlatContent();
4059 for (int i = 0, length = param->length(); i < length; ++i) {
4060 if (param_content.Get(i) == ')') {
4061 parenthesis_in_arg_string = true;
4062 break;
4063 }
4064 }
4065 }
4066 // If the formal parameters include an unbalanced block comment, the
4067 // function must be rejected. Since JavaScript does not allow nested
4068 // comments we can include a trailing block comment to catch this.
4069 builder.AppendCString("\n/**/");
4070 }
4071 builder.AppendCString(") {\n");
4072 if (argc > 0) {
4073 Handle<String> body;
4074 ASSIGN_RETURN_ON_EXCEPTION(
4075 isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
4076 JSFunction);
4077 builder.AppendString(body);
4078 }
4079 builder.AppendCString("\n})");
4080 ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction);
4081
4082 // The SyntaxError must be thrown after all the (observable) ToString
4083 // conversions are done.
4084 if (parenthesis_in_arg_string) {
4085 THROW_NEW_ERROR(isolate,
4086 NewSyntaxError(MessageTemplate::kParenthesisInArgString),
4087 JSFunction);
4088 }
4089 }
4090
4091 // Compile the string in the constructor and not a helper so that errors to
4092 // come from here.
Ben Murdoch097c5b22016-05-18 11:27:45 +01004093 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004094 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
4095 Handle<JSFunction> function;
4096 {
4097 ASSIGN_RETURN_ON_EXCEPTION(
4098 isolate, function,
4099 CompileString(handle(target->native_context(), isolate), source,
4100 ONLY_SINGLE_FUNCTION_LITERAL),
4101 JSFunction);
4102 Handle<Object> result;
4103 ASSIGN_RETURN_ON_EXCEPTION(
4104 isolate, result,
4105 Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
4106 JSFunction);
4107 function = Handle<JSFunction>::cast(result);
4108 function->shared()->set_name_should_print_as_anonymous(true);
4109 }
4110
4111 // If new.target is equal to target then the function created
4112 // is already correctly setup and nothing else should be done
4113 // here. But if new.target is not equal to target then we are
4114 // have a Function builtin subclassing case and therefore the
4115 // function has wrong initial map. To fix that we create a new
4116 // function object with correct initial map.
4117 Handle<Object> unchecked_new_target = args.new_target();
4118 if (!unchecked_new_target->IsUndefined() &&
4119 !unchecked_new_target.is_identical_to(target)) {
4120 Handle<JSReceiver> new_target =
4121 Handle<JSReceiver>::cast(unchecked_new_target);
4122 Handle<Map> initial_map;
4123 ASSIGN_RETURN_ON_EXCEPTION(
4124 isolate, initial_map,
4125 JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction);
4126
4127 Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
4128 Handle<Map> map = Map::AsLanguageMode(
4129 initial_map, shared_info->language_mode(), shared_info->kind());
4130
4131 Handle<Context> context(function->context(), isolate);
4132 function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
4133 map, shared_info, context, NOT_TENURED);
4134 }
4135 return function;
4136}
4137
4138} // namespace
4139
4140
4141// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
4142BUILTIN(FunctionConstructor) {
4143 HandleScope scope(isolate);
4144 Handle<JSFunction> result;
4145 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4146 isolate, result, CreateDynamicFunction(isolate, args, "function"));
4147 return *result;
4148}
4149
4150
4151// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
4152BUILTIN(FunctionPrototypeBind) {
4153 HandleScope scope(isolate);
4154 DCHECK_LE(1, args.length());
4155 if (!args.receiver()->IsCallable()) {
4156 THROW_NEW_ERROR_RETURN_FAILURE(
4157 isolate, NewTypeError(MessageTemplate::kFunctionBind));
4158 }
4159
4160 // Allocate the bound function with the given {this_arg} and {args}.
4161 Handle<JSReceiver> target = args.at<JSReceiver>(0);
4162 Handle<Object> this_arg = isolate->factory()->undefined_value();
4163 ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
4164 if (args.length() > 1) {
4165 this_arg = args.at<Object>(1);
4166 for (int i = 2; i < args.length(); ++i) {
4167 argv[i - 2] = args.at<Object>(i);
4168 }
4169 }
4170 Handle<JSBoundFunction> function;
4171 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4172 isolate, function,
4173 isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
4174
Ben Murdochc5610432016-08-08 18:44:38 +01004175 LookupIterator length_lookup(target, isolate->factory()->length_string(),
4176 target, LookupIterator::OWN);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004177 // Setup the "length" property based on the "length" of the {target}.
Ben Murdochc5610432016-08-08 18:44:38 +01004178 // If the targets length is the default JSFunction accessor, we can keep the
4179 // accessor that's installed by default on the JSBoundFunction. It lazily
4180 // computes the value from the underlying internal length.
4181 if (!target->IsJSFunction() ||
4182 length_lookup.state() != LookupIterator::ACCESSOR ||
4183 !length_lookup.GetAccessors()->IsAccessorInfo()) {
4184 Handle<Object> length(Smi::FromInt(0), isolate);
4185 Maybe<PropertyAttributes> attributes =
4186 JSReceiver::GetPropertyAttributes(&length_lookup);
4187 if (!attributes.IsJust()) return isolate->heap()->exception();
4188 if (attributes.FromJust() != ABSENT) {
4189 Handle<Object> target_length;
4190 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length,
4191 Object::GetProperty(&length_lookup));
4192 if (target_length->IsNumber()) {
4193 length = isolate->factory()->NewNumber(std::max(
4194 0.0, DoubleToInteger(target_length->Number()) - argv.length()));
4195 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004196 }
Ben Murdochc5610432016-08-08 18:44:38 +01004197 LookupIterator it(function, isolate->factory()->length_string(), function);
4198 DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
4199 RETURN_FAILURE_ON_EXCEPTION(isolate,
4200 JSObject::DefineOwnPropertyIgnoreAttributes(
4201 &it, length, it.property_attributes()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004202 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004203
4204 // Setup the "name" property based on the "name" of the {target}.
Ben Murdochc5610432016-08-08 18:44:38 +01004205 // If the targets name is the default JSFunction accessor, we can keep the
4206 // accessor that's installed by default on the JSBoundFunction. It lazily
4207 // computes the value from the underlying internal name.
4208 LookupIterator name_lookup(target, isolate->factory()->name_string(), target,
4209 LookupIterator::OWN);
4210 if (!target->IsJSFunction() ||
4211 name_lookup.state() != LookupIterator::ACCESSOR ||
4212 !name_lookup.GetAccessors()->IsAccessorInfo()) {
4213 Handle<Object> target_name;
4214 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name,
4215 Object::GetProperty(&name_lookup));
4216 Handle<String> name;
4217 if (target_name->IsString()) {
4218 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4219 isolate, name,
4220 Name::ToFunctionName(Handle<String>::cast(target_name)));
4221 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4222 isolate, name, isolate->factory()->NewConsString(
4223 isolate->factory()->bound__string(), name));
4224 } else {
4225 name = isolate->factory()->bound__string();
4226 }
4227 LookupIterator it(function, isolate->factory()->name_string());
4228 DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
4229 RETURN_FAILURE_ON_EXCEPTION(isolate,
4230 JSObject::DefineOwnPropertyIgnoreAttributes(
4231 &it, name, it.property_attributes()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004232 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004233 return *function;
4234}
4235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004236// ES6 section 19.2.3.5 Function.prototype.toString ( )
4237BUILTIN(FunctionPrototypeToString) {
4238 HandleScope scope(isolate);
4239 Handle<Object> receiver = args.receiver();
4240 if (receiver->IsJSBoundFunction()) {
4241 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
4242 } else if (receiver->IsJSFunction()) {
4243 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
4244 }
4245 THROW_NEW_ERROR_RETURN_FAILURE(
4246 isolate, NewTypeError(MessageTemplate::kNotGeneric,
4247 isolate->factory()->NewStringFromAsciiChecked(
4248 "Function.prototype.toString")));
4249}
4250
4251
4252// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
4253BUILTIN(GeneratorFunctionConstructor) {
4254 HandleScope scope(isolate);
4255 Handle<JSFunction> result;
4256 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4257 isolate, result, CreateDynamicFunction(isolate, args, "function*"));
4258 return *result;
4259}
4260
Ben Murdochc5610432016-08-08 18:44:38 +01004261BUILTIN(AsyncFunctionConstructor) {
4262 HandleScope scope(isolate);
4263 Handle<JSFunction> result;
4264 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4265 isolate, result, CreateDynamicFunction(isolate, args, "async function"));
4266 return *result;
4267}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004268
4269// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
4270BUILTIN(SymbolConstructor) {
4271 HandleScope scope(isolate);
4272 Handle<Symbol> result = isolate->factory()->NewSymbol();
4273 Handle<Object> description = args.atOrUndefined(isolate, 1);
4274 if (!description->IsUndefined()) {
4275 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
4276 Object::ToString(isolate, description));
4277 result->set_name(*description);
4278 }
4279 return *result;
4280}
4281
4282
4283// ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
4284BUILTIN(SymbolConstructor_ConstructStub) {
4285 HandleScope scope(isolate);
4286 THROW_NEW_ERROR_RETURN_FAILURE(
4287 isolate, NewTypeError(MessageTemplate::kNotConstructor,
4288 isolate->factory()->Symbol_string()));
4289}
4290
4291
4292// ES6 19.1.3.6 Object.prototype.toString
4293BUILTIN(ObjectProtoToString) {
4294 HandleScope scope(isolate);
4295 Handle<Object> object = args.at<Object>(0);
4296 Handle<String> result;
4297 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdochda12d292016-06-02 14:46:10 +01004298 isolate, result, Object::ObjectProtoToString(isolate, object));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004299 return *result;
4300}
4301
Ben Murdochda12d292016-06-02 14:46:10 +01004302// -----------------------------------------------------------------------------
4303// ES6 section 21.1 String Objects
4304
4305namespace {
4306
4307bool ToUint16(Handle<Object> value, uint16_t* result) {
4308 if (value->IsNumber() || Object::ToNumber(value).ToHandle(&value)) {
4309 *result = DoubleToUint32(value->Number());
4310 return true;
4311 }
4312 return false;
4313}
4314
4315} // namespace
4316
4317// ES6 21.1.2.1 String.fromCharCode ( ...codeUnits )
4318BUILTIN(StringFromCharCode) {
4319 HandleScope scope(isolate);
4320 // Check resulting string length.
4321 int index = 0;
4322 Handle<String> result;
4323 int const length = args.length() - 1;
4324 if (length == 0) return isolate->heap()->empty_string();
4325 DCHECK_LT(0, length);
4326 // Load the first character code.
4327 uint16_t code;
4328 if (!ToUint16(args.at<Object>(1), &code)) return isolate->heap()->exception();
4329 // Assume that the resulting String contains only one byte characters.
4330 if (code <= String::kMaxOneByteCharCodeU) {
4331 // Check for single one-byte character fast case.
4332 if (length == 1) {
4333 return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
4334 }
4335 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4336 isolate, result, isolate->factory()->NewRawOneByteString(length));
4337 do {
4338 Handle<SeqOneByteString>::cast(result)->Set(index, code);
4339 if (++index == length) break;
4340 if (!ToUint16(args.at<Object>(1 + index), &code)) {
4341 return isolate->heap()->exception();
4342 }
4343 } while (code <= String::kMaxOneByteCharCodeU);
4344 }
4345 // Check if all characters fit into the one byte range.
4346 if (index < length) {
4347 // Fallback to two byte string.
4348 Handle<String> new_result;
4349 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4350 isolate, new_result, isolate->factory()->NewRawTwoByteString(length));
4351 for (int new_index = 0; new_index < index; ++new_index) {
4352 uint16_t new_code =
4353 Handle<SeqOneByteString>::cast(result)->Get(new_index);
4354 Handle<SeqTwoByteString>::cast(new_result)->Set(new_index, new_code);
4355 }
4356 while (true) {
4357 Handle<SeqTwoByteString>::cast(new_result)->Set(index, code);
4358 if (++index == length) break;
4359 if (!ToUint16(args.at<Object>(1 + index), &code)) {
4360 return isolate->heap()->exception();
4361 }
4362 }
4363 result = new_result;
4364 }
4365 return *result;
4366}
4367
Ben Murdochc5610432016-08-08 18:44:38 +01004368// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
4369void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
4370 typedef CodeStubAssembler::Label Label;
4371 typedef compiler::Node Node;
4372 typedef CodeStubAssembler::Variable Variable;
4373
4374 Node* receiver = assembler->Parameter(0);
4375 Node* position = assembler->Parameter(1);
4376 Node* context = assembler->Parameter(4);
4377
4378 // Check that {receiver} is coercible to Object and convert it to a String.
4379 receiver =
4380 assembler->ToThisString(context, receiver, "String.prototype.charAt");
4381
4382 // Convert the {position} to a Smi and check that it's in bounds of the
4383 // {receiver}.
4384 // TODO(bmeurer): Find an abstraction for this!
4385 {
4386 // Check if the {position} is already a Smi.
4387 Variable var_position(assembler, MachineRepresentation::kTagged);
4388 var_position.Bind(position);
4389 Label if_positionissmi(assembler),
4390 if_positionisnotsmi(assembler, Label::kDeferred);
4391 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
4392 &if_positionisnotsmi);
4393 assembler->Bind(&if_positionisnotsmi);
4394 {
4395 // Convert the {position} to an Integer via the ToIntegerStub.
4396 Callable callable = CodeFactory::ToInteger(assembler->isolate());
4397 Node* index = assembler->CallStub(callable, context, position);
4398
4399 // Check if the resulting {index} is now a Smi.
4400 Label if_indexissmi(assembler, Label::kDeferred),
4401 if_indexisnotsmi(assembler, Label::kDeferred);
4402 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
4403 &if_indexisnotsmi);
4404
4405 assembler->Bind(&if_indexissmi);
4406 {
4407 var_position.Bind(index);
4408 assembler->Goto(&if_positionissmi);
4409 }
4410
4411 assembler->Bind(&if_indexisnotsmi);
4412 {
4413 // The ToIntegerStub canonicalizes everything in Smi range to Smi
4414 // representation, so any HeapNumber returned is not in Smi range.
4415 // The only exception here is -0.0, which we treat as 0.
4416 Node* index_value = assembler->LoadHeapNumberValue(index);
4417 Label if_indexiszero(assembler, Label::kDeferred),
4418 if_indexisnotzero(assembler, Label::kDeferred);
4419 assembler->Branch(assembler->Float64Equal(
4420 index_value, assembler->Float64Constant(0.0)),
4421 &if_indexiszero, &if_indexisnotzero);
4422
4423 assembler->Bind(&if_indexiszero);
4424 {
4425 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
4426 assembler->Goto(&if_positionissmi);
4427 }
4428
4429 assembler->Bind(&if_indexisnotzero);
4430 {
4431 // The {index} is some other integral Number, that is definitely
4432 // neither -0.0 nor in Smi range.
4433 assembler->Return(assembler->EmptyStringConstant());
4434 }
4435 }
4436 }
4437 assembler->Bind(&if_positionissmi);
4438 position = var_position.value();
4439
4440 // Determine the actual length of the {receiver} String.
4441 Node* receiver_length =
4442 assembler->LoadObjectField(receiver, String::kLengthOffset);
4443
4444 // Return "" if the Smi {position} is outside the bounds of the {receiver}.
4445 Label if_positioninbounds(assembler),
4446 if_positionnotinbounds(assembler, Label::kDeferred);
4447 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
4448 &if_positionnotinbounds, &if_positioninbounds);
4449 assembler->Bind(&if_positionnotinbounds);
4450 assembler->Return(assembler->EmptyStringConstant());
4451 assembler->Bind(&if_positioninbounds);
4452 }
4453
4454 // Load the character code at the {position} from the {receiver}.
4455 Node* code = assembler->StringCharCodeAt(receiver, position);
4456
4457 // And return the single character string with only that {code}.
4458 Node* result = assembler->StringFromCharCode(code);
4459 assembler->Return(result);
4460}
4461
4462// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
4463void Builtins::Generate_StringPrototypeCharCodeAt(
4464 CodeStubAssembler* assembler) {
4465 typedef CodeStubAssembler::Label Label;
4466 typedef compiler::Node Node;
4467 typedef CodeStubAssembler::Variable Variable;
4468
4469 Node* receiver = assembler->Parameter(0);
4470 Node* position = assembler->Parameter(1);
4471 Node* context = assembler->Parameter(4);
4472
4473 // Check that {receiver} is coercible to Object and convert it to a String.
4474 receiver =
4475 assembler->ToThisString(context, receiver, "String.prototype.charCodeAt");
4476
4477 // Convert the {position} to a Smi and check that it's in bounds of the
4478 // {receiver}.
4479 // TODO(bmeurer): Find an abstraction for this!
4480 {
4481 // Check if the {position} is already a Smi.
4482 Variable var_position(assembler, MachineRepresentation::kTagged);
4483 var_position.Bind(position);
4484 Label if_positionissmi(assembler),
4485 if_positionisnotsmi(assembler, Label::kDeferred);
4486 assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
4487 &if_positionisnotsmi);
4488 assembler->Bind(&if_positionisnotsmi);
4489 {
4490 // Convert the {position} to an Integer via the ToIntegerStub.
4491 Callable callable = CodeFactory::ToInteger(assembler->isolate());
4492 Node* index = assembler->CallStub(callable, context, position);
4493
4494 // Check if the resulting {index} is now a Smi.
4495 Label if_indexissmi(assembler, Label::kDeferred),
4496 if_indexisnotsmi(assembler, Label::kDeferred);
4497 assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
4498 &if_indexisnotsmi);
4499
4500 assembler->Bind(&if_indexissmi);
4501 {
4502 var_position.Bind(index);
4503 assembler->Goto(&if_positionissmi);
4504 }
4505
4506 assembler->Bind(&if_indexisnotsmi);
4507 {
4508 // The ToIntegerStub canonicalizes everything in Smi range to Smi
4509 // representation, so any HeapNumber returned is not in Smi range.
4510 // The only exception here is -0.0, which we treat as 0.
4511 Node* index_value = assembler->LoadHeapNumberValue(index);
4512 Label if_indexiszero(assembler, Label::kDeferred),
4513 if_indexisnotzero(assembler, Label::kDeferred);
4514 assembler->Branch(assembler->Float64Equal(
4515 index_value, assembler->Float64Constant(0.0)),
4516 &if_indexiszero, &if_indexisnotzero);
4517
4518 assembler->Bind(&if_indexiszero);
4519 {
4520 var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
4521 assembler->Goto(&if_positionissmi);
4522 }
4523
4524 assembler->Bind(&if_indexisnotzero);
4525 {
4526 // The {index} is some other integral Number, that is definitely
4527 // neither -0.0 nor in Smi range.
4528 assembler->Return(assembler->NaNConstant());
4529 }
4530 }
4531 }
4532 assembler->Bind(&if_positionissmi);
4533 position = var_position.value();
4534
4535 // Determine the actual length of the {receiver} String.
4536 Node* receiver_length =
4537 assembler->LoadObjectField(receiver, String::kLengthOffset);
4538
4539 // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
4540 Label if_positioninbounds(assembler),
4541 if_positionnotinbounds(assembler, Label::kDeferred);
4542 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
4543 &if_positionnotinbounds, &if_positioninbounds);
4544 assembler->Bind(&if_positionnotinbounds);
4545 assembler->Return(assembler->NaNConstant());
4546 assembler->Bind(&if_positioninbounds);
4547 }
4548
4549 // Load the character at the {position} from the {receiver}.
4550 Node* value = assembler->StringCharCodeAt(receiver, position);
4551 Node* result = assembler->SmiFromWord32(value);
4552 assembler->Return(result);
4553}
4554
Ben Murdochda12d292016-06-02 14:46:10 +01004555// -----------------------------------------------------------------------------
4556// ES6 section 21.1 ArrayBuffer Objects
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004557
4558// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
4559BUILTIN(ArrayBufferConstructor) {
4560 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004561 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004562 DCHECK(*target == target->native_context()->array_buffer_fun() ||
4563 *target == target->native_context()->shared_array_buffer_fun());
4564 THROW_NEW_ERROR_RETURN_FAILURE(
4565 isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
4566 handle(target->shared()->name(), isolate)));
4567}
4568
4569
4570// ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
4571BUILTIN(ArrayBufferConstructor_ConstructStub) {
4572 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004573 Handle<JSFunction> target = args.target<JSFunction>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004574 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
4575 Handle<Object> length = args.atOrUndefined(isolate, 1);
4576 DCHECK(*target == target->native_context()->array_buffer_fun() ||
4577 *target == target->native_context()->shared_array_buffer_fun());
4578 Handle<Object> number_length;
4579 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
4580 Object::ToInteger(isolate, length));
4581 if (number_length->Number() < 0.0) {
4582 THROW_NEW_ERROR_RETURN_FAILURE(
4583 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
4584 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01004585 Handle<JSObject> result;
4586 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
4587 JSObject::New(target, new_target));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004588 size_t byte_length;
4589 if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
4590 THROW_NEW_ERROR_RETURN_FAILURE(
4591 isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
4592 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004593 SharedFlag shared_flag =
4594 (*target == target->native_context()->array_buffer_fun())
4595 ? SharedFlag::kNotShared
4596 : SharedFlag::kShared;
Ben Murdoch097c5b22016-05-18 11:27:45 +01004597 if (!JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer>::cast(result),
4598 isolate, byte_length, true,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004599 shared_flag)) {
4600 THROW_NEW_ERROR_RETURN_FAILURE(
4601 isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
4602 }
4603 return *result;
4604}
4605
4606
4607// ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
4608BUILTIN(ArrayBufferIsView) {
4609 SealHandleScope shs(isolate);
4610 DCHECK_EQ(2, args.length());
4611 Object* arg = args[1];
4612 return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
4613}
4614
4615
4616// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
4617BUILTIN(ProxyConstructor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004618 HandleScope scope(isolate);
4619 THROW_NEW_ERROR_RETURN_FAILURE(
4620 isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004621 NewTypeError(MessageTemplate::kConstructorNotFunction,
4622 isolate->factory()->NewStringFromAsciiChecked("Proxy")));
4623}
4624
4625
4626// ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
4627BUILTIN(ProxyConstructor_ConstructStub) {
4628 HandleScope scope(isolate);
4629 DCHECK(isolate->proxy_function()->IsConstructor());
4630 Handle<Object> target = args.atOrUndefined(isolate, 1);
4631 Handle<Object> handler = args.atOrUndefined(isolate, 2);
4632 Handle<JSProxy> result;
4633 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
4634 JSProxy::New(isolate, target, handler));
4635 return *result;
4636}
4637
4638
4639// -----------------------------------------------------------------------------
4640// Throwers for restricted function properties and strict arguments object
4641// properties
4642
4643
4644BUILTIN(RestrictedFunctionPropertiesThrower) {
4645 HandleScope scope(isolate);
4646 THROW_NEW_ERROR_RETURN_FAILURE(
4647 isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
4648}
4649
4650
4651BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
4652 HandleScope scope(isolate);
4653 THROW_NEW_ERROR_RETURN_FAILURE(
4654 isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004655}
4656
4657
Steve Block44f0eee2011-05-26 01:26:41 +01004658// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00004659//
4660
4661
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004662namespace {
Steve Blocka7e24c12009-10-30 11:49:00 +00004663
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004664MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
Ben Murdochc5610432016-08-08 18:44:38 +01004665 Isolate* isolate,
4666 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args) {
Steve Block44f0eee2011-05-26 01:26:41 +01004667 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004668 Handle<HeapObject> function = args.target<HeapObject>();
Ben Murdochc5610432016-08-08 18:44:38 +01004669 Handle<HeapObject> new_target = args.new_target();
4670 bool is_construct = !new_target->IsUndefined();
Ben Murdoch097c5b22016-05-18 11:27:45 +01004671 Handle<JSReceiver> receiver;
Ben Murdochda12d292016-06-02 14:46:10 +01004672
4673 DCHECK(function->IsFunctionTemplateInfo() ||
4674 Handle<JSFunction>::cast(function)->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00004675
Ben Murdoch097c5b22016-05-18 11:27:45 +01004676 Handle<FunctionTemplateInfo> fun_data =
4677 function->IsFunctionTemplateInfo()
4678 ? Handle<FunctionTemplateInfo>::cast(function)
4679 : handle(JSFunction::cast(*function)->shared()->get_api_func_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00004680 if (is_construct) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004681 DCHECK(args.receiver()->IsTheHole());
4682 if (fun_data->instance_template()->IsUndefined()) {
4683 v8::Local<ObjectTemplate> templ =
4684 ObjectTemplate::New(reinterpret_cast<v8::Isolate*>(isolate),
4685 ToApiHandle<v8::FunctionTemplate>(fun_data));
4686 fun_data->set_instance_template(*Utils::OpenHandle(*templ));
4687 }
4688 Handle<ObjectTemplateInfo> instance_template(
4689 ObjectTemplateInfo::cast(fun_data->instance_template()), isolate);
Ben Murdochc5610432016-08-08 18:44:38 +01004690 ASSIGN_RETURN_ON_EXCEPTION(
4691 isolate, receiver,
4692 ApiNatives::InstantiateObject(instance_template,
4693 Handle<JSReceiver>::cast(new_target)),
4694 Object);
Ben Murdoch097c5b22016-05-18 11:27:45 +01004695 args[0] = *receiver;
4696 DCHECK_EQ(*receiver, *args.receiver());
4697 } else {
4698 DCHECK(args.receiver()->IsJSReceiver());
4699 receiver = args.at<JSReceiver>(0);
Steve Blocka7e24c12009-10-30 11:49:00 +00004700 }
4701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004702 if (!is_construct && !fun_data->accept_any_receiver()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004703 if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
4704 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
4705 if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
4706 isolate->ReportFailedAccessCheck(js_receiver);
4707 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
4708 }
4709 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004710 }
4711
Ben Murdoch097c5b22016-05-18 11:27:45 +01004712 Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, *receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00004713
4714 if (raw_holder->IsNull()) {
4715 // This function cannot be called with the given receiver. Abort!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004716 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
4717 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +00004718 }
4719
4720 Object* raw_call_data = fun_data->call_code();
4721 if (!raw_call_data->IsUndefined()) {
Ben Murdochda12d292016-06-02 14:46:10 +01004722 DCHECK(raw_call_data->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00004723 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
4724 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004725 v8::FunctionCallback callback =
4726 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00004727 Object* data_obj = call_data->data();
Steve Blocka7e24c12009-10-30 11:49:00 +00004728
Steve Block44f0eee2011-05-26 01:26:41 +01004729 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004730 DCHECK(raw_holder->IsJSObject());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004731
Ben Murdochc5610432016-08-08 18:44:38 +01004732 FunctionCallbackArguments custom(isolate, data_obj, *function, raw_holder,
4733 *new_target, &args[0] - 1,
4734 args.length() - 1);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004735
Ben Murdochda12d292016-06-02 14:46:10 +01004736 Handle<Object> result = custom.Call(callback);
4737 if (result.is_null()) result = isolate->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00004738
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004739 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
4740 if (!is_construct || result->IsJSObject()) {
4741 return scope.CloseAndEscape(result);
4742 }
Steve Blocka7e24c12009-10-30 11:49:00 +00004743 }
4744
Ben Murdoch097c5b22016-05-18 11:27:45 +01004745 return scope.CloseAndEscape(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00004746}
Leon Clarkee46be812010-01-19 14:06:41 +00004747
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004748} // namespace
4749
Leon Clarkee46be812010-01-19 14:06:41 +00004750
4751BUILTIN(HandleApiCall) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004752 HandleScope scope(isolate);
4753 Handle<Object> result;
4754 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Ben Murdochc5610432016-08-08 18:44:38 +01004755 HandleApiCallHelper(isolate, args));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004756 return *result;
Leon Clarkee46be812010-01-19 14:06:41 +00004757}
4758
4759
Ben Murdoch097c5b22016-05-18 11:27:45 +01004760Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode,
4761 TailCallMode tail_call_mode) {
4762 switch (tail_call_mode) {
4763 case TailCallMode::kDisallow:
4764 switch (mode) {
4765 case ConvertReceiverMode::kNullOrUndefined:
4766 return CallFunction_ReceiverIsNullOrUndefined();
4767 case ConvertReceiverMode::kNotNullOrUndefined:
4768 return CallFunction_ReceiverIsNotNullOrUndefined();
4769 case ConvertReceiverMode::kAny:
4770 return CallFunction_ReceiverIsAny();
4771 }
4772 break;
4773 case TailCallMode::kAllow:
4774 switch (mode) {
4775 case ConvertReceiverMode::kNullOrUndefined:
4776 return TailCallFunction_ReceiverIsNullOrUndefined();
4777 case ConvertReceiverMode::kNotNullOrUndefined:
4778 return TailCallFunction_ReceiverIsNotNullOrUndefined();
4779 case ConvertReceiverMode::kAny:
4780 return TailCallFunction_ReceiverIsAny();
4781 }
4782 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004783 }
4784 UNREACHABLE();
4785 return Handle<Code>::null();
4786}
4787
Ben Murdoch097c5b22016-05-18 11:27:45 +01004788Handle<Code> Builtins::Call(ConvertReceiverMode mode,
4789 TailCallMode tail_call_mode) {
4790 switch (tail_call_mode) {
4791 case TailCallMode::kDisallow:
4792 switch (mode) {
4793 case ConvertReceiverMode::kNullOrUndefined:
4794 return Call_ReceiverIsNullOrUndefined();
4795 case ConvertReceiverMode::kNotNullOrUndefined:
4796 return Call_ReceiverIsNotNullOrUndefined();
4797 case ConvertReceiverMode::kAny:
4798 return Call_ReceiverIsAny();
4799 }
4800 break;
4801 case TailCallMode::kAllow:
4802 switch (mode) {
4803 case ConvertReceiverMode::kNullOrUndefined:
4804 return TailCall_ReceiverIsNullOrUndefined();
4805 case ConvertReceiverMode::kNotNullOrUndefined:
4806 return TailCall_ReceiverIsNotNullOrUndefined();
4807 case ConvertReceiverMode::kAny:
4808 return TailCall_ReceiverIsAny();
4809 }
4810 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004811 }
4812 UNREACHABLE();
4813 return Handle<Code>::null();
4814}
4815
Ben Murdoch097c5b22016-05-18 11:27:45 +01004816Handle<Code> Builtins::CallBoundFunction(TailCallMode tail_call_mode) {
4817 switch (tail_call_mode) {
4818 case TailCallMode::kDisallow:
4819 return CallBoundFunction();
4820 case TailCallMode::kAllow:
4821 return TailCallBoundFunction();
4822 }
4823 UNREACHABLE();
4824 return Handle<Code>::null();
4825}
4826
4827Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode) {
4828 switch (tail_call_mode) {
4829 case TailCallMode::kDisallow:
4830 return InterpreterPushArgsAndCall();
4831 case TailCallMode::kAllow:
4832 return InterpreterPushArgsAndTailCall();
4833 }
4834 UNREACHABLE();
4835 return Handle<Code>::null();
4836}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004837
4838namespace {
4839
4840class RelocatableArguments
Ben Murdochc5610432016-08-08 18:44:38 +01004841 : public BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004842 public Relocatable {
4843 public:
4844 RelocatableArguments(Isolate* isolate, int length, Object** arguments)
Ben Murdochc5610432016-08-08 18:44:38 +01004845 : BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>(length,
4846 arguments),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004847 Relocatable(isolate) {}
4848
4849 virtual inline void IterateInstance(ObjectVisitor* v) {
4850 if (length() == 0) return;
4851 v->VisitPointers(lowest_address(), highest_address() + 1);
4852 }
4853
4854 private:
4855 DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
4856};
4857
4858} // namespace
4859
Ben Murdoch097c5b22016-05-18 11:27:45 +01004860MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004861 Handle<Object> receiver,
4862 int argc,
4863 Handle<Object> args[]) {
Ben Murdochda12d292016-06-02 14:46:10 +01004864 Isolate* isolate = function->GetIsolate();
4865 // Do proper receiver conversion for non-strict mode api functions.
4866 if (!receiver->IsJSReceiver()) {
4867 DCHECK(function->IsFunctionTemplateInfo() || function->IsJSFunction());
4868 if (function->IsFunctionTemplateInfo() ||
4869 is_sloppy(JSFunction::cast(*function)->shared()->language_mode())) {
Ben Murdochc5610432016-08-08 18:44:38 +01004870 ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
4871 Object::ConvertReceiver(isolate, receiver),
4872 Object);
Ben Murdochda12d292016-06-02 14:46:10 +01004873 }
4874 }
Ben Murdochc5610432016-08-08 18:44:38 +01004875 // Construct BuiltinArguments object:
4876 // new target, function, arguments reversed, receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004877 const int kBufferSize = 32;
4878 Object* small_argv[kBufferSize];
4879 Object** argv;
Ben Murdochc5610432016-08-08 18:44:38 +01004880 if (argc + 3 <= kBufferSize) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004881 argv = small_argv;
4882 } else {
Ben Murdochc5610432016-08-08 18:44:38 +01004883 argv = new Object*[argc + 3];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004884 }
Ben Murdochc5610432016-08-08 18:44:38 +01004885 argv[argc + 2] = *receiver;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004886 for (int i = 0; i < argc; ++i) {
Ben Murdochc5610432016-08-08 18:44:38 +01004887 argv[argc - i + 1] = *args[i];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004888 }
Ben Murdochc5610432016-08-08 18:44:38 +01004889 argv[1] = *function;
4890 argv[0] = isolate->heap()->undefined_value(); // new target
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004891 MaybeHandle<Object> result;
4892 {
Ben Murdochc5610432016-08-08 18:44:38 +01004893 RelocatableArguments arguments(isolate, argc + 3, &argv[argc] + 2);
4894 result = HandleApiCallHelper(isolate, arguments);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004895 }
4896 if (argv != small_argv) {
4897 delete[] argv;
4898 }
4899 return result;
Leon Clarkee46be812010-01-19 14:06:41 +00004900}
Steve Blocka7e24c12009-10-30 11:49:00 +00004901
4902
4903// Helper function to handle calls to non-function objects created through the
4904// API. The object can be called as either a constructor (using new) or just as
4905// a function (without new).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004906MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004907 Isolate* isolate, bool is_construct_call,
4908 BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004909 Handle<Object> receiver = args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00004910
4911 // Get the object called.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004912 JSObject* obj = JSObject::cast(*receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00004913
Ben Murdochc5610432016-08-08 18:44:38 +01004914 // Set the new target.
4915 HeapObject* new_target;
4916 if (is_construct_call) {
4917 // TODO(adamk): This should be passed through in args instead of
4918 // being patched in here. We need to set a non-undefined value
4919 // for v8::FunctionCallbackInfo::IsConstructCall() to get the
4920 // right answer.
4921 new_target = obj;
4922 } else {
4923 new_target = isolate->heap()->undefined_value();
4924 }
4925
Steve Blocka7e24c12009-10-30 11:49:00 +00004926 // Get the invocation callback from the function descriptor that was
4927 // used to create the called object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004928 DCHECK(obj->map()->is_callable());
4929 JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
4930 // TODO(ishell): turn this back to a DCHECK.
4931 CHECK(constructor->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00004932 Object* handler =
Steve Block6ded16b2010-05-10 14:33:55 +01004933 constructor->shared()->get_api_func_data()->instance_call_handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004934 DCHECK(!handler->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004935 // TODO(ishell): remove this debugging code.
4936 CHECK(handler->IsCallHandlerInfo());
Steve Blocka7e24c12009-10-30 11:49:00 +00004937 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
4938 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004939 v8::FunctionCallback callback =
4940 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00004941
4942 // Get the data for the call and perform the callback.
Steve Blocka7e24c12009-10-30 11:49:00 +00004943 Object* result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004944 {
Steve Block44f0eee2011-05-26 01:26:41 +01004945 HandleScope scope(isolate);
4946 LOG(isolate, ApiObjectAccess("call non-function", obj));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08004947
Ben Murdochc5610432016-08-08 18:44:38 +01004948 FunctionCallbackArguments custom(isolate, call_data->data(), constructor,
4949 obj, new_target, &args[0] - 1,
4950 args.length() - 1);
Ben Murdochda12d292016-06-02 14:46:10 +01004951 Handle<Object> result_handle = custom.Call(callback);
4952 if (result_handle.is_null()) {
4953 result = isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00004954 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01004955 result = *result_handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00004956 }
4957 }
4958 // Check for exceptions and return result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004959 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00004960 return result;
4961}
4962
4963
4964// Handle calls to non-function objects created through the API. This delegate
4965// function is used when the call is a normal function call.
4966BUILTIN(HandleApiCallAsFunction) {
Steve Block44f0eee2011-05-26 01:26:41 +01004967 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004968}
Steve Blocka7e24c12009-10-30 11:49:00 +00004969
4970
4971// Handle calls to non-function objects created through the API. This delegate
4972// function is used when the call is a construct call.
4973BUILTIN(HandleApiCallAsConstructor) {
Steve Block44f0eee2011-05-26 01:26:41 +01004974 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00004975}
Steve Blocka7e24c12009-10-30 11:49:00 +00004976
4977
Steve Blocka7e24c12009-10-30 11:49:00 +00004978static void Generate_LoadIC_Miss(MacroAssembler* masm) {
4979 LoadIC::GenerateMiss(masm);
4980}
4981
4982
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004983static void Generate_LoadIC_Normal(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004984 LoadIC::GenerateNormal(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004985}
4986
4987
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004988static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
4989 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
4990}
4991
4992
4993static void Generate_LoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004994 LoadIC::GenerateRuntimeGetProperty(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00004995}
4996
4997
Ben Murdoch257744e2011-11-30 15:57:28 +00004998static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01004999 KeyedLoadIC::GenerateRuntimeGetProperty(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00005000}
5001
5002
Steve Blocka7e24c12009-10-30 11:49:00 +00005003static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005004 KeyedLoadIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00005005}
5006
5007
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005008static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01005009 KeyedLoadIC::GenerateMegamorphic(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00005010}
5011
Steve Block1e0659c2011-05-24 12:43:12 +01005012
Steve Blocka7e24c12009-10-30 11:49:00 +00005013static void Generate_StoreIC_Miss(MacroAssembler* masm) {
5014 StoreIC::GenerateMiss(masm);
5015}
5016
5017
Steve Block8defd9f2010-07-08 12:39:36 +01005018static void Generate_StoreIC_Normal(MacroAssembler* masm) {
5019 StoreIC::GenerateNormal(masm);
5020}
5021
5022
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005023static void Generate_StoreIC_Slow(MacroAssembler* masm) {
5024 NamedStoreHandlerCompiler::GenerateSlow(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00005025}
5026
5027
5028static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005029 ElementHandlerCompiler::GenerateStoreSlow(masm);
5030}
5031
5032
5033static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
5034 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
5035}
5036
Ben Murdochc5610432016-08-08 18:44:38 +01005037static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
5038 StoreIC::GenerateMegamorphic(masm);
5039}
5040
5041static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
5042 StoreIC::GenerateMegamorphic(masm);
5043}
5044
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005045
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005046static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
5047 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
5048}
5049
5050
5051static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
5052 KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
5053}
5054
5055
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005056static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
5057 KeyedStoreIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00005058}
5059
5060
Steve Blocka7e24c12009-10-30 11:49:00 +00005061static void Generate_Return_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005062 DebugCodegen::GenerateDebugBreakStub(masm,
5063 DebugCodegen::SAVE_RESULT_REGISTER);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01005064}
5065
5066
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005067static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005068 DebugCodegen::GenerateDebugBreakStub(masm,
5069 DebugCodegen::IGNORE_RESULT_REGISTER);
Steve Block6ded16b2010-05-10 14:33:55 +01005070}
5071
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01005072
Steve Block6ded16b2010-05-10 14:33:55 +01005073static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005074 DebugCodegen::GenerateFrameDropperLiveEdit(masm);
Steve Block6ded16b2010-05-10 14:33:55 +01005075}
Steve Blocka7e24c12009-10-30 11:49:00 +00005076
Steve Block44f0eee2011-05-26 01:26:41 +01005077
5078Builtins::Builtins() : initialized_(false) {
5079 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
5080 memset(names_, 0, sizeof(names_[0]) * builtin_count);
5081}
5082
5083
5084Builtins::~Builtins() {
5085}
5086
Steve Blocka7e24c12009-10-30 11:49:00 +00005087
Leon Clarkee46be812010-01-19 14:06:41 +00005088#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
Steve Block44f0eee2011-05-26 01:26:41 +01005089Address const Builtins::c_functions_[cfunction_count] = {
5090 BUILTIN_LIST_C(DEF_ENUM_C)
5091};
Steve Blocka7e24c12009-10-30 11:49:00 +00005092#undef DEF_ENUM_C
5093
Steve Blocka7e24c12009-10-30 11:49:00 +00005094
Steve Block44f0eee2011-05-26 01:26:41 +01005095struct BuiltinDesc {
Ben Murdochda12d292016-06-02 14:46:10 +01005096 Handle<Code> (*builder)(Isolate*, struct BuiltinDesc const*);
Steve Block44f0eee2011-05-26 01:26:41 +01005097 byte* generator;
5098 byte* c_code;
5099 const char* s_name; // name is only used for generating log information.
5100 int name;
5101 Code::Flags flags;
5102 BuiltinExtraArguments extra_args;
Ben Murdochda12d292016-06-02 14:46:10 +01005103 int argc;
Steve Block44f0eee2011-05-26 01:26:41 +01005104};
5105
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005106#define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
5107
Steve Block44f0eee2011-05-26 01:26:41 +01005108class BuiltinFunctionTable {
5109 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005110 BuiltinDesc* functions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005111 base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005112 return functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01005113 }
5114
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005115 base::OnceType once_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005116 BuiltinDesc functions_[Builtins::builtin_count + 1];
Steve Block44f0eee2011-05-26 01:26:41 +01005117
5118 friend class Builtins;
5119};
5120
Ben Murdochda12d292016-06-02 14:46:10 +01005121namespace {
5122
5123BuiltinFunctionTable builtin_function_table = BUILTIN_FUNCTION_TABLE_INIT;
5124
5125Handle<Code> MacroAssemblerBuilder(Isolate* isolate,
5126 BuiltinDesc const* builtin_desc) {
5127// For now we generate builtin adaptor code into a stack-allocated
5128// buffer, before copying it into individual code objects. Be careful
5129// with alignment, some platforms don't like unaligned code.
5130#ifdef DEBUG
5131 // We can generate a lot of debug code on Arm64.
5132 const size_t buffer_size = 32 * KB;
5133#elif V8_TARGET_ARCH_PPC64
5134 // 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
5135 const size_t buffer_size = 10 * KB;
5136#else
5137 const size_t buffer_size = 8 * KB;
5138#endif
5139 union {
5140 int force_alignment;
5141 byte buffer[buffer_size]; // NOLINT(runtime/arrays)
5142 } u;
5143
5144 MacroAssembler masm(isolate, u.buffer, sizeof(u.buffer),
5145 CodeObjectRequired::kYes);
5146 // Generate the code/adaptor.
5147 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
5148 Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5149 // We pass all arguments to the generator, but it may not use all of
5150 // them. This works because the first arguments are on top of the
5151 // stack.
5152 DCHECK(!masm.has_frame());
5153 g(&masm, builtin_desc->name, builtin_desc->extra_args);
5154 // Move the code into the object heap.
5155 CodeDesc desc;
5156 masm.GetCode(&desc);
5157 Code::Flags flags = builtin_desc->flags;
5158 return isolate->factory()->NewCode(desc, flags, masm.CodeObject());
5159}
5160
5161Handle<Code> CodeStubAssemblerBuilder(Isolate* isolate,
5162 BuiltinDesc const* builtin_desc) {
5163 Zone zone(isolate->allocator());
Ben Murdochc5610432016-08-08 18:44:38 +01005164 CodeStubAssembler assembler(isolate, &zone, builtin_desc->argc,
5165 builtin_desc->flags, builtin_desc->s_name);
Ben Murdochda12d292016-06-02 14:46:10 +01005166 // Generate the code/adaptor.
Ben Murdochc5610432016-08-08 18:44:38 +01005167 typedef void (*Generator)(CodeStubAssembler*);
Ben Murdochda12d292016-06-02 14:46:10 +01005168 Generator g = FUNCTION_CAST<Generator>(builtin_desc->generator);
5169 g(&assembler);
5170 return assembler.GenerateCode();
5171}
5172
5173} // namespace
Steve Block44f0eee2011-05-26 01:26:41 +01005174
5175// Define array of pointers to generators and C builtin functions.
5176// We do this in a sort of roundabout way so that we can do the initialization
5177// within the lexical scope of Builtins:: and within a context where
5178// Code::Flags names a non-abstract type.
5179void Builtins::InitBuiltinFunctionTable() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005180 BuiltinDesc* functions = builtin_function_table.functions_;
Ben Murdochda12d292016-06-02 14:46:10 +01005181 functions[builtin_count].builder = nullptr;
5182 functions[builtin_count].generator = nullptr;
5183 functions[builtin_count].c_code = nullptr;
5184 functions[builtin_count].s_name = nullptr;
Steve Block44f0eee2011-05-26 01:26:41 +01005185 functions[builtin_count].name = builtin_count;
5186 functions[builtin_count].flags = static_cast<Code::Flags>(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005187 functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
Ben Murdochda12d292016-06-02 14:46:10 +01005188 functions[builtin_count].argc = 0;
Steve Block44f0eee2011-05-26 01:26:41 +01005189
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005190#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
Ben Murdochda12d292016-06-02 14:46:10 +01005191 functions->builder = &MacroAssemblerBuilder; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005192 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
5193 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
5194 functions->s_name = #aname; \
5195 functions->name = c_##aname; \
5196 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
5197 functions->extra_args = BuiltinExtraArguments::aextra_args; \
Ben Murdochda12d292016-06-02 14:46:10 +01005198 functions->argc = 0; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005199 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01005200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005201#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
Ben Murdochda12d292016-06-02 14:46:10 +01005202 functions->builder = &MacroAssemblerBuilder; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005203 functions->generator = FUNCTION_ADDR(Generate_##aname); \
5204 functions->c_code = NULL; \
5205 functions->s_name = #aname; \
5206 functions->name = k##aname; \
5207 functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
5208 functions->extra_args = BuiltinExtraArguments::kNone; \
Ben Murdochda12d292016-06-02 14:46:10 +01005209 functions->argc = 0; \
5210 ++functions;
5211
5212#define DEF_FUNCTION_PTR_T(aname, aargc) \
5213 functions->builder = &CodeStubAssemblerBuilder; \
5214 functions->generator = FUNCTION_ADDR(Generate_##aname); \
5215 functions->c_code = NULL; \
5216 functions->s_name = #aname; \
5217 functions->name = k##aname; \
5218 functions->flags = \
5219 Code::ComputeFlags(Code::BUILTIN, UNINITIALIZED, kNoExtraICState); \
5220 functions->extra_args = BuiltinExtraArguments::kNone; \
5221 functions->argc = aargc; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005222 ++functions;
Steve Block44f0eee2011-05-26 01:26:41 +01005223
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005224#define DEF_FUNCTION_PTR_H(aname, kind) \
Ben Murdochda12d292016-06-02 14:46:10 +01005225 functions->builder = &MacroAssemblerBuilder; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005226 functions->generator = FUNCTION_ADDR(Generate_##aname); \
5227 functions->c_code = NULL; \
5228 functions->s_name = #aname; \
5229 functions->name = k##aname; \
5230 functions->flags = Code::ComputeHandlerFlags(Code::kind); \
5231 functions->extra_args = BuiltinExtraArguments::kNone; \
Ben Murdochda12d292016-06-02 14:46:10 +01005232 functions->argc = 0; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005233 ++functions;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005234
Steve Block44f0eee2011-05-26 01:26:41 +01005235 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
5236 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
Ben Murdochda12d292016-06-02 14:46:10 +01005237 BUILTIN_LIST_T(DEF_FUNCTION_PTR_T)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005238 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01005239 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
5240
5241#undef DEF_FUNCTION_PTR_C
5242#undef DEF_FUNCTION_PTR_A
Ben Murdochda12d292016-06-02 14:46:10 +01005243#undef DEF_FUNCTION_PTR_H
5244#undef DEF_FUNCTION_PTR_T
Steve Block44f0eee2011-05-26 01:26:41 +01005245}
5246
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005247
5248void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
5249 DCHECK(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +00005250
5251 // Create a scope for the handles in the builtins.
Ben Murdoch8b112d22011-06-08 16:22:53 +01005252 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005253
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005254 const BuiltinDesc* functions = builtin_function_table.functions();
Steve Blocka7e24c12009-10-30 11:49:00 +00005255
Steve Blocka7e24c12009-10-30 11:49:00 +00005256 // Traverse the list of builtins and generate an adaptor in a
5257 // separate code object for each one.
5258 for (int i = 0; i < builtin_count; i++) {
5259 if (create_heap_objects) {
Ben Murdochda12d292016-06-02 14:46:10 +01005260 Handle<Code> code = (*functions[i].builder)(isolate, functions + i);
Steve Blocka7e24c12009-10-30 11:49:00 +00005261 // Log the event and add the code to the builtins array.
Ben Murdoch8b112d22011-06-08 16:22:53 +01005262 PROFILE(isolate,
Ben Murdochda12d292016-06-02 14:46:10 +01005263 CodeCreateEvent(Logger::BUILTIN_TAG, AbstractCode::cast(*code),
5264 functions[i].s_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005265 builtins_[i] = *code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005266 code->set_builtin_index(i);
Steve Blocka7e24c12009-10-30 11:49:00 +00005267#ifdef ENABLE_DISASSEMBLER
5268 if (FLAG_print_builtin_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005269 CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
5270 OFStream os(trace_scope.file());
5271 os << "Builtin: " << functions[i].s_name << "\n";
5272 code->Disassemble(functions[i].s_name, os);
5273 os << "\n";
Steve Blocka7e24c12009-10-30 11:49:00 +00005274 }
5275#endif
5276 } else {
5277 // Deserializing. The values will be filled in during IterateBuiltins.
5278 builtins_[i] = NULL;
5279 }
5280 names_[i] = functions[i].s_name;
5281 }
5282
5283 // Mark as initialized.
Steve Block44f0eee2011-05-26 01:26:41 +01005284 initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00005285}
5286
5287
5288void Builtins::TearDown() {
Steve Block44f0eee2011-05-26 01:26:41 +01005289 initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00005290}
5291
5292
5293void Builtins::IterateBuiltins(ObjectVisitor* v) {
5294 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
5295}
5296
5297
5298const char* Builtins::Lookup(byte* pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01005299 // may be called during initialization (disassembler!)
5300 if (initialized_) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005301 for (int i = 0; i < builtin_count; i++) {
5302 Code* entry = Code::cast(builtins_[i]);
5303 if (entry->contains(pc)) {
5304 return names_[i];
5305 }
5306 }
5307 }
5308 return NULL;
5309}
5310
Ben Murdochb0fe1622011-05-05 13:52:32 +01005311
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005312void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005313 masm->TailCallRuntime(Runtime::kInterrupt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005314}
5315
5316
5317void Builtins::Generate_StackCheck(MacroAssembler* masm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005318 masm->TailCallRuntime(Runtime::kStackGuard);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005319}
5320
Ben Murdochc5610432016-08-08 18:44:38 +01005321namespace {
5322
5323void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
5324 compiler::Node* context,
5325 compiler::Node** out_instance_type,
5326 compiler::Node** out_backing_store) {
5327 using namespace compiler;
5328 CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a),
5329 not_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a),
5330 not_float_or_clamped(a), invalid(a);
5331
5332 // Fail if it is not a heap object.
5333 a->Branch(a->WordIsSmi(tagged), &is_smi, &not_smi);
5334 a->Bind(&is_smi);
5335 a->Goto(&invalid);
5336
5337 // Fail if the array's instance type is not JSTypedArray.
5338 a->Bind(&not_smi);
5339 a->Branch(a->WordEqual(a->LoadInstanceType(tagged),
5340 a->Int32Constant(JS_TYPED_ARRAY_TYPE)),
5341 &is_typed_array, &not_typed_array);
5342 a->Bind(&not_typed_array);
5343 a->Goto(&invalid);
5344
5345 // Fail if the array's JSArrayBuffer is not shared.
5346 a->Bind(&is_typed_array);
5347 Node* array_buffer = a->LoadObjectField(tagged, JSTypedArray::kBufferOffset);
5348 Node* is_buffer_shared = a->BitFieldDecode<JSArrayBuffer::IsShared>(
5349 a->LoadObjectField(array_buffer, JSArrayBuffer::kBitFieldSlot));
5350 a->Branch(is_buffer_shared, &is_shared, &not_shared);
5351 a->Bind(&not_shared);
5352 a->Goto(&invalid);
5353
5354 // Fail if the array's element type is float32, float64 or clamped.
5355 a->Bind(&is_shared);
5356 Node* elements_instance_type = a->LoadInstanceType(
5357 a->LoadObjectField(tagged, JSObject::kElementsOffset));
5358 STATIC_ASSERT(FIXED_INT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5359 STATIC_ASSERT(FIXED_INT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5360 STATIC_ASSERT(FIXED_INT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5361 STATIC_ASSERT(FIXED_UINT8_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5362 STATIC_ASSERT(FIXED_UINT16_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5363 STATIC_ASSERT(FIXED_UINT32_ARRAY_TYPE < FIXED_FLOAT32_ARRAY_TYPE);
5364 a->Branch(a->Int32LessThan(elements_instance_type,
5365 a->Int32Constant(FIXED_FLOAT32_ARRAY_TYPE)),
5366 &not_float_or_clamped, &is_float_or_clamped);
5367 a->Bind(&is_float_or_clamped);
5368 a->Goto(&invalid);
5369
5370 a->Bind(&invalid);
5371 a->CallRuntime(Runtime::kThrowNotIntegerSharedTypedArrayError, context,
5372 tagged);
5373 a->Return(a->UndefinedConstant());
5374
5375 a->Bind(&not_float_or_clamped);
5376 *out_instance_type = elements_instance_type;
5377
5378 Node* backing_store =
5379 a->LoadObjectField(array_buffer, JSArrayBuffer::kBackingStoreOffset);
5380 Node* byte_offset = a->ChangeUint32ToWord(a->TruncateTaggedToWord32(
5381 context,
5382 a->LoadObjectField(tagged, JSArrayBufferView::kByteOffsetOffset)));
5383 *out_backing_store = a->IntPtrAdd(backing_store, byte_offset);
5384}
5385
5386// https://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomics.ValidateAtomicAccess
5387compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
5388 compiler::Node* tagged,
5389 compiler::Node* context) {
5390 using namespace compiler;
5391 CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32);
5392
5393 Callable to_number = CodeFactory::ToNumber(a->isolate());
5394 Node* number_index = a->CallStub(to_number, context, tagged);
5395 CodeStubAssembler::Label done(a, &var_result);
5396
5397 CodeStubAssembler::Label if_numberissmi(a), if_numberisnotsmi(a);
5398 a->Branch(a->WordIsSmi(number_index), &if_numberissmi, &if_numberisnotsmi);
5399
5400 a->Bind(&if_numberissmi);
5401 {
5402 var_result.Bind(a->SmiToWord32(number_index));
5403 a->Goto(&done);
5404 }
5405
5406 a->Bind(&if_numberisnotsmi);
5407 {
5408 Node* number_index_value = a->LoadHeapNumberValue(number_index);
5409 Node* access_index = a->TruncateFloat64ToWord32(number_index_value);
5410 Node* test_index = a->ChangeInt32ToFloat64(access_index);
5411
5412 CodeStubAssembler::Label if_indexesareequal(a), if_indexesarenotequal(a);
5413 a->Branch(a->Float64Equal(number_index_value, test_index),
5414 &if_indexesareequal, &if_indexesarenotequal);
5415
5416 a->Bind(&if_indexesareequal);
5417 {
5418 var_result.Bind(access_index);
5419 a->Goto(&done);
5420 }
5421
5422 a->Bind(&if_indexesarenotequal);
5423 a->Return(
5424 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
5425 }
5426
5427 a->Bind(&done);
5428 return var_result.value();
5429}
5430
5431void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
5432 compiler::Node* array_length_word,
5433 compiler::Node* context) {
5434 using namespace compiler;
5435 // Check if the index is in bounds. If not, throw RangeError.
5436 CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a);
5437 a->Branch(
5438 a->WordOr(a->Int32LessThan(index_word, a->Int32Constant(0)),
5439 a->Int32GreaterThanOrEqual(index_word, array_length_word)),
5440 &if_notinbounds, &if_inbounds);
5441 a->Bind(&if_notinbounds);
5442 a->Return(
5443 a->CallRuntime(Runtime::kThrowInvalidAtomicAccessIndexError, context));
5444 a->Bind(&if_inbounds);
5445}
5446
5447} // anonymous namespace
5448
5449void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) {
5450 using namespace compiler;
5451 Node* array = a->Parameter(1);
5452 Node* index = a->Parameter(2);
5453 Node* context = a->Parameter(3 + 2);
5454
5455 Node* instance_type;
5456 Node* backing_store;
5457 ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
5458
5459 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
5460 Node* array_length_word32 = a->TruncateTaggedToWord32(
5461 context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
5462 ValidateAtomicIndex(a, index_word32, array_length_word32, context);
5463 Node* index_word = a->ChangeUint32ToWord(index_word32);
5464
5465 CodeStubAssembler::Label i8(a), u8(a), i16(a), u16(a), i32(a), u32(a),
5466 other(a);
5467 int32_t case_values[] = {
5468 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
5469 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
5470 };
5471 CodeStubAssembler::Label* case_labels[] = {
5472 &i8, &u8, &i16, &u16, &i32, &u32,
5473 };
5474 a->Switch(instance_type, &other, case_values, case_labels,
5475 arraysize(case_labels));
5476
5477 a->Bind(&i8);
5478 a->Return(
5479 a->SmiTag(a->AtomicLoad(MachineType::Int8(), backing_store, index_word)));
5480
5481 a->Bind(&u8);
5482 a->Return(a->SmiTag(
5483 a->AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
5484
5485 a->Bind(&i16);
5486 a->Return(a->SmiTag(a->AtomicLoad(MachineType::Int16(), backing_store,
5487 a->WordShl(index_word, 1))));
5488
5489 a->Bind(&u16);
5490 a->Return(a->SmiTag(a->AtomicLoad(MachineType::Uint16(), backing_store,
5491 a->WordShl(index_word, 1))));
5492
5493 a->Bind(&i32);
5494 a->Return(a->ChangeInt32ToTagged(a->AtomicLoad(
5495 MachineType::Int32(), backing_store, a->WordShl(index_word, 2))));
5496
5497 a->Bind(&u32);
5498 a->Return(a->ChangeUint32ToTagged(a->AtomicLoad(
5499 MachineType::Uint32(), backing_store, a->WordShl(index_word, 2))));
5500
5501 // This shouldn't happen, we've already validated the type.
5502 a->Bind(&other);
5503 a->Return(a->Int32Constant(0));
5504}
5505
5506void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) {
5507 using namespace compiler;
5508 Node* array = a->Parameter(1);
5509 Node* index = a->Parameter(2);
5510 Node* value = a->Parameter(3);
5511 Node* context = a->Parameter(4 + 2);
5512
5513 Node* instance_type;
5514 Node* backing_store;
5515 ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
5516
5517 Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
5518 Node* array_length_word32 = a->TruncateTaggedToWord32(
5519 context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
5520 ValidateAtomicIndex(a, index_word32, array_length_word32, context);
5521 Node* index_word = a->ChangeUint32ToWord(index_word32);
5522
5523 Callable to_integer = CodeFactory::ToInteger(a->isolate());
5524 Node* value_integer = a->CallStub(to_integer, context, value);
5525 Node* value_word32 = a->TruncateTaggedToWord32(context, value_integer);
5526
5527 CodeStubAssembler::Label u8(a), u16(a), u32(a), other(a);
5528 int32_t case_values[] = {
5529 FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
5530 FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
5531 };
5532 CodeStubAssembler::Label* case_labels[] = {
5533 &u8, &u8, &u16, &u16, &u32, &u32,
5534 };
5535 a->Switch(instance_type, &other, case_values, case_labels,
5536 arraysize(case_labels));
5537
5538 a->Bind(&u8);
5539 a->AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
5540 value_word32);
5541 a->Return(value_integer);
5542
5543 a->Bind(&u16);
5544 a->SmiTag(a->AtomicStore(MachineRepresentation::kWord16, backing_store,
5545 a->WordShl(index_word, 1), value_word32));
5546 a->Return(value_integer);
5547
5548 a->Bind(&u32);
5549 a->AtomicStore(MachineRepresentation::kWord32, backing_store,
5550 a->WordShl(index_word, 2), value_word32);
5551 a->Return(value_integer);
5552
5553 // This shouldn't happen, we've already validated the type.
5554 a->Bind(&other);
5555 a->Return(a->Int32Constant(0));
5556}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005557
Steve Block44f0eee2011-05-26 01:26:41 +01005558#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
5559Handle<Code> Builtins::name() { \
5560 Code** code_address = \
5561 reinterpret_cast<Code**>(builtin_address(k##name)); \
5562 return Handle<Code>(code_address); \
5563}
5564#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
5565Handle<Code> Builtins::name() { \
5566 Code** code_address = \
5567 reinterpret_cast<Code**>(builtin_address(k##name)); \
5568 return Handle<Code>(code_address); \
5569}
Ben Murdochda12d292016-06-02 14:46:10 +01005570#define DEFINE_BUILTIN_ACCESSOR_T(name, argc) \
5571 Handle<Code> Builtins::name() { \
5572 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##name)); \
5573 return Handle<Code>(code_address); \
5574 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005575#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
5576Handle<Code> Builtins::name() { \
5577 Code** code_address = \
5578 reinterpret_cast<Code**>(builtin_address(k##name)); \
5579 return Handle<Code>(code_address); \
5580}
Steve Block44f0eee2011-05-26 01:26:41 +01005581BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
5582BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
Ben Murdochda12d292016-06-02 14:46:10 +01005583BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005584BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01005585BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
5586#undef DEFINE_BUILTIN_ACCESSOR_C
5587#undef DEFINE_BUILTIN_ACCESSOR_A
Ben Murdochda12d292016-06-02 14:46:10 +01005588#undef DEFINE_BUILTIN_ACCESSOR_T
5589#undef DEFINE_BUILTIN_ACCESSOR_H
Steve Block44f0eee2011-05-26 01:26:41 +01005590
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005591} // namespace internal
5592} // namespace v8