• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdlib.h>
6 #include <limits>
7 
8 #include "src/v8.h"
9 
10 #include "src/accessors.h"
11 #include "src/allocation-site-scopes.h"
12 #include "src/api.h"
13 #include "src/arguments.h"
14 #include "src/bootstrapper.h"
15 #include "src/codegen.h"
16 #include "src/compilation-cache.h"
17 #include "src/compiler.h"
18 #include "src/conversions.h"
19 #include "src/cpu.h"
20 #include "src/cpu-profiler.h"
21 #include "src/dateparser-inl.h"
22 #include "src/debug.h"
23 #include "src/deoptimizer.h"
24 #include "src/date.h"
25 #include "src/execution.h"
26 #include "src/full-codegen.h"
27 #include "src/global-handles.h"
28 #include "src/isolate-inl.h"
29 #include "src/jsregexp.h"
30 #include "src/jsregexp-inl.h"
31 #include "src/json-parser.h"
32 #include "src/json-stringifier.h"
33 #include "src/liveedit.h"
34 #include "src/misc-intrinsics.h"
35 #include "src/parser.h"
36 #include "src/platform.h"
37 #include "src/runtime-profiler.h"
38 #include "src/runtime.h"
39 #include "src/scopeinfo.h"
40 #include "src/smart-pointers.h"
41 #include "src/string-search.h"
42 #include "src/stub-cache.h"
43 #include "src/uri.h"
44 #include "src/v8threads.h"
45 #include "src/vm-state-inl.h"
46 
47 #ifdef V8_I18N_SUPPORT
48 #include "src/i18n.h"
49 #include "unicode/brkiter.h"
50 #include "unicode/calendar.h"
51 #include "unicode/coll.h"
52 #include "unicode/curramt.h"
53 #include "unicode/datefmt.h"
54 #include "unicode/dcfmtsym.h"
55 #include "unicode/decimfmt.h"
56 #include "unicode/dtfmtsym.h"
57 #include "unicode/dtptngen.h"
58 #include "unicode/locid.h"
59 #include "unicode/numfmt.h"
60 #include "unicode/numsys.h"
61 #include "unicode/rbbi.h"
62 #include "unicode/smpdtfmt.h"
63 #include "unicode/timezone.h"
64 #include "unicode/uchar.h"
65 #include "unicode/ucol.h"
66 #include "unicode/ucurr.h"
67 #include "unicode/uloc.h"
68 #include "unicode/unum.h"
69 #include "unicode/uversion.h"
70 #endif
71 
72 #ifndef _STLP_VENDOR_CSTD
73 // STLPort doesn't import fpclassify and isless into the std namespace.
74 using std::fpclassify;
75 using std::isless;
76 #endif
77 
78 namespace v8 {
79 namespace internal {
80 
81 
82 #define RUNTIME_ASSERT(value) \
83   if (!(value)) return isolate->ThrowIllegalOperation();
84 
85 #define RUNTIME_ASSERT_HANDLIFIED(value, T)                          \
86   if (!(value)) {                                                    \
87     isolate->ThrowIllegalOperation();                                \
88     return MaybeHandle<T>();                                         \
89   }
90 
91 // Cast the given object to a value of the specified type and store
92 // it in a variable with the given name.  If the object is not of the
93 // expected type call IllegalOperation and return.
94 #define CONVERT_ARG_CHECKED(Type, name, index)                       \
95   RUNTIME_ASSERT(args[index]->Is##Type());                           \
96   Type* name = Type::cast(args[index]);
97 
98 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
99   RUNTIME_ASSERT(args[index]->Is##Type());                           \
100   Handle<Type> name = args.at<Type>(index);
101 
102 #define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index)               \
103   RUNTIME_ASSERT(args[index]->IsNumber());                           \
104   Handle<Object> name = args.at<Object>(index);
105 
106 // Cast the given object to a boolean and store it in a variable with
107 // the given name.  If the object is not a boolean call IllegalOperation
108 // and return.
109 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
110   RUNTIME_ASSERT(args[index]->IsBoolean());                          \
111   bool name = args[index]->IsTrue();
112 
113 // Cast the given argument to a Smi and store its value in an int variable
114 // with the given name.  If the argument is not a Smi call IllegalOperation
115 // and return.
116 #define CONVERT_SMI_ARG_CHECKED(name, index)                         \
117   RUNTIME_ASSERT(args[index]->IsSmi());                              \
118   int name = args.smi_at(index);
119 
120 // Cast the given argument to a double and store it in a variable with
121 // the given name.  If the argument is not a number (as opposed to
122 // the number not-a-number) call IllegalOperation and return.
123 #define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
124   RUNTIME_ASSERT(args[index]->IsNumber());                           \
125   double name = args.number_at(index);
126 
127 // Call the specified converter on the object *comand store the result in
128 // a variable of the specified type with the given name.  If the
129 // object is not a Number call IllegalOperation and return.
130 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
131   RUNTIME_ASSERT(obj->IsNumber());                                   \
132   type name = NumberTo##Type(obj);
133 
134 
135 // Cast the given argument to PropertyDetails and store its value in a
136 // variable with the given name.  If the argument is not a Smi call
137 // IllegalOperation and return.
138 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
139   RUNTIME_ASSERT(args[index]->IsSmi());                              \
140   PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
141 
142 
143 // Assert that the given argument has a valid value for a StrictMode
144 // and store it in a StrictMode variable with the given name.
145 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
146   RUNTIME_ASSERT(args[index]->IsSmi());                              \
147   RUNTIME_ASSERT(args.smi_at(index) == STRICT ||                     \
148                  args.smi_at(index) == SLOPPY);                      \
149   StrictMode name = static_cast<StrictMode>(args.smi_at(index));
150 
151 
ComputeObjectLiteralMap(Handle<Context> context,Handle<FixedArray> constant_properties,bool * is_result_from_cache)152 static Handle<Map> ComputeObjectLiteralMap(
153     Handle<Context> context,
154     Handle<FixedArray> constant_properties,
155     bool* is_result_from_cache) {
156   Isolate* isolate = context->GetIsolate();
157   int properties_length = constant_properties->length();
158   int number_of_properties = properties_length / 2;
159   // Check that there are only internal strings and array indices among keys.
160   int number_of_string_keys = 0;
161   for (int p = 0; p != properties_length; p += 2) {
162     Object* key = constant_properties->get(p);
163     uint32_t element_index = 0;
164     if (key->IsInternalizedString()) {
165       number_of_string_keys++;
166     } else if (key->ToArrayIndex(&element_index)) {
167       // An index key does not require space in the property backing store.
168       number_of_properties--;
169     } else {
170       // Bail out as a non-internalized-string non-index key makes caching
171       // impossible.
172       // ASSERT to make sure that the if condition after the loop is false.
173       ASSERT(number_of_string_keys != number_of_properties);
174       break;
175     }
176   }
177   // If we only have internalized strings and array indices among keys then we
178   // can use the map cache in the native context.
179   const int kMaxKeys = 10;
180   if ((number_of_string_keys == number_of_properties) &&
181       (number_of_string_keys < kMaxKeys)) {
182     // Create the fixed array with the key.
183     Handle<FixedArray> keys =
184         isolate->factory()->NewFixedArray(number_of_string_keys);
185     if (number_of_string_keys > 0) {
186       int index = 0;
187       for (int p = 0; p < properties_length; p += 2) {
188         Object* key = constant_properties->get(p);
189         if (key->IsInternalizedString()) {
190           keys->set(index++, key);
191         }
192       }
193       ASSERT(index == number_of_string_keys);
194     }
195     *is_result_from_cache = true;
196     return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
197   }
198   *is_result_from_cache = false;
199   return Map::Create(handle(context->object_function()), number_of_properties);
200 }
201 
202 
203 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
204     Isolate* isolate,
205     Handle<FixedArray> literals,
206     Handle<FixedArray> constant_properties);
207 
208 
CreateObjectLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> constant_properties,bool should_have_fast_elements,bool has_function_literal)209 MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
210     Isolate* isolate,
211     Handle<FixedArray> literals,
212     Handle<FixedArray> constant_properties,
213     bool should_have_fast_elements,
214     bool has_function_literal) {
215   // Get the native context from the literals array.  This is the
216   // context in which the function was created and we use the object
217   // function from this context to create the object literal.  We do
218   // not use the object function from the current native context
219   // because this might be the object function from another context
220   // which we should not have access to.
221   Handle<Context> context =
222       Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
223 
224   // In case we have function literals, we want the object to be in
225   // slow properties mode for now. We don't go in the map cache because
226   // maps with constant functions can't be shared if the functions are
227   // not the same (which is the common case).
228   bool is_result_from_cache = false;
229   Handle<Map> map = has_function_literal
230       ? Handle<Map>(context->object_function()->initial_map())
231       : ComputeObjectLiteralMap(context,
232                                 constant_properties,
233                                 &is_result_from_cache);
234 
235   PretenureFlag pretenure_flag =
236       isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
237 
238   Handle<JSObject> boilerplate =
239       isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
240 
241   // Normalize the elements of the boilerplate to save space if needed.
242   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
243 
244   // Add the constant properties to the boilerplate.
245   int length = constant_properties->length();
246   bool should_transform =
247       !is_result_from_cache && boilerplate->HasFastProperties();
248   bool should_normalize = should_transform || has_function_literal;
249   if (should_normalize) {
250     // TODO(verwaest): We might not want to ever normalize here.
251     JSObject::NormalizeProperties(
252         boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
253   }
254   Object::ValueType value_type = should_normalize
255       ? Object::FORCE_TAGGED : Object::OPTIMAL_REPRESENTATION;
256 
257   // TODO(verwaest): Support tracking representations in the boilerplate.
258   for (int index = 0; index < length; index +=2) {
259     Handle<Object> key(constant_properties->get(index+0), isolate);
260     Handle<Object> value(constant_properties->get(index+1), isolate);
261     if (value->IsFixedArray()) {
262       // The value contains the constant_properties of a
263       // simple object or array literal.
264       Handle<FixedArray> array = Handle<FixedArray>::cast(value);
265       ASSIGN_RETURN_ON_EXCEPTION(
266           isolate, value,
267           CreateLiteralBoilerplate(isolate, literals, array),
268           Object);
269     }
270     MaybeHandle<Object> maybe_result;
271     uint32_t element_index = 0;
272     StoreMode mode = value->IsJSObject() ? FORCE_FIELD : ALLOW_AS_CONSTANT;
273     if (key->IsInternalizedString()) {
274       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
275         // Array index as string (uint32).
276         maybe_result = JSObject::SetOwnElement(
277             boilerplate, element_index, value, SLOPPY);
278       } else {
279         Handle<String> name(String::cast(*key));
280         ASSERT(!name->AsArrayIndex(&element_index));
281         maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(
282             boilerplate, name, value, NONE,
283             value_type, mode);
284       }
285     } else if (key->ToArrayIndex(&element_index)) {
286       // Array index (uint32).
287       maybe_result = JSObject::SetOwnElement(
288           boilerplate, element_index, value, SLOPPY);
289     } else {
290       // Non-uint32 number.
291       ASSERT(key->IsNumber());
292       double num = key->Number();
293       char arr[100];
294       Vector<char> buffer(arr, ARRAY_SIZE(arr));
295       const char* str = DoubleToCString(num, buffer);
296       Handle<String> name = isolate->factory()->NewStringFromAsciiChecked(str);
297       maybe_result = JSObject::SetOwnPropertyIgnoreAttributes(
298           boilerplate, name, value, NONE,
299           value_type, mode);
300     }
301     // If setting the property on the boilerplate throws an
302     // exception, the exception is converted to an empty handle in
303     // the handle based operations.  In that case, we need to
304     // convert back to an exception.
305     RETURN_ON_EXCEPTION(isolate, maybe_result, Object);
306   }
307 
308   // Transform to fast properties if necessary. For object literals with
309   // containing function literals we defer this operation until after all
310   // computed properties have been assigned so that we can generate
311   // constant function properties.
312   if (should_transform && !has_function_literal) {
313     JSObject::TransformToFastProperties(
314         boilerplate, boilerplate->map()->unused_property_fields());
315   }
316 
317   return boilerplate;
318 }
319 
320 
TransitionElements(Handle<Object> object,ElementsKind to_kind,Isolate * isolate)321 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
322     Handle<Object> object,
323     ElementsKind to_kind,
324     Isolate* isolate) {
325   HandleScope scope(isolate);
326   if (!object->IsJSObject()) {
327     isolate->ThrowIllegalOperation();
328     return MaybeHandle<Object>();
329   }
330   ElementsKind from_kind =
331       Handle<JSObject>::cast(object)->map()->elements_kind();
332   if (Map::IsValidElementsTransition(from_kind, to_kind)) {
333     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
334     return object;
335   }
336   isolate->ThrowIllegalOperation();
337   return MaybeHandle<Object>();
338 }
339 
340 
341 static const int kSmiLiteralMinimumLength = 1024;
342 
343 
CreateArrayLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> elements)344 MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
345     Isolate* isolate,
346     Handle<FixedArray> literals,
347     Handle<FixedArray> elements) {
348   // Create the JSArray.
349   Handle<JSFunction> constructor(
350       JSFunction::NativeContextFromLiterals(*literals)->array_function());
351 
352   PretenureFlag pretenure_flag =
353       isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
354 
355   Handle<JSArray> object = Handle<JSArray>::cast(
356       isolate->factory()->NewJSObject(constructor, pretenure_flag));
357 
358   ElementsKind constant_elements_kind =
359       static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
360   Handle<FixedArrayBase> constant_elements_values(
361       FixedArrayBase::cast(elements->get(1)));
362 
363   { DisallowHeapAllocation no_gc;
364     ASSERT(IsFastElementsKind(constant_elements_kind));
365     Context* native_context = isolate->context()->native_context();
366     Object* maps_array = native_context->js_array_maps();
367     ASSERT(!maps_array->IsUndefined());
368     Object* map = FixedArray::cast(maps_array)->get(constant_elements_kind);
369     object->set_map(Map::cast(map));
370   }
371 
372   Handle<FixedArrayBase> copied_elements_values;
373   if (IsFastDoubleElementsKind(constant_elements_kind)) {
374     ASSERT(FLAG_smi_only_arrays);
375     copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
376         Handle<FixedDoubleArray>::cast(constant_elements_values));
377   } else {
378     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
379     const bool is_cow =
380         (constant_elements_values->map() ==
381          isolate->heap()->fixed_cow_array_map());
382     if (is_cow) {
383       copied_elements_values = constant_elements_values;
384 #if DEBUG
385       Handle<FixedArray> fixed_array_values =
386           Handle<FixedArray>::cast(copied_elements_values);
387       for (int i = 0; i < fixed_array_values->length(); i++) {
388         ASSERT(!fixed_array_values->get(i)->IsFixedArray());
389       }
390 #endif
391     } else {
392       Handle<FixedArray> fixed_array_values =
393           Handle<FixedArray>::cast(constant_elements_values);
394       Handle<FixedArray> fixed_array_values_copy =
395           isolate->factory()->CopyFixedArray(fixed_array_values);
396       copied_elements_values = fixed_array_values_copy;
397       for (int i = 0; i < fixed_array_values->length(); i++) {
398         if (fixed_array_values->get(i)->IsFixedArray()) {
399           // The value contains the constant_properties of a
400           // simple object or array literal.
401           Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
402           Handle<Object> result;
403           ASSIGN_RETURN_ON_EXCEPTION(
404               isolate, result,
405               CreateLiteralBoilerplate(isolate, literals, fa),
406               Object);
407           fixed_array_values_copy->set(i, *result);
408         }
409       }
410     }
411   }
412   object->set_elements(*copied_elements_values);
413   object->set_length(Smi::FromInt(copied_elements_values->length()));
414 
415   //  Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
416   //  on or the object is larger than the threshold.
417   if (!FLAG_smi_only_arrays &&
418       constant_elements_values->length() < kSmiLiteralMinimumLength) {
419     ElementsKind elements_kind = object->GetElementsKind();
420     if (!IsFastObjectElementsKind(elements_kind)) {
421       if (IsFastHoleyElementsKind(elements_kind)) {
422         TransitionElements(object, FAST_HOLEY_ELEMENTS, isolate).Check();
423       } else {
424         TransitionElements(object, FAST_ELEMENTS, isolate).Check();
425       }
426     }
427   }
428 
429   JSObject::ValidateElements(object);
430   return object;
431 }
432 
433 
CreateLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> array)434 MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
435     Isolate* isolate,
436     Handle<FixedArray> literals,
437     Handle<FixedArray> array) {
438   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
439   const bool kHasNoFunctionLiteral = false;
440   switch (CompileTimeValue::GetLiteralType(array)) {
441     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
442       return CreateObjectLiteralBoilerplate(isolate,
443                                             literals,
444                                             elements,
445                                             true,
446                                             kHasNoFunctionLiteral);
447     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
448       return CreateObjectLiteralBoilerplate(isolate,
449                                             literals,
450                                             elements,
451                                             false,
452                                             kHasNoFunctionLiteral);
453     case CompileTimeValue::ARRAY_LITERAL:
454       return Runtime::CreateArrayLiteralBoilerplate(
455           isolate, literals, elements);
456     default:
457       UNREACHABLE();
458       return MaybeHandle<Object>();
459   }
460 }
461 
462 
RUNTIME_FUNCTION(RuntimeHidden_CreateObjectLiteral)463 RUNTIME_FUNCTION(RuntimeHidden_CreateObjectLiteral) {
464   HandleScope scope(isolate);
465   ASSERT(args.length() == 4);
466   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
467   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
468   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
469   CONVERT_SMI_ARG_CHECKED(flags, 3);
470   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
471   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
472 
473   RUNTIME_ASSERT(literals_index >= 0 && literals_index < literals->length());
474 
475   // Check if boilerplate exists. If not, create it first.
476   Handle<Object> literal_site(literals->get(literals_index), isolate);
477   Handle<AllocationSite> site;
478   Handle<JSObject> boilerplate;
479   if (*literal_site == isolate->heap()->undefined_value()) {
480     Handle<Object> raw_boilerplate;
481     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
482         isolate, raw_boilerplate,
483         CreateObjectLiteralBoilerplate(
484             isolate,
485             literals,
486             constant_properties,
487             should_have_fast_elements,
488             has_function_literal));
489     boilerplate = Handle<JSObject>::cast(raw_boilerplate);
490 
491     AllocationSiteCreationContext creation_context(isolate);
492     site = creation_context.EnterNewScope();
493     RETURN_FAILURE_ON_EXCEPTION(
494         isolate,
495         JSObject::DeepWalk(boilerplate, &creation_context));
496     creation_context.ExitScope(site, boilerplate);
497 
498     // Update the functions literal and return the boilerplate.
499     literals->set(literals_index, *site);
500   } else {
501     site = Handle<AllocationSite>::cast(literal_site);
502     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
503                                    isolate);
504   }
505 
506   AllocationSiteUsageContext usage_context(isolate, site, true);
507   usage_context.EnterNewScope();
508   MaybeHandle<Object> maybe_copy = JSObject::DeepCopy(
509       boilerplate, &usage_context);
510   usage_context.ExitScope(site, boilerplate);
511   Handle<Object> copy;
512   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, copy, maybe_copy);
513   return *copy;
514 }
515 
516 
GetLiteralAllocationSite(Isolate * isolate,Handle<FixedArray> literals,int literals_index,Handle<FixedArray> elements)517 MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
518     Isolate* isolate,
519     Handle<FixedArray> literals,
520     int literals_index,
521     Handle<FixedArray> elements) {
522   // Check if boilerplate exists. If not, create it first.
523   Handle<Object> literal_site(literals->get(literals_index), isolate);
524   Handle<AllocationSite> site;
525   if (*literal_site == isolate->heap()->undefined_value()) {
526     ASSERT(*elements != isolate->heap()->empty_fixed_array());
527     Handle<Object> boilerplate;
528     ASSIGN_RETURN_ON_EXCEPTION(
529         isolate, boilerplate,
530         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements),
531         AllocationSite);
532 
533     AllocationSiteCreationContext creation_context(isolate);
534     site = creation_context.EnterNewScope();
535     if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate),
536                            &creation_context).is_null()) {
537       return Handle<AllocationSite>::null();
538     }
539     creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
540 
541     literals->set(literals_index, *site);
542   } else {
543     site = Handle<AllocationSite>::cast(literal_site);
544   }
545 
546   return site;
547 }
548 
549 
CreateArrayLiteralImpl(Isolate * isolate,Handle<FixedArray> literals,int literals_index,Handle<FixedArray> elements,int flags)550 static MaybeHandle<JSObject> CreateArrayLiteralImpl(Isolate* isolate,
551                                            Handle<FixedArray> literals,
552                                            int literals_index,
553                                            Handle<FixedArray> elements,
554                                            int flags) {
555   RUNTIME_ASSERT_HANDLIFIED(literals_index >= 0 &&
556                             literals_index < literals->length(), JSObject);
557   Handle<AllocationSite> site;
558   ASSIGN_RETURN_ON_EXCEPTION(
559       isolate, site,
560       GetLiteralAllocationSite(isolate, literals, literals_index, elements),
561       JSObject);
562 
563   bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
564   Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
565   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
566   usage_context.EnterNewScope();
567   JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
568       ? JSObject::kNoHints
569       : JSObject::kObjectIsShallowArray;
570   MaybeHandle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
571                                                   hints);
572   usage_context.ExitScope(site, boilerplate);
573   return copy;
574 }
575 
576 
RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteral)577 RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteral) {
578   HandleScope scope(isolate);
579   ASSERT(args.length() == 4);
580   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
581   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
582   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
583   CONVERT_SMI_ARG_CHECKED(flags, 3);
584 
585   Handle<JSObject> result;
586   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
587       CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
588                              flags));
589   return *result;
590 }
591 
592 
RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteralStubBailout)593 RUNTIME_FUNCTION(RuntimeHidden_CreateArrayLiteralStubBailout) {
594   HandleScope scope(isolate);
595   ASSERT(args.length() == 3);
596   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
597   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
598   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
599 
600   Handle<JSObject> result;
601   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
602      CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
603                             ArrayLiteral::kShallowElements));
604   return *result;
605 }
606 
607 
RUNTIME_FUNCTION(Runtime_CreateSymbol)608 RUNTIME_FUNCTION(Runtime_CreateSymbol) {
609   HandleScope scope(isolate);
610   ASSERT(args.length() == 1);
611   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
612   RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
613   Handle<Symbol> symbol = isolate->factory()->NewSymbol();
614   if (name->IsString()) symbol->set_name(*name);
615   return *symbol;
616 }
617 
618 
RUNTIME_FUNCTION(Runtime_CreatePrivateSymbol)619 RUNTIME_FUNCTION(Runtime_CreatePrivateSymbol) {
620   HandleScope scope(isolate);
621   ASSERT(args.length() == 1);
622   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
623   RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
624   Handle<Symbol> symbol = isolate->factory()->NewPrivateSymbol();
625   if (name->IsString()) symbol->set_name(*name);
626   return *symbol;
627 }
628 
629 
RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol)630 RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
631   HandleScope scope(isolate);
632   ASSERT(args.length() == 1);
633   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
634   Handle<JSObject> registry = isolate->GetSymbolRegistry();
635   Handle<String> part = isolate->factory()->private_intern_string();
636   Handle<Object> privates;
637   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
638       isolate, privates, Object::GetPropertyOrElement(registry, part));
639   Handle<Object> symbol;
640   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
641       isolate, symbol, Object::GetPropertyOrElement(privates, name));
642   if (!symbol->IsSymbol()) {
643     ASSERT(symbol->IsUndefined());
644     symbol = isolate->factory()->NewPrivateSymbol();
645     Handle<Symbol>::cast(symbol)->set_name(*name);
646     JSObject::SetProperty(Handle<JSObject>::cast(privates),
647                           name, symbol, NONE, STRICT).Assert();
648   }
649   return *symbol;
650 }
651 
652 
RUNTIME_FUNCTION(Runtime_NewSymbolWrapper)653 RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
654   HandleScope scope(isolate);
655   ASSERT(args.length() == 1);
656   CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
657   return *Object::ToObject(isolate, symbol).ToHandleChecked();
658 }
659 
660 
RUNTIME_FUNCTION(Runtime_SymbolDescription)661 RUNTIME_FUNCTION(Runtime_SymbolDescription) {
662   SealHandleScope shs(isolate);
663   ASSERT(args.length() == 1);
664   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
665   return symbol->name();
666 }
667 
668 
RUNTIME_FUNCTION(Runtime_SymbolRegistry)669 RUNTIME_FUNCTION(Runtime_SymbolRegistry) {
670   HandleScope scope(isolate);
671   ASSERT(args.length() == 0);
672   return *isolate->GetSymbolRegistry();
673 }
674 
675 
RUNTIME_FUNCTION(Runtime_SymbolIsPrivate)676 RUNTIME_FUNCTION(Runtime_SymbolIsPrivate) {
677   SealHandleScope shs(isolate);
678   ASSERT(args.length() == 1);
679   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
680   return isolate->heap()->ToBoolean(symbol->is_private());
681 }
682 
683 
RUNTIME_FUNCTION(Runtime_CreateJSProxy)684 RUNTIME_FUNCTION(Runtime_CreateJSProxy) {
685   HandleScope scope(isolate);
686   ASSERT(args.length() == 2);
687   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
688   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
689   if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
690   return *isolate->factory()->NewJSProxy(handler, prototype);
691 }
692 
693 
RUNTIME_FUNCTION(Runtime_CreateJSFunctionProxy)694 RUNTIME_FUNCTION(Runtime_CreateJSFunctionProxy) {
695   HandleScope scope(isolate);
696   ASSERT(args.length() == 4);
697   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, handler, 0);
698   CONVERT_ARG_HANDLE_CHECKED(Object, call_trap, 1);
699   RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
700   CONVERT_ARG_HANDLE_CHECKED(JSFunction, construct_trap, 2);
701   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 3);
702   if (!prototype->IsJSReceiver()) prototype = isolate->factory()->null_value();
703   return *isolate->factory()->NewJSFunctionProxy(
704       handler, call_trap, construct_trap, prototype);
705 }
706 
707 
RUNTIME_FUNCTION(Runtime_IsJSProxy)708 RUNTIME_FUNCTION(Runtime_IsJSProxy) {
709   SealHandleScope shs(isolate);
710   ASSERT(args.length() == 1);
711   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
712   return isolate->heap()->ToBoolean(obj->IsJSProxy());
713 }
714 
715 
RUNTIME_FUNCTION(Runtime_IsJSFunctionProxy)716 RUNTIME_FUNCTION(Runtime_IsJSFunctionProxy) {
717   SealHandleScope shs(isolate);
718   ASSERT(args.length() == 1);
719   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
720   return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
721 }
722 
723 
RUNTIME_FUNCTION(Runtime_GetHandler)724 RUNTIME_FUNCTION(Runtime_GetHandler) {
725   SealHandleScope shs(isolate);
726   ASSERT(args.length() == 1);
727   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
728   return proxy->handler();
729 }
730 
731 
RUNTIME_FUNCTION(Runtime_GetCallTrap)732 RUNTIME_FUNCTION(Runtime_GetCallTrap) {
733   SealHandleScope shs(isolate);
734   ASSERT(args.length() == 1);
735   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
736   return proxy->call_trap();
737 }
738 
739 
RUNTIME_FUNCTION(Runtime_GetConstructTrap)740 RUNTIME_FUNCTION(Runtime_GetConstructTrap) {
741   SealHandleScope shs(isolate);
742   ASSERT(args.length() == 1);
743   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
744   return proxy->construct_trap();
745 }
746 
747 
RUNTIME_FUNCTION(Runtime_Fix)748 RUNTIME_FUNCTION(Runtime_Fix) {
749   HandleScope scope(isolate);
750   ASSERT(args.length() == 1);
751   CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
752   JSProxy::Fix(proxy);
753   return isolate->heap()->undefined_value();
754 }
755 
756 
FreeArrayBuffer(Isolate * isolate,JSArrayBuffer * phantom_array_buffer)757 void Runtime::FreeArrayBuffer(Isolate* isolate,
758                               JSArrayBuffer* phantom_array_buffer) {
759   if (phantom_array_buffer->should_be_freed()) {
760     ASSERT(phantom_array_buffer->is_external());
761     free(phantom_array_buffer->backing_store());
762   }
763   if (phantom_array_buffer->is_external()) return;
764 
765   size_t allocated_length = NumberToSize(
766       isolate, phantom_array_buffer->byte_length());
767 
768   reinterpret_cast<v8::Isolate*>(isolate)
769       ->AdjustAmountOfExternalAllocatedMemory(
770           -static_cast<int64_t>(allocated_length));
771   CHECK(V8::ArrayBufferAllocator() != NULL);
772   V8::ArrayBufferAllocator()->Free(
773       phantom_array_buffer->backing_store(),
774       allocated_length);
775 }
776 
777 
SetupArrayBuffer(Isolate * isolate,Handle<JSArrayBuffer> array_buffer,bool is_external,void * data,size_t allocated_length)778 void Runtime::SetupArrayBuffer(Isolate* isolate,
779                                Handle<JSArrayBuffer> array_buffer,
780                                bool is_external,
781                                void* data,
782                                size_t allocated_length) {
783   ASSERT(array_buffer->GetInternalFieldCount() ==
784       v8::ArrayBuffer::kInternalFieldCount);
785   for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
786     array_buffer->SetInternalField(i, Smi::FromInt(0));
787   }
788   array_buffer->set_backing_store(data);
789   array_buffer->set_flag(Smi::FromInt(0));
790   array_buffer->set_is_external(is_external);
791 
792   Handle<Object> byte_length =
793       isolate->factory()->NewNumberFromSize(allocated_length);
794   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
795   array_buffer->set_byte_length(*byte_length);
796 
797   array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
798   isolate->heap()->set_array_buffers_list(*array_buffer);
799   array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
800 }
801 
802 
SetupArrayBufferAllocatingData(Isolate * isolate,Handle<JSArrayBuffer> array_buffer,size_t allocated_length,bool initialize)803 bool Runtime::SetupArrayBufferAllocatingData(
804     Isolate* isolate,
805     Handle<JSArrayBuffer> array_buffer,
806     size_t allocated_length,
807     bool initialize) {
808   void* data;
809   CHECK(V8::ArrayBufferAllocator() != NULL);
810   if (allocated_length != 0) {
811     if (initialize) {
812       data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
813     } else {
814       data =
815           V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
816     }
817     if (data == NULL) return false;
818   } else {
819     data = NULL;
820   }
821 
822   SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
823 
824   reinterpret_cast<v8::Isolate*>(isolate)
825       ->AdjustAmountOfExternalAllocatedMemory(allocated_length);
826 
827   return true;
828 }
829 
830 
NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer)831 void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
832   Isolate* isolate = array_buffer->GetIsolate();
833   for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate);
834        !view_obj->IsUndefined();) {
835     Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj));
836     if (view->IsJSTypedArray()) {
837       JSTypedArray::cast(*view)->Neuter();
838     } else if (view->IsJSDataView()) {
839       JSDataView::cast(*view)->Neuter();
840     } else {
841       UNREACHABLE();
842     }
843     view_obj = handle(view->weak_next(), isolate);
844   }
845   array_buffer->Neuter();
846 }
847 
848 
RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize)849 RUNTIME_FUNCTION(Runtime_ArrayBufferInitialize) {
850   HandleScope scope(isolate);
851   ASSERT(args.length() == 2);
852   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
853   CONVERT_NUMBER_ARG_HANDLE_CHECKED(byteLength, 1);
854   if (!holder->byte_length()->IsUndefined()) {
855     // ArrayBuffer is already initialized; probably a fuzz test.
856     return *holder;
857   }
858   size_t allocated_length = 0;
859   if (!TryNumberToSize(isolate, *byteLength, &allocated_length)) {
860     return isolate->Throw(
861         *isolate->factory()->NewRangeError("invalid_array_buffer_length",
862                                            HandleVector<Object>(NULL, 0)));
863   }
864   if (!Runtime::SetupArrayBufferAllocatingData(isolate,
865                                                holder, allocated_length)) {
866     return isolate->Throw(
867         *isolate->factory()->NewRangeError("invalid_array_buffer_length",
868                                            HandleVector<Object>(NULL, 0)));
869   }
870   return *holder;
871 }
872 
873 
RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength)874 RUNTIME_FUNCTION(Runtime_ArrayBufferGetByteLength) {
875   SealHandleScope shs(isolate);
876   ASSERT(args.length() == 1);
877   CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
878   return holder->byte_length();
879 }
880 
881 
RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl)882 RUNTIME_FUNCTION(Runtime_ArrayBufferSliceImpl) {
883   HandleScope scope(isolate);
884   ASSERT(args.length() == 3);
885   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
886   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
887   CONVERT_NUMBER_ARG_HANDLE_CHECKED(first, 2);
888   RUNTIME_ASSERT(!source.is_identical_to(target));
889   size_t start = 0;
890   RUNTIME_ASSERT(TryNumberToSize(isolate, *first, &start));
891   size_t target_length = NumberToSize(isolate, target->byte_length());
892 
893   if (target_length == 0) return isolate->heap()->undefined_value();
894 
895   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
896   RUNTIME_ASSERT(start <= source_byte_length);
897   RUNTIME_ASSERT(source_byte_length - start >= target_length);
898   uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
899   uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
900   CopyBytes(target_data, source_data + start, target_length);
901   return isolate->heap()->undefined_value();
902 }
903 
904 
RUNTIME_FUNCTION(Runtime_ArrayBufferIsView)905 RUNTIME_FUNCTION(Runtime_ArrayBufferIsView) {
906   HandleScope scope(isolate);
907   ASSERT(args.length() == 1);
908   CONVERT_ARG_CHECKED(Object, object, 0);
909   return isolate->heap()->ToBoolean(object->IsJSArrayBufferView());
910 }
911 
912 
RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter)913 RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
914   HandleScope scope(isolate);
915   ASSERT(args.length() == 1);
916   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
917   if (array_buffer->backing_store() == NULL) {
918     CHECK(Smi::FromInt(0) == array_buffer->byte_length());
919     return isolate->heap()->undefined_value();
920   }
921   ASSERT(!array_buffer->is_external());
922   void* backing_store = array_buffer->backing_store();
923   size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
924   array_buffer->set_is_external(true);
925   Runtime::NeuterArrayBuffer(array_buffer);
926   V8::ArrayBufferAllocator()->Free(backing_store, byte_length);
927   return isolate->heap()->undefined_value();
928 }
929 
930 
ArrayIdToTypeAndSize(int arrayId,ExternalArrayType * array_type,ElementsKind * external_elements_kind,ElementsKind * fixed_elements_kind,size_t * element_size)931 void Runtime::ArrayIdToTypeAndSize(
932     int arrayId,
933     ExternalArrayType* array_type,
934     ElementsKind* external_elements_kind,
935     ElementsKind* fixed_elements_kind,
936     size_t* element_size) {
937   switch (arrayId) {
938 #define ARRAY_ID_CASE(Type, type, TYPE, ctype, size)                           \
939     case ARRAY_ID_##TYPE:                                                      \
940       *array_type = kExternal##Type##Array;                                    \
941       *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS;                    \
942       *fixed_elements_kind = TYPE##_ELEMENTS;                                  \
943       *element_size = size;                                                    \
944       break;
945 
946     TYPED_ARRAYS(ARRAY_ID_CASE)
947 #undef ARRAY_ID_CASE
948 
949     default:
950       UNREACHABLE();
951   }
952 }
953 
954 
RUNTIME_FUNCTION(Runtime_TypedArrayInitialize)955 RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
956   HandleScope scope(isolate);
957   ASSERT(args.length() == 5);
958   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
959   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
960   CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
961   CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset_object, 3);
962   CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length_object, 4);
963 
964   RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
965                  arrayId <= Runtime::ARRAY_ID_LAST);
966 
967   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
968   size_t element_size = 1;  // Bogus initialization.
969   ElementsKind external_elements_kind =
970       EXTERNAL_INT8_ELEMENTS;  // Bogus initialization.
971   ElementsKind fixed_elements_kind = INT8_ELEMENTS;  // Bogus initialization.
972   Runtime::ArrayIdToTypeAndSize(arrayId,
973       &array_type,
974       &external_elements_kind,
975       &fixed_elements_kind,
976       &element_size);
977   RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
978 
979   size_t byte_offset = 0;
980   size_t byte_length = 0;
981   RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset_object, &byte_offset));
982   RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length_object, &byte_length));
983 
984   if (maybe_buffer->IsJSArrayBuffer()) {
985     Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
986     size_t array_buffer_byte_length =
987         NumberToSize(isolate, buffer->byte_length());
988     RUNTIME_ASSERT(byte_offset <= array_buffer_byte_length);
989     RUNTIME_ASSERT(array_buffer_byte_length - byte_offset >= byte_length);
990   } else {
991     RUNTIME_ASSERT(maybe_buffer->IsNull());
992   }
993 
994   RUNTIME_ASSERT(byte_length % element_size == 0);
995   size_t length = byte_length / element_size;
996 
997   if (length > static_cast<unsigned>(Smi::kMaxValue)) {
998     return isolate->Throw(
999         *isolate->factory()->NewRangeError("invalid_typed_array_length",
1000                                            HandleVector<Object>(NULL, 0)));
1001   }
1002 
1003   // All checks are done, now we can modify objects.
1004 
1005   ASSERT(holder->GetInternalFieldCount() ==
1006       v8::ArrayBufferView::kInternalFieldCount);
1007   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1008     holder->SetInternalField(i, Smi::FromInt(0));
1009   }
1010   Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
1011   holder->set_length(*length_obj);
1012   holder->set_byte_offset(*byte_offset_object);
1013   holder->set_byte_length(*byte_length_object);
1014 
1015   if (!maybe_buffer->IsNull()) {
1016     Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
1017     holder->set_buffer(*buffer);
1018     holder->set_weak_next(buffer->weak_first_view());
1019     buffer->set_weak_first_view(*holder);
1020 
1021     Handle<ExternalArray> elements =
1022         isolate->factory()->NewExternalArray(
1023             static_cast<int>(length), array_type,
1024             static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
1025     Handle<Map> map =
1026         JSObject::GetElementsTransitionMap(holder, external_elements_kind);
1027     JSObject::SetMapAndElements(holder, map, elements);
1028     ASSERT(IsExternalArrayElementsKind(holder->map()->elements_kind()));
1029   } else {
1030     holder->set_buffer(Smi::FromInt(0));
1031     holder->set_weak_next(isolate->heap()->undefined_value());
1032     Handle<FixedTypedArrayBase> elements =
1033         isolate->factory()->NewFixedTypedArray(
1034             static_cast<int>(length), array_type);
1035     holder->set_elements(*elements);
1036   }
1037   return isolate->heap()->undefined_value();
1038 }
1039 
1040 
1041 // Initializes a typed array from an array-like object.
1042 // If an array-like object happens to be a typed array of the same type,
1043 // initializes backing store using memove.
1044 //
1045 // Returns true if backing store was initialized or false otherwise.
RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike)1046 RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
1047   HandleScope scope(isolate);
1048   ASSERT(args.length() == 4);
1049   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
1050   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
1051   CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
1052   CONVERT_NUMBER_ARG_HANDLE_CHECKED(length_obj, 3);
1053 
1054   RUNTIME_ASSERT(arrayId >= Runtime::ARRAY_ID_FIRST &&
1055                  arrayId <= Runtime::ARRAY_ID_LAST);
1056 
1057   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
1058   size_t element_size = 1;  // Bogus initialization.
1059   ElementsKind external_elements_kind =
1060       EXTERNAL_INT8_ELEMENTS;  // Bogus intialization.
1061   ElementsKind fixed_elements_kind = INT8_ELEMENTS;  // Bogus initialization.
1062   Runtime::ArrayIdToTypeAndSize(arrayId,
1063       &array_type,
1064       &external_elements_kind,
1065       &fixed_elements_kind,
1066       &element_size);
1067 
1068   RUNTIME_ASSERT(holder->map()->elements_kind() == fixed_elements_kind);
1069 
1070   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
1071   if (source->IsJSTypedArray() &&
1072       JSTypedArray::cast(*source)->type() == array_type) {
1073     length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate);
1074   }
1075   size_t length = 0;
1076   RUNTIME_ASSERT(TryNumberToSize(isolate, *length_obj, &length));
1077 
1078   if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
1079       (length > (kMaxInt / element_size))) {
1080     return isolate->Throw(*isolate->factory()->
1081           NewRangeError("invalid_typed_array_length",
1082             HandleVector<Object>(NULL, 0)));
1083   }
1084   size_t byte_length = length * element_size;
1085 
1086   ASSERT(holder->GetInternalFieldCount() ==
1087       v8::ArrayBufferView::kInternalFieldCount);
1088   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1089     holder->SetInternalField(i, Smi::FromInt(0));
1090   }
1091 
1092   // NOTE: not initializing backing store.
1093   // We assume that the caller of this function will initialize holder
1094   // with the loop
1095   //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
1096   // We assume that the caller of this function is always a typed array
1097   // constructor.
1098   // If source is a typed array, this loop will always run to completion,
1099   // so we are sure that the backing store will be initialized.
1100   // Otherwise, the indexing operation might throw, so the loop will not
1101   // run to completion and the typed array might remain partly initialized.
1102   // However we further assume that the caller of this function is a typed array
1103   // constructor, and the exception will propagate out of the constructor,
1104   // therefore uninitialized memory will not be accessible by a user program.
1105   //
1106   // TODO(dslomov): revise this once we support subclassing.
1107 
1108   if (!Runtime::SetupArrayBufferAllocatingData(
1109         isolate, buffer, byte_length, false)) {
1110     return isolate->Throw(*isolate->factory()->
1111           NewRangeError("invalid_array_buffer_length",
1112             HandleVector<Object>(NULL, 0)));
1113   }
1114 
1115   holder->set_buffer(*buffer);
1116   holder->set_byte_offset(Smi::FromInt(0));
1117   Handle<Object> byte_length_obj(
1118       isolate->factory()->NewNumberFromSize(byte_length));
1119   holder->set_byte_length(*byte_length_obj);
1120   holder->set_length(*length_obj);
1121   holder->set_weak_next(buffer->weak_first_view());
1122   buffer->set_weak_first_view(*holder);
1123 
1124   Handle<ExternalArray> elements =
1125       isolate->factory()->NewExternalArray(
1126           static_cast<int>(length), array_type,
1127           static_cast<uint8_t*>(buffer->backing_store()));
1128   Handle<Map> map = JSObject::GetElementsTransitionMap(
1129       holder, external_elements_kind);
1130   JSObject::SetMapAndElements(holder, map, elements);
1131 
1132   if (source->IsJSTypedArray()) {
1133     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
1134 
1135     if (typed_array->type() == holder->type()) {
1136       uint8_t* backing_store =
1137         static_cast<uint8_t*>(
1138           typed_array->GetBuffer()->backing_store());
1139       size_t source_byte_offset =
1140           NumberToSize(isolate, typed_array->byte_offset());
1141       memcpy(
1142           buffer->backing_store(),
1143           backing_store + source_byte_offset,
1144           byte_length);
1145       return isolate->heap()->true_value();
1146     }
1147   }
1148 
1149   return isolate->heap()->false_value();
1150 }
1151 
1152 
1153 #define BUFFER_VIEW_GETTER(Type, getter, accessor) \
1154   RUNTIME_FUNCTION(Runtime_##Type##Get##getter) {                    \
1155     HandleScope scope(isolate);                                               \
1156     ASSERT(args.length() == 1);                                               \
1157     CONVERT_ARG_HANDLE_CHECKED(JS##Type, holder, 0);                          \
1158     return holder->accessor();                                                \
1159   }
1160 
BUFFER_VIEW_GETTER(ArrayBufferView,ByteLength,byte_length)1161 BUFFER_VIEW_GETTER(ArrayBufferView, ByteLength, byte_length)
1162 BUFFER_VIEW_GETTER(ArrayBufferView, ByteOffset, byte_offset)
1163 BUFFER_VIEW_GETTER(TypedArray, Length, length)
1164 BUFFER_VIEW_GETTER(DataView, Buffer, buffer)
1165 
1166 #undef BUFFER_VIEW_GETTER
1167 
1168 RUNTIME_FUNCTION(Runtime_TypedArrayGetBuffer) {
1169   HandleScope scope(isolate);
1170   ASSERT(args.length() == 1);
1171   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
1172   return *holder->GetBuffer();
1173 }
1174 
1175 
1176 // Return codes for Runtime_TypedArraySetFastCases.
1177 // Should be synchronized with typedarray.js natives.
1178 enum TypedArraySetResultCodes {
1179   // Set from typed array of the same type.
1180   // This is processed by TypedArraySetFastCases
1181   TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
1182   // Set from typed array of the different type, overlapping in memory.
1183   TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
1184   // Set from typed array of the different type, non-overlapping.
1185   TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
1186   // Set from non-typed array.
1187   TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
1188 };
1189 
1190 
RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases)1191 RUNTIME_FUNCTION(Runtime_TypedArraySetFastCases) {
1192   HandleScope scope(isolate);
1193   ASSERT(args.length() == 3);
1194   if (!args[0]->IsJSTypedArray())
1195     return isolate->Throw(*isolate->factory()->NewTypeError(
1196         "not_typed_array", HandleVector<Object>(NULL, 0)));
1197 
1198   if (!args[1]->IsJSTypedArray())
1199     return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
1200 
1201   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, target_obj, 0);
1202   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, source_obj, 1);
1203   CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset_obj, 2);
1204 
1205   Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1206   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1207   size_t offset = 0;
1208   RUNTIME_ASSERT(TryNumberToSize(isolate, *offset_obj, &offset));
1209   size_t target_length = NumberToSize(isolate, target->length());
1210   size_t source_length = NumberToSize(isolate, source->length());
1211   size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1212   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1213   if (offset > target_length ||
1214       offset + source_length > target_length ||
1215       offset + source_length < offset)  // overflow
1216     return isolate->Throw(*isolate->factory()->NewRangeError(
1217           "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
1218 
1219   size_t target_offset = NumberToSize(isolate, target->byte_offset());
1220   size_t source_offset = NumberToSize(isolate, source->byte_offset());
1221   uint8_t* target_base =
1222       static_cast<uint8_t*>(
1223         target->GetBuffer()->backing_store()) + target_offset;
1224   uint8_t* source_base =
1225       static_cast<uint8_t*>(
1226         source->GetBuffer()->backing_store()) + source_offset;
1227 
1228   // Typed arrays of the same type: use memmove.
1229   if (target->type() == source->type()) {
1230     memmove(target_base + offset * target->element_size(),
1231         source_base, source_byte_length);
1232     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
1233   }
1234 
1235   // Typed arrays of different types over the same backing store
1236   if ((source_base <= target_base &&
1237         source_base + source_byte_length > target_base) ||
1238       (target_base <= source_base &&
1239         target_base + target_byte_length > source_base)) {
1240     // We do not support overlapping ArrayBuffers
1241     ASSERT(
1242       target->GetBuffer()->backing_store() ==
1243       source->GetBuffer()->backing_store());
1244     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
1245   } else {  // Non-overlapping typed arrays
1246     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
1247   }
1248 }
1249 
1250 
RUNTIME_FUNCTION(Runtime_TypedArrayMaxSizeInHeap)1251 RUNTIME_FUNCTION(Runtime_TypedArrayMaxSizeInHeap) {
1252   ASSERT(args.length() == 0);
1253   ASSERT_OBJECT_SIZE(
1254       FLAG_typed_array_max_size_in_heap + FixedTypedArrayBase::kDataOffset);
1255   return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
1256 }
1257 
1258 
RUNTIME_FUNCTION(Runtime_DataViewInitialize)1259 RUNTIME_FUNCTION(Runtime_DataViewInitialize) {
1260   HandleScope scope(isolate);
1261   ASSERT(args.length() == 4);
1262   CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
1263   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
1264   CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_offset, 2);
1265   CONVERT_NUMBER_ARG_HANDLE_CHECKED(byte_length, 3);
1266 
1267   ASSERT(holder->GetInternalFieldCount() ==
1268       v8::ArrayBufferView::kInternalFieldCount);
1269   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1270     holder->SetInternalField(i, Smi::FromInt(0));
1271   }
1272   size_t buffer_length = 0;
1273   size_t offset = 0;
1274   size_t length = 0;
1275   RUNTIME_ASSERT(
1276       TryNumberToSize(isolate, buffer->byte_length(), &buffer_length));
1277   RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_offset, &offset));
1278   RUNTIME_ASSERT(TryNumberToSize(isolate, *byte_length, &length));
1279 
1280   // TODO(jkummerow): When we have a "safe numerics" helper class, use it here.
1281   // Entire range [offset, offset + length] must be in bounds.
1282   RUNTIME_ASSERT(offset <= buffer_length);
1283   RUNTIME_ASSERT(offset + length <= buffer_length);
1284   // No overflow.
1285   RUNTIME_ASSERT(offset + length >= offset);
1286 
1287   holder->set_buffer(*buffer);
1288   holder->set_byte_offset(*byte_offset);
1289   holder->set_byte_length(*byte_length);
1290 
1291   holder->set_weak_next(buffer->weak_first_view());
1292   buffer->set_weak_first_view(*holder);
1293 
1294   return isolate->heap()->undefined_value();
1295 }
1296 
1297 
NeedToFlipBytes(bool is_little_endian)1298 inline static bool NeedToFlipBytes(bool is_little_endian) {
1299 #ifdef V8_TARGET_LITTLE_ENDIAN
1300   return !is_little_endian;
1301 #else
1302   return is_little_endian;
1303 #endif
1304 }
1305 
1306 
1307 template<int n>
CopyBytes(uint8_t * target,uint8_t * source)1308 inline void CopyBytes(uint8_t* target, uint8_t* source) {
1309   for (int i = 0; i < n; i++) {
1310     *(target++) = *(source++);
1311   }
1312 }
1313 
1314 
1315 template<int n>
FlipBytes(uint8_t * target,uint8_t * source)1316 inline void FlipBytes(uint8_t* target, uint8_t* source) {
1317   source = source + (n-1);
1318   for (int i = 0; i < n; i++) {
1319     *(target++) = *(source--);
1320   }
1321 }
1322 
1323 
1324 template<typename T>
DataViewGetValue(Isolate * isolate,Handle<JSDataView> data_view,Handle<Object> byte_offset_obj,bool is_little_endian,T * result)1325 inline static bool DataViewGetValue(
1326     Isolate* isolate,
1327     Handle<JSDataView> data_view,
1328     Handle<Object> byte_offset_obj,
1329     bool is_little_endian,
1330     T* result) {
1331   size_t byte_offset = 0;
1332   if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1333     return false;
1334   }
1335   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1336 
1337   size_t data_view_byte_offset =
1338       NumberToSize(isolate, data_view->byte_offset());
1339   size_t data_view_byte_length =
1340       NumberToSize(isolate, data_view->byte_length());
1341   if (byte_offset + sizeof(T) > data_view_byte_length ||
1342       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1343     return false;
1344   }
1345 
1346   union Value {
1347     T data;
1348     uint8_t bytes[sizeof(T)];
1349   };
1350 
1351   Value value;
1352   size_t buffer_offset = data_view_byte_offset + byte_offset;
1353   ASSERT(
1354       NumberToSize(isolate, buffer->byte_length())
1355       >= buffer_offset + sizeof(T));
1356   uint8_t* source =
1357         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1358   if (NeedToFlipBytes(is_little_endian)) {
1359     FlipBytes<sizeof(T)>(value.bytes, source);
1360   } else {
1361     CopyBytes<sizeof(T)>(value.bytes, source);
1362   }
1363   *result = value.data;
1364   return true;
1365 }
1366 
1367 
1368 template<typename T>
DataViewSetValue(Isolate * isolate,Handle<JSDataView> data_view,Handle<Object> byte_offset_obj,bool is_little_endian,T data)1369 static bool DataViewSetValue(
1370     Isolate* isolate,
1371     Handle<JSDataView> data_view,
1372     Handle<Object> byte_offset_obj,
1373     bool is_little_endian,
1374     T data) {
1375   size_t byte_offset = 0;
1376   if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1377     return false;
1378   }
1379   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1380 
1381   size_t data_view_byte_offset =
1382       NumberToSize(isolate, data_view->byte_offset());
1383   size_t data_view_byte_length =
1384       NumberToSize(isolate, data_view->byte_length());
1385   if (byte_offset + sizeof(T) > data_view_byte_length ||
1386       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1387     return false;
1388   }
1389 
1390   union Value {
1391     T data;
1392     uint8_t bytes[sizeof(T)];
1393   };
1394 
1395   Value value;
1396   value.data = data;
1397   size_t buffer_offset = data_view_byte_offset + byte_offset;
1398   ASSERT(
1399       NumberToSize(isolate, buffer->byte_length())
1400       >= buffer_offset + sizeof(T));
1401   uint8_t* target =
1402         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1403   if (NeedToFlipBytes(is_little_endian)) {
1404     FlipBytes<sizeof(T)>(target, value.bytes);
1405   } else {
1406     CopyBytes<sizeof(T)>(target, value.bytes);
1407   }
1408   return true;
1409 }
1410 
1411 
1412 #define DATA_VIEW_GETTER(TypeName, Type, Converter)                           \
1413   RUNTIME_FUNCTION(Runtime_DataViewGet##TypeName) {                           \
1414     HandleScope scope(isolate);                                               \
1415     ASSERT(args.length() == 3);                                               \
1416     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1417     CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1);                             \
1418     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2);                         \
1419     Type result;                                                              \
1420     if (DataViewGetValue(                                                     \
1421           isolate, holder, offset, is_little_endian, &result)) {              \
1422       return *isolate->factory()->Converter(result);                          \
1423     } else {                                                                  \
1424       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1425           "invalid_data_view_accessor_offset",                                \
1426           HandleVector<Object>(NULL, 0)));                                    \
1427     }                                                                         \
1428   }
1429 
1430 DATA_VIEW_GETTER(Uint8, uint8_t, NewNumberFromUint)
1431 DATA_VIEW_GETTER(Int8, int8_t, NewNumberFromInt)
1432 DATA_VIEW_GETTER(Uint16, uint16_t, NewNumberFromUint)
1433 DATA_VIEW_GETTER(Int16, int16_t, NewNumberFromInt)
1434 DATA_VIEW_GETTER(Uint32, uint32_t, NewNumberFromUint)
1435 DATA_VIEW_GETTER(Int32, int32_t, NewNumberFromInt)
1436 DATA_VIEW_GETTER(Float32, float, NewNumber)
1437 DATA_VIEW_GETTER(Float64, double, NewNumber)
1438 
1439 #undef DATA_VIEW_GETTER
1440 
1441 
1442 template <typename T>
1443 static T DataViewConvertValue(double value);
1444 
1445 
1446 template <>
DataViewConvertValue(double value)1447 int8_t DataViewConvertValue<int8_t>(double value) {
1448   return static_cast<int8_t>(DoubleToInt32(value));
1449 }
1450 
1451 
1452 template <>
DataViewConvertValue(double value)1453 int16_t DataViewConvertValue<int16_t>(double value) {
1454   return static_cast<int16_t>(DoubleToInt32(value));
1455 }
1456 
1457 
1458 template <>
DataViewConvertValue(double value)1459 int32_t DataViewConvertValue<int32_t>(double value) {
1460   return DoubleToInt32(value);
1461 }
1462 
1463 
1464 template <>
DataViewConvertValue(double value)1465 uint8_t DataViewConvertValue<uint8_t>(double value) {
1466   return static_cast<uint8_t>(DoubleToUint32(value));
1467 }
1468 
1469 
1470 template <>
DataViewConvertValue(double value)1471 uint16_t DataViewConvertValue<uint16_t>(double value) {
1472   return static_cast<uint16_t>(DoubleToUint32(value));
1473 }
1474 
1475 
1476 template <>
DataViewConvertValue(double value)1477 uint32_t DataViewConvertValue<uint32_t>(double value) {
1478   return DoubleToUint32(value);
1479 }
1480 
1481 
1482 template <>
DataViewConvertValue(double value)1483 float DataViewConvertValue<float>(double value) {
1484   return static_cast<float>(value);
1485 }
1486 
1487 
1488 template <>
DataViewConvertValue(double value)1489 double DataViewConvertValue<double>(double value) {
1490   return value;
1491 }
1492 
1493 
1494 #define DATA_VIEW_SETTER(TypeName, Type)                                      \
1495   RUNTIME_FUNCTION(Runtime_DataViewSet##TypeName) {                           \
1496     HandleScope scope(isolate);                                               \
1497     ASSERT(args.length() == 4);                                               \
1498     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1499     CONVERT_NUMBER_ARG_HANDLE_CHECKED(offset, 1);                             \
1500     CONVERT_NUMBER_ARG_HANDLE_CHECKED(value, 2);                              \
1501     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3);                         \
1502     Type v = DataViewConvertValue<Type>(value->Number());                     \
1503     if (DataViewSetValue(                                                     \
1504           isolate, holder, offset, is_little_endian, v)) {                    \
1505       return isolate->heap()->undefined_value();                              \
1506     } else {                                                                  \
1507       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1508           "invalid_data_view_accessor_offset",                                \
1509           HandleVector<Object>(NULL, 0)));                                    \
1510     }                                                                         \
1511   }
1512 
DATA_VIEW_SETTER(Uint8,uint8_t)1513 DATA_VIEW_SETTER(Uint8, uint8_t)
1514 DATA_VIEW_SETTER(Int8, int8_t)
1515 DATA_VIEW_SETTER(Uint16, uint16_t)
1516 DATA_VIEW_SETTER(Int16, int16_t)
1517 DATA_VIEW_SETTER(Uint32, uint32_t)
1518 DATA_VIEW_SETTER(Int32, int32_t)
1519 DATA_VIEW_SETTER(Float32, float)
1520 DATA_VIEW_SETTER(Float64, double)
1521 
1522 #undef DATA_VIEW_SETTER
1523 
1524 
1525 RUNTIME_FUNCTION(Runtime_SetInitialize) {
1526   HandleScope scope(isolate);
1527   ASSERT(args.length() == 1);
1528   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1529   Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
1530   holder->set_table(*table);
1531   return *holder;
1532 }
1533 
1534 
RUNTIME_FUNCTION(Runtime_SetAdd)1535 RUNTIME_FUNCTION(Runtime_SetAdd) {
1536   HandleScope scope(isolate);
1537   ASSERT(args.length() == 2);
1538   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1539   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1540   Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1541   table = OrderedHashSet::Add(table, key);
1542   holder->set_table(*table);
1543   return isolate->heap()->undefined_value();
1544 }
1545 
1546 
RUNTIME_FUNCTION(Runtime_SetHas)1547 RUNTIME_FUNCTION(Runtime_SetHas) {
1548   HandleScope scope(isolate);
1549   ASSERT(args.length() == 2);
1550   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1551   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1552   Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1553   return isolate->heap()->ToBoolean(table->Contains(key));
1554 }
1555 
1556 
RUNTIME_FUNCTION(Runtime_SetDelete)1557 RUNTIME_FUNCTION(Runtime_SetDelete) {
1558   HandleScope scope(isolate);
1559   ASSERT(args.length() == 2);
1560   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1561   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1562   Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1563   bool was_present = false;
1564   table = OrderedHashSet::Remove(table, key, &was_present);
1565   holder->set_table(*table);
1566   return isolate->heap()->ToBoolean(was_present);
1567 }
1568 
1569 
RUNTIME_FUNCTION(Runtime_SetClear)1570 RUNTIME_FUNCTION(Runtime_SetClear) {
1571   HandleScope scope(isolate);
1572   ASSERT(args.length() == 1);
1573   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1574   Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1575   table = OrderedHashSet::Clear(table);
1576   holder->set_table(*table);
1577   return isolate->heap()->undefined_value();
1578 }
1579 
1580 
RUNTIME_FUNCTION(Runtime_SetGetSize)1581 RUNTIME_FUNCTION(Runtime_SetGetSize) {
1582   HandleScope scope(isolate);
1583   ASSERT(args.length() == 1);
1584   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1585   Handle<OrderedHashSet> table(OrderedHashSet::cast(holder->table()));
1586   return Smi::FromInt(table->NumberOfElements());
1587 }
1588 
1589 
RUNTIME_FUNCTION(Runtime_SetIteratorInitialize)1590 RUNTIME_FUNCTION(Runtime_SetIteratorInitialize) {
1591   HandleScope scope(isolate);
1592   ASSERT(args.length() == 3);
1593   CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
1594   CONVERT_ARG_HANDLE_CHECKED(JSSet, set, 1);
1595   CONVERT_SMI_ARG_CHECKED(kind, 2)
1596   RUNTIME_ASSERT(kind == JSSetIterator::kKindValues ||
1597                  kind == JSSetIterator::kKindEntries);
1598   Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
1599   holder->set_table(*table);
1600   holder->set_index(Smi::FromInt(0));
1601   holder->set_kind(Smi::FromInt(kind));
1602   return isolate->heap()->undefined_value();
1603 }
1604 
1605 
RUNTIME_FUNCTION(Runtime_SetIteratorNext)1606 RUNTIME_FUNCTION(Runtime_SetIteratorNext) {
1607   HandleScope scope(isolate);
1608   ASSERT(args.length() == 1);
1609   CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
1610   return *JSSetIterator::Next(holder);
1611 }
1612 
1613 
RUNTIME_FUNCTION(Runtime_MapInitialize)1614 RUNTIME_FUNCTION(Runtime_MapInitialize) {
1615   HandleScope scope(isolate);
1616   ASSERT(args.length() == 1);
1617   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1618   Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
1619   holder->set_table(*table);
1620   return *holder;
1621 }
1622 
1623 
RUNTIME_FUNCTION(Runtime_MapGet)1624 RUNTIME_FUNCTION(Runtime_MapGet) {
1625   HandleScope scope(isolate);
1626   ASSERT(args.length() == 2);
1627   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1628   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1629   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1630   Handle<Object> lookup(table->Lookup(key), isolate);
1631   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1632 }
1633 
1634 
RUNTIME_FUNCTION(Runtime_MapHas)1635 RUNTIME_FUNCTION(Runtime_MapHas) {
1636   HandleScope scope(isolate);
1637   ASSERT(args.length() == 2);
1638   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1639   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1640   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1641   Handle<Object> lookup(table->Lookup(key), isolate);
1642   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1643 }
1644 
1645 
RUNTIME_FUNCTION(Runtime_MapDelete)1646 RUNTIME_FUNCTION(Runtime_MapDelete) {
1647   HandleScope scope(isolate);
1648   ASSERT(args.length() == 2);
1649   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1650   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1651   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1652   bool was_present = false;
1653   Handle<OrderedHashMap> new_table =
1654       OrderedHashMap::Remove(table, key, &was_present);
1655   holder->set_table(*new_table);
1656   return isolate->heap()->ToBoolean(was_present);
1657 }
1658 
1659 
RUNTIME_FUNCTION(Runtime_MapClear)1660 RUNTIME_FUNCTION(Runtime_MapClear) {
1661   HandleScope scope(isolate);
1662   ASSERT(args.length() == 1);
1663   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1664   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1665   table = OrderedHashMap::Clear(table);
1666   holder->set_table(*table);
1667   return isolate->heap()->undefined_value();
1668 }
1669 
1670 
RUNTIME_FUNCTION(Runtime_MapSet)1671 RUNTIME_FUNCTION(Runtime_MapSet) {
1672   HandleScope scope(isolate);
1673   ASSERT(args.length() == 3);
1674   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1675   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1676   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1677   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1678   Handle<OrderedHashMap> new_table = OrderedHashMap::Put(table, key, value);
1679   holder->set_table(*new_table);
1680   return isolate->heap()->undefined_value();
1681 }
1682 
1683 
RUNTIME_FUNCTION(Runtime_MapGetSize)1684 RUNTIME_FUNCTION(Runtime_MapGetSize) {
1685   HandleScope scope(isolate);
1686   ASSERT(args.length() == 1);
1687   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1688   Handle<OrderedHashMap> table(OrderedHashMap::cast(holder->table()));
1689   return Smi::FromInt(table->NumberOfElements());
1690 }
1691 
1692 
RUNTIME_FUNCTION(Runtime_MapIteratorInitialize)1693 RUNTIME_FUNCTION(Runtime_MapIteratorInitialize) {
1694   HandleScope scope(isolate);
1695   ASSERT(args.length() == 3);
1696   CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
1697   CONVERT_ARG_HANDLE_CHECKED(JSMap, map, 1);
1698   CONVERT_SMI_ARG_CHECKED(kind, 2)
1699   RUNTIME_ASSERT(kind == JSMapIterator::kKindKeys
1700       || kind == JSMapIterator::kKindValues
1701       || kind == JSMapIterator::kKindEntries);
1702   Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
1703   holder->set_table(*table);
1704   holder->set_index(Smi::FromInt(0));
1705   holder->set_kind(Smi::FromInt(kind));
1706   return isolate->heap()->undefined_value();
1707 }
1708 
1709 
RUNTIME_FUNCTION(Runtime_MapIteratorNext)1710 RUNTIME_FUNCTION(Runtime_MapIteratorNext) {
1711   HandleScope scope(isolate);
1712   ASSERT(args.length() == 1);
1713   CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
1714   return *JSMapIterator::Next(holder);
1715 }
1716 
1717 
WeakCollectionInitialize(Isolate * isolate,Handle<JSWeakCollection> weak_collection)1718 static Handle<JSWeakCollection> WeakCollectionInitialize(
1719     Isolate* isolate,
1720     Handle<JSWeakCollection> weak_collection) {
1721   ASSERT(weak_collection->map()->inobject_properties() == 0);
1722   Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
1723   weak_collection->set_table(*table);
1724   return weak_collection;
1725 }
1726 
1727 
RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize)1728 RUNTIME_FUNCTION(Runtime_WeakCollectionInitialize) {
1729   HandleScope scope(isolate);
1730   ASSERT(args.length() == 1);
1731   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1732   return *WeakCollectionInitialize(isolate, weak_collection);
1733 }
1734 
1735 
RUNTIME_FUNCTION(Runtime_WeakCollectionGet)1736 RUNTIME_FUNCTION(Runtime_WeakCollectionGet) {
1737   HandleScope scope(isolate);
1738   ASSERT(args.length() == 2);
1739   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1740   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1741   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1742   Handle<ObjectHashTable> table(
1743       ObjectHashTable::cast(weak_collection->table()));
1744   RUNTIME_ASSERT(table->IsKey(*key));
1745   Handle<Object> lookup(table->Lookup(key), isolate);
1746   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1747 }
1748 
1749 
RUNTIME_FUNCTION(Runtime_WeakCollectionHas)1750 RUNTIME_FUNCTION(Runtime_WeakCollectionHas) {
1751   HandleScope scope(isolate);
1752   ASSERT(args.length() == 2);
1753   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1754   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1755   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1756   Handle<ObjectHashTable> table(
1757       ObjectHashTable::cast(weak_collection->table()));
1758   RUNTIME_ASSERT(table->IsKey(*key));
1759   Handle<Object> lookup(table->Lookup(key), isolate);
1760   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1761 }
1762 
1763 
RUNTIME_FUNCTION(Runtime_WeakCollectionDelete)1764 RUNTIME_FUNCTION(Runtime_WeakCollectionDelete) {
1765   HandleScope scope(isolate);
1766   ASSERT(args.length() == 2);
1767   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1768   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1769   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1770   Handle<ObjectHashTable> table(ObjectHashTable::cast(
1771       weak_collection->table()));
1772   RUNTIME_ASSERT(table->IsKey(*key));
1773   bool was_present = false;
1774   Handle<ObjectHashTable> new_table =
1775       ObjectHashTable::Remove(table, key, &was_present);
1776   weak_collection->set_table(*new_table);
1777   return isolate->heap()->ToBoolean(was_present);
1778 }
1779 
1780 
RUNTIME_FUNCTION(Runtime_WeakCollectionSet)1781 RUNTIME_FUNCTION(Runtime_WeakCollectionSet) {
1782   HandleScope scope(isolate);
1783   ASSERT(args.length() == 3);
1784   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1785   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1786   RUNTIME_ASSERT(key->IsJSReceiver() || key->IsSymbol());
1787   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1788   Handle<ObjectHashTable> table(
1789       ObjectHashTable::cast(weak_collection->table()));
1790   RUNTIME_ASSERT(table->IsKey(*key));
1791   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1792   weak_collection->set_table(*new_table);
1793   return isolate->heap()->undefined_value();
1794 }
1795 
1796 
RUNTIME_FUNCTION(Runtime_ClassOf)1797 RUNTIME_FUNCTION(Runtime_ClassOf) {
1798   SealHandleScope shs(isolate);
1799   ASSERT(args.length() == 1);
1800   CONVERT_ARG_CHECKED(Object, obj, 0);
1801   if (!obj->IsJSObject()) return isolate->heap()->null_value();
1802   return JSObject::cast(obj)->class_name();
1803 }
1804 
1805 
RUNTIME_FUNCTION(Runtime_GetPrototype)1806 RUNTIME_FUNCTION(Runtime_GetPrototype) {
1807   HandleScope scope(isolate);
1808   ASSERT(args.length() == 1);
1809   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
1810   // We don't expect access checks to be needed on JSProxy objects.
1811   ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1812   do {
1813     if (obj->IsAccessCheckNeeded() &&
1814         !isolate->MayNamedAccess(Handle<JSObject>::cast(obj),
1815                                  isolate->factory()->proto_string(),
1816                                  v8::ACCESS_GET)) {
1817       isolate->ReportFailedAccessCheck(Handle<JSObject>::cast(obj),
1818                                        v8::ACCESS_GET);
1819       RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1820       return isolate->heap()->undefined_value();
1821     }
1822     obj = Object::GetPrototype(isolate, obj);
1823   } while (obj->IsJSObject() &&
1824            JSObject::cast(*obj)->map()->is_hidden_prototype());
1825   return *obj;
1826 }
1827 
1828 
GetPrototypeSkipHiddenPrototypes(Isolate * isolate,Handle<Object> receiver)1829 static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
1830     Isolate* isolate, Handle<Object> receiver) {
1831   Handle<Object> current = Object::GetPrototype(isolate, receiver);
1832   while (current->IsJSObject() &&
1833          JSObject::cast(*current)->map()->is_hidden_prototype()) {
1834     current = Object::GetPrototype(isolate, current);
1835   }
1836   return current;
1837 }
1838 
1839 
RUNTIME_FUNCTION(Runtime_SetPrototype)1840 RUNTIME_FUNCTION(Runtime_SetPrototype) {
1841   HandleScope scope(isolate);
1842   ASSERT(args.length() == 2);
1843   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1844   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1845   if (obj->IsAccessCheckNeeded() &&
1846       !isolate->MayNamedAccess(
1847           obj, isolate->factory()->proto_string(), v8::ACCESS_SET)) {
1848     isolate->ReportFailedAccessCheck(obj, v8::ACCESS_SET);
1849     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1850     return isolate->heap()->undefined_value();
1851   }
1852   if (obj->map()->is_observed()) {
1853     Handle<Object> old_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
1854     Handle<Object> result;
1855     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1856         isolate, result,
1857         JSObject::SetPrototype(obj, prototype, true));
1858 
1859     Handle<Object> new_value = GetPrototypeSkipHiddenPrototypes(isolate, obj);
1860     if (!new_value->SameValue(*old_value)) {
1861       JSObject::EnqueueChangeRecord(obj, "setPrototype",
1862                                     isolate->factory()->proto_string(),
1863                                     old_value);
1864     }
1865     return *result;
1866   }
1867   Handle<Object> result;
1868   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1869       isolate, result,
1870       JSObject::SetPrototype(obj, prototype, true));
1871   return *result;
1872 }
1873 
1874 
RUNTIME_FUNCTION(Runtime_IsInPrototypeChain)1875 RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
1876   HandleScope shs(isolate);
1877   ASSERT(args.length() == 2);
1878   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1879   CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
1880   CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
1881   while (true) {
1882     Handle<Object> prototype = Object::GetPrototype(isolate, V);
1883     if (prototype->IsNull()) return isolate->heap()->false_value();
1884     if (*O == *prototype) return isolate->heap()->true_value();
1885     V = prototype;
1886   }
1887 }
1888 
1889 
CheckAccessException(Object * callback,v8::AccessType access_type)1890 static bool CheckAccessException(Object* callback,
1891                                  v8::AccessType access_type) {
1892   DisallowHeapAllocation no_gc;
1893   ASSERT(!callback->IsForeign());
1894   if (callback->IsAccessorInfo()) {
1895     AccessorInfo* info = AccessorInfo::cast(callback);
1896     return
1897         (access_type == v8::ACCESS_HAS &&
1898            (info->all_can_read() || info->all_can_write())) ||
1899         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1900         (access_type == v8::ACCESS_SET && info->all_can_write());
1901   }
1902   if (callback->IsAccessorPair()) {
1903     AccessorPair* info = AccessorPair::cast(callback);
1904     return
1905         (access_type == v8::ACCESS_HAS &&
1906            (info->all_can_read() || info->all_can_write())) ||
1907         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1908         (access_type == v8::ACCESS_SET && info->all_can_write());
1909   }
1910   return false;
1911 }
1912 
1913 
1914 template<class Key>
CheckGenericAccess(Handle<JSObject> receiver,Handle<JSObject> holder,Key key,v8::AccessType access_type,bool (Isolate::* mayAccess)(Handle<JSObject>,Key,v8::AccessType))1915 static bool CheckGenericAccess(
1916     Handle<JSObject> receiver,
1917     Handle<JSObject> holder,
1918     Key key,
1919     v8::AccessType access_type,
1920     bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) {
1921   Isolate* isolate = receiver->GetIsolate();
1922   for (Handle<JSObject> current = receiver;
1923        true;
1924        current = handle(JSObject::cast(current->GetPrototype()), isolate)) {
1925     if (current->IsAccessCheckNeeded() &&
1926         !(isolate->*mayAccess)(current, key, access_type)) {
1927       return false;
1928     }
1929     if (current.is_identical_to(holder)) break;
1930   }
1931   return true;
1932 }
1933 
1934 
1935 enum AccessCheckResult {
1936   ACCESS_FORBIDDEN,
1937   ACCESS_ALLOWED,
1938   ACCESS_ABSENT
1939 };
1940 
1941 
CheckPropertyAccess(Handle<JSObject> obj,Handle<Name> name,v8::AccessType access_type)1942 static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
1943                                              Handle<Name> name,
1944                                              v8::AccessType access_type) {
1945   uint32_t index;
1946   if (name->AsArrayIndex(&index)) {
1947     // TODO(1095): we should traverse hidden prototype hierachy as well.
1948     if (CheckGenericAccess(
1949             obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
1950       return ACCESS_ALLOWED;
1951     }
1952 
1953     obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
1954     return ACCESS_FORBIDDEN;
1955   }
1956 
1957   Isolate* isolate = obj->GetIsolate();
1958   LookupResult lookup(isolate);
1959   obj->LookupOwn(name, &lookup, true);
1960 
1961   if (!lookup.IsProperty()) return ACCESS_ABSENT;
1962   Handle<JSObject> holder(lookup.holder(), isolate);
1963   if (CheckGenericAccess<Handle<Object> >(
1964           obj, holder, name, access_type, &Isolate::MayNamedAccess)) {
1965     return ACCESS_ALLOWED;
1966   }
1967 
1968   // Access check callback denied the access, but some properties
1969   // can have a special permissions which override callbacks descision
1970   // (currently see v8::AccessControl).
1971   // API callbacks can have per callback access exceptions.
1972   switch (lookup.type()) {
1973     case CALLBACKS:
1974       if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1975         return ACCESS_ALLOWED;
1976       }
1977       break;
1978     case INTERCEPTOR:
1979       // If the object has an interceptor, try real named properties.
1980       // Overwrite the result to fetch the correct property later.
1981       holder->LookupRealNamedProperty(name, &lookup);
1982       if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1983         if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1984           return ACCESS_ALLOWED;
1985         }
1986       }
1987       break;
1988     default:
1989       break;
1990   }
1991 
1992   isolate->ReportFailedAccessCheck(obj, access_type);
1993   return ACCESS_FORBIDDEN;
1994 }
1995 
1996 
1997 // Enumerator used as indices into the array returned from GetOwnProperty
1998 enum PropertyDescriptorIndices {
1999   IS_ACCESSOR_INDEX,
2000   VALUE_INDEX,
2001   GETTER_INDEX,
2002   SETTER_INDEX,
2003   WRITABLE_INDEX,
2004   ENUMERABLE_INDEX,
2005   CONFIGURABLE_INDEX,
2006   DESCRIPTOR_SIZE
2007 };
2008 
2009 
GetOwnProperty(Isolate * isolate,Handle<JSObject> obj,Handle<Name> name)2010 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
2011                                                           Handle<JSObject> obj,
2012                                                           Handle<Name> name) {
2013   Heap* heap = isolate->heap();
2014   Factory* factory = isolate->factory();
2015   // Due to some WebKit tests, we want to make sure that we do not log
2016   // more than one access failure here.
2017   AccessCheckResult access_check_result =
2018       CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
2019   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
2020   switch (access_check_result) {
2021     case ACCESS_FORBIDDEN: return factory->false_value();
2022     case ACCESS_ALLOWED: break;
2023     case ACCESS_ABSENT: return factory->undefined_value();
2024   }
2025 
2026   PropertyAttributes attrs = JSReceiver::GetOwnPropertyAttributes(obj, name);
2027   if (attrs == ABSENT) {
2028     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
2029     return factory->undefined_value();
2030   }
2031   ASSERT(!isolate->has_scheduled_exception());
2032   Handle<AccessorPair> accessors;
2033   bool has_accessors =
2034       JSObject::GetOwnPropertyAccessorPair(obj, name).ToHandle(&accessors);
2035   Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
2036   elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
2037   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
2038   elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(has_accessors));
2039 
2040   if (!has_accessors) {
2041     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
2042     // Runtime::GetObjectProperty does access check.
2043     Handle<Object> value;
2044     ASSIGN_RETURN_ON_EXCEPTION(
2045         isolate, value, Runtime::GetObjectProperty(isolate, obj, name),
2046         Object);
2047     elms->set(VALUE_INDEX, *value);
2048   } else {
2049     // Access checks are performed for both accessors separately.
2050     // When they fail, the respective field is not set in the descriptor.
2051     Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
2052     Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
2053 
2054     if (!getter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_GET)) {
2055       ASSERT(!isolate->has_scheduled_exception());
2056       elms->set(GETTER_INDEX, *getter);
2057     } else {
2058       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
2059     }
2060 
2061     if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) {
2062       ASSERT(!isolate->has_scheduled_exception());
2063       elms->set(SETTER_INDEX, *setter);
2064     } else {
2065       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
2066     }
2067   }
2068 
2069   return isolate->factory()->NewJSArrayWithElements(elms);
2070 }
2071 
2072 
2073 // Returns an array with the property description:
2074 //  if args[1] is not a property on args[0]
2075 //          returns undefined
2076 //  if args[1] is a data property on args[0]
2077 //         [false, value, Writeable, Enumerable, Configurable]
2078 //  if args[1] is an accessor on args[0]
2079 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
RUNTIME_FUNCTION(Runtime_GetOwnProperty)2080 RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
2081   HandleScope scope(isolate);
2082   ASSERT(args.length() == 2);
2083   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
2084   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2085   Handle<Object> result;
2086   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2087       isolate, result, GetOwnProperty(isolate, obj, name));
2088   return *result;
2089 }
2090 
2091 
RUNTIME_FUNCTION(Runtime_PreventExtensions)2092 RUNTIME_FUNCTION(Runtime_PreventExtensions) {
2093   HandleScope scope(isolate);
2094   ASSERT(args.length() == 1);
2095   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
2096   Handle<Object> result;
2097   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2098       isolate, result, JSObject::PreventExtensions(obj));
2099   return *result;
2100 }
2101 
2102 
RUNTIME_FUNCTION(Runtime_IsExtensible)2103 RUNTIME_FUNCTION(Runtime_IsExtensible) {
2104   SealHandleScope shs(isolate);
2105   ASSERT(args.length() == 1);
2106   CONVERT_ARG_CHECKED(JSObject, obj, 0);
2107   if (obj->IsJSGlobalProxy()) {
2108     Object* proto = obj->GetPrototype();
2109     if (proto->IsNull()) return isolate->heap()->false_value();
2110     ASSERT(proto->IsJSGlobalObject());
2111     obj = JSObject::cast(proto);
2112   }
2113   return isolate->heap()->ToBoolean(obj->map()->is_extensible());
2114 }
2115 
2116 
RUNTIME_FUNCTION(Runtime_RegExpCompile)2117 RUNTIME_FUNCTION(Runtime_RegExpCompile) {
2118   HandleScope scope(isolate);
2119   ASSERT(args.length() == 3);
2120   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
2121   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
2122   CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
2123   Handle<Object> result;
2124   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2125       isolate, result, RegExpImpl::Compile(re, pattern, flags));
2126   return *result;
2127 }
2128 
2129 
RUNTIME_FUNCTION(Runtime_CreateApiFunction)2130 RUNTIME_FUNCTION(Runtime_CreateApiFunction) {
2131   HandleScope scope(isolate);
2132   ASSERT(args.length() == 2);
2133   CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
2134   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
2135   return *isolate->factory()->CreateApiFunction(data, prototype);
2136 }
2137 
2138 
RUNTIME_FUNCTION(Runtime_IsTemplate)2139 RUNTIME_FUNCTION(Runtime_IsTemplate) {
2140   SealHandleScope shs(isolate);
2141   ASSERT(args.length() == 1);
2142   CONVERT_ARG_HANDLE_CHECKED(Object, arg, 0);
2143   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
2144   return isolate->heap()->ToBoolean(result);
2145 }
2146 
2147 
RUNTIME_FUNCTION(Runtime_GetTemplateField)2148 RUNTIME_FUNCTION(Runtime_GetTemplateField) {
2149   SealHandleScope shs(isolate);
2150   ASSERT(args.length() == 2);
2151   CONVERT_ARG_CHECKED(HeapObject, templ, 0);
2152   CONVERT_SMI_ARG_CHECKED(index, 1);
2153   int offset = index * kPointerSize + HeapObject::kHeaderSize;
2154   InstanceType type = templ->map()->instance_type();
2155   RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
2156                  type == OBJECT_TEMPLATE_INFO_TYPE);
2157   RUNTIME_ASSERT(offset > 0);
2158   if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
2159     RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
2160   } else {
2161     RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
2162   }
2163   return *HeapObject::RawField(templ, offset);
2164 }
2165 
2166 
RUNTIME_FUNCTION(Runtime_DisableAccessChecks)2167 RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
2168   HandleScope scope(isolate);
2169   ASSERT(args.length() == 1);
2170   CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
2171   Handle<Map> old_map(object->map());
2172   bool needs_access_checks = old_map->is_access_check_needed();
2173   if (needs_access_checks) {
2174     // Copy map so it won't interfere constructor's initial map.
2175     Handle<Map> new_map = Map::Copy(old_map);
2176     new_map->set_is_access_check_needed(false);
2177     if (object->IsJSObject()) {
2178       JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
2179     } else {
2180       object->set_map(*new_map);
2181     }
2182   }
2183   return isolate->heap()->ToBoolean(needs_access_checks);
2184 }
2185 
2186 
RUNTIME_FUNCTION(Runtime_EnableAccessChecks)2187 RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
2188   HandleScope scope(isolate);
2189   ASSERT(args.length() == 1);
2190   CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
2191   Handle<Map> old_map(object->map());
2192   if (!old_map->is_access_check_needed()) {
2193     // Copy map so it won't interfere constructor's initial map.
2194     Handle<Map> new_map = Map::Copy(old_map);
2195     new_map->set_is_access_check_needed(true);
2196     if (object->IsJSObject()) {
2197       JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
2198     } else {
2199       object->set_map(*new_map);
2200     }
2201   }
2202   return isolate->heap()->undefined_value();
2203 }
2204 
2205 
2206 // Transform getter or setter into something DefineAccessor can handle.
InstantiateAccessorComponent(Isolate * isolate,Handle<Object> component)2207 static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
2208                                                    Handle<Object> component) {
2209   if (component->IsUndefined()) return isolate->factory()->null_value();
2210   Handle<FunctionTemplateInfo> info =
2211       Handle<FunctionTemplateInfo>::cast(component);
2212   return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
2213 }
2214 
2215 
RUNTIME_FUNCTION(Runtime_SetAccessorProperty)2216 RUNTIME_FUNCTION(Runtime_SetAccessorProperty) {
2217   HandleScope scope(isolate);
2218   ASSERT(args.length() == 6);
2219   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2220   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2221   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
2222   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
2223   CONVERT_SMI_ARG_CHECKED(attribute, 4);
2224   CONVERT_SMI_ARG_CHECKED(access_control, 5);
2225   RUNTIME_ASSERT(getter->IsUndefined() || getter->IsFunctionTemplateInfo());
2226   RUNTIME_ASSERT(setter->IsUndefined() || setter->IsFunctionTemplateInfo());
2227   RUNTIME_ASSERT(PropertyDetails::AttributesField::is_valid(
2228       static_cast<PropertyAttributes>(attribute)));
2229   JSObject::DefineAccessor(object,
2230                            name,
2231                            InstantiateAccessorComponent(isolate, getter),
2232                            InstantiateAccessorComponent(isolate, setter),
2233                            static_cast<PropertyAttributes>(attribute),
2234                            static_cast<v8::AccessControl>(access_control));
2235   return isolate->heap()->undefined_value();
2236 }
2237 
2238 
ThrowRedeclarationError(Isolate * isolate,Handle<String> name)2239 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
2240   HandleScope scope(isolate);
2241   Handle<Object> args[1] = { name };
2242   Handle<Object> error = isolate->factory()->NewTypeError(
2243       "var_redeclaration", HandleVector(args, 1));
2244   return isolate->Throw(*error);
2245 }
2246 
2247 
RUNTIME_FUNCTION(RuntimeHidden_DeclareGlobals)2248 RUNTIME_FUNCTION(RuntimeHidden_DeclareGlobals) {
2249   HandleScope scope(isolate);
2250   ASSERT(args.length() == 3);
2251   Handle<GlobalObject> global = Handle<GlobalObject>(
2252       isolate->context()->global_object());
2253 
2254   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
2255   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
2256   CONVERT_SMI_ARG_CHECKED(flags, 2);
2257 
2258   // Traverse the name/value pairs and set the properties.
2259   int length = pairs->length();
2260   for (int i = 0; i < length; i += 2) {
2261     HandleScope scope(isolate);
2262     Handle<String> name(String::cast(pairs->get(i)));
2263     Handle<Object> value(pairs->get(i + 1), isolate);
2264 
2265     // We have to declare a global const property. To capture we only
2266     // assign to it when evaluating the assignment for "const x =
2267     // <expr>" the initial value is the hole.
2268     bool is_var = value->IsUndefined();
2269     bool is_const = value->IsTheHole();
2270     bool is_function = value->IsSharedFunctionInfo();
2271     ASSERT(is_var + is_const + is_function == 1);
2272 
2273     if (is_var || is_const) {
2274       // Lookup the property in the global object, and don't set the
2275       // value of the variable if the property is already there.
2276       // Do the lookup own properties only, see ES5 erratum.
2277       LookupResult lookup(isolate);
2278       global->LookupOwn(name, &lookup, true);
2279       if (lookup.IsFound()) {
2280         // We found an existing property. Unless it was an interceptor
2281         // that claims the property is absent, skip this declaration.
2282         if (!lookup.IsInterceptor()) continue;
2283         if (JSReceiver::GetPropertyAttributes(global, name) != ABSENT) continue;
2284         // Fall-through and introduce the absent property by using
2285         // SetProperty.
2286       }
2287     } else if (is_function) {
2288       // Copy the function and update its context. Use it as value.
2289       Handle<SharedFunctionInfo> shared =
2290           Handle<SharedFunctionInfo>::cast(value);
2291       Handle<JSFunction> function =
2292           isolate->factory()->NewFunctionFromSharedFunctionInfo(
2293               shared, context, TENURED);
2294       value = function;
2295     }
2296 
2297     LookupResult lookup(isolate);
2298     global->LookupOwn(name, &lookup, true);
2299 
2300     // Compute the property attributes. According to ECMA-262,
2301     // the property must be non-configurable except in eval.
2302     int attr = NONE;
2303     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2304     if (!is_eval) {
2305       attr |= DONT_DELETE;
2306     }
2307     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2308     if (is_const || (is_native && is_function)) {
2309       attr |= READ_ONLY;
2310     }
2311 
2312     StrictMode strict_mode = DeclareGlobalsStrictMode::decode(flags);
2313 
2314     if (!lookup.IsFound() || is_function) {
2315       // If the own property exists, check that we can reconfigure it
2316       // as required for function declarations.
2317       if (lookup.IsFound() && lookup.IsDontDelete()) {
2318         if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2319             lookup.IsPropertyCallbacks()) {
2320           return ThrowRedeclarationError(isolate, name);
2321         }
2322         // If the existing property is not configurable, keep its attributes.
2323         attr = lookup.GetAttributes();
2324       }
2325       // Define or redefine own property.
2326       RETURN_FAILURE_ON_EXCEPTION(isolate,
2327           JSObject::SetOwnPropertyIgnoreAttributes(
2328               global, name, value, static_cast<PropertyAttributes>(attr)));
2329     } else {
2330       // Do a [[Put]] on the existing (own) property.
2331       RETURN_FAILURE_ON_EXCEPTION(
2332           isolate,
2333           JSObject::SetProperty(
2334               global, name, value, static_cast<PropertyAttributes>(attr),
2335               strict_mode));
2336     }
2337   }
2338 
2339   ASSERT(!isolate->has_pending_exception());
2340   return isolate->heap()->undefined_value();
2341 }
2342 
2343 
RUNTIME_FUNCTION(RuntimeHidden_DeclareContextSlot)2344 RUNTIME_FUNCTION(RuntimeHidden_DeclareContextSlot) {
2345   HandleScope scope(isolate);
2346   ASSERT(args.length() == 4);
2347 
2348   // Declarations are always made in a function or native context.  In the
2349   // case of eval code, the context passed is the context of the caller,
2350   // which may be some nested context and not the declaration context.
2351   CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
2352   Handle<Context> context(context_arg->declaration_context());
2353   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
2354   CONVERT_SMI_ARG_CHECKED(mode_arg, 2);
2355   PropertyAttributes mode = static_cast<PropertyAttributes>(mode_arg);
2356   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2357   CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
2358 
2359   int index;
2360   PropertyAttributes attributes;
2361   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2362   BindingFlags binding_flags;
2363   Handle<Object> holder =
2364       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2365 
2366   if (attributes != ABSENT) {
2367     // The name was declared before; check for conflicting re-declarations.
2368     // Note: this is actually inconsistent with what happens for globals (where
2369     // we silently ignore such declarations).
2370     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2371       // Functions are not read-only.
2372       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2373       return ThrowRedeclarationError(isolate, name);
2374     }
2375 
2376     // Initialize it if necessary.
2377     if (*initial_value != NULL) {
2378       if (index >= 0) {
2379         ASSERT(holder.is_identical_to(context));
2380         if (((attributes & READ_ONLY) == 0) ||
2381             context->get(index)->IsTheHole()) {
2382           context->set(index, *initial_value);
2383         }
2384       } else {
2385         // Slow case: The property is in the context extension object of a
2386         // function context or the global object of a native context.
2387         Handle<JSObject> object = Handle<JSObject>::cast(holder);
2388         RETURN_FAILURE_ON_EXCEPTION(
2389             isolate,
2390             JSReceiver::SetProperty(object, name, initial_value, mode, SLOPPY));
2391       }
2392     }
2393 
2394   } else {
2395     // The property is not in the function context. It needs to be
2396     // "declared" in the function context's extension context or as a
2397     // property of the the global object.
2398     Handle<JSObject> object;
2399     if (context->has_extension()) {
2400       object = Handle<JSObject>(JSObject::cast(context->extension()));
2401     } else {
2402       // Context extension objects are allocated lazily.
2403       ASSERT(context->IsFunctionContext());
2404       object = isolate->factory()->NewJSObject(
2405           isolate->context_extension_function());
2406       context->set_extension(*object);
2407     }
2408     ASSERT(*object != NULL);
2409 
2410     // Declare the property by setting it to the initial value if provided,
2411     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2412     // constant declarations).
2413     ASSERT(!JSReceiver::HasOwnProperty(object, name));
2414     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2415     if (*initial_value != NULL) value = initial_value;
2416     // Declaring a const context slot is a conflicting declaration if
2417     // there is a callback with that name in a prototype. It is
2418     // allowed to introduce const variables in
2419     // JSContextExtensionObjects. They are treated specially in
2420     // SetProperty and no setters are invoked for those since they are
2421     // not real JSObjects.
2422     if (initial_value->IsTheHole() &&
2423         !object->IsJSContextExtensionObject()) {
2424       LookupResult lookup(isolate);
2425       object->Lookup(name, &lookup);
2426       if (lookup.IsPropertyCallbacks()) {
2427         return ThrowRedeclarationError(isolate, name);
2428       }
2429     }
2430     if (object->IsJSGlobalObject()) {
2431       // Define own property on the global object.
2432       RETURN_FAILURE_ON_EXCEPTION(isolate,
2433          JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, mode));
2434     } else {
2435       RETURN_FAILURE_ON_EXCEPTION(isolate,
2436          JSReceiver::SetProperty(object, name, value, mode, SLOPPY));
2437     }
2438   }
2439 
2440   return isolate->heap()->undefined_value();
2441 }
2442 
2443 
RUNTIME_FUNCTION(Runtime_InitializeVarGlobal)2444 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
2445   HandleScope scope(isolate);
2446   // args[0] == name
2447   // args[1] == language_mode
2448   // args[2] == value (optional)
2449 
2450   // Determine if we need to assign to the variable if it already
2451   // exists (based on the number of arguments).
2452   RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
2453   bool assign = args.length() == 3;
2454 
2455   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2456   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
2457 
2458   // According to ECMA-262, section 12.2, page 62, the property must
2459   // not be deletable.
2460   PropertyAttributes attributes = DONT_DELETE;
2461 
2462   // Lookup the property as own on the global object. If it isn't
2463   // there, there is a property with this name in the prototype chain.
2464   // We follow Safari and Firefox behavior and only set the property
2465   // if there is an explicit initialization value that we have
2466   // to assign to the property.
2467   // Note that objects can have hidden prototypes, so we need to traverse
2468   // the whole chain of hidden prototypes to do an 'own' lookup.
2469   LookupResult lookup(isolate);
2470   isolate->context()->global_object()->LookupOwn(name, &lookup, true);
2471   if (lookup.IsInterceptor()) {
2472     Handle<JSObject> holder(lookup.holder());
2473     PropertyAttributes intercepted =
2474         JSReceiver::GetPropertyAttributes(holder, name);
2475     if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2476       // Found an interceptor that's not read only.
2477       if (assign) {
2478         CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2479         Handle<Object> result;
2480         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2481             isolate, result,
2482             JSObject::SetPropertyForResult(
2483                 holder, &lookup, name, value, attributes, strict_mode));
2484         return *result;
2485       } else {
2486         return isolate->heap()->undefined_value();
2487       }
2488     }
2489   }
2490 
2491   if (assign) {
2492     CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2493     Handle<GlobalObject> global(isolate->context()->global_object());
2494     Handle<Object> result;
2495     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2496         isolate, result,
2497         JSReceiver::SetProperty(global, name, value, attributes, strict_mode));
2498     return *result;
2499   }
2500   return isolate->heap()->undefined_value();
2501 }
2502 
2503 
RUNTIME_FUNCTION(RuntimeHidden_InitializeConstGlobal)2504 RUNTIME_FUNCTION(RuntimeHidden_InitializeConstGlobal) {
2505   SealHandleScope shs(isolate);
2506   // All constants are declared with an initial value. The name
2507   // of the constant is the first argument and the initial value
2508   // is the second.
2509   RUNTIME_ASSERT(args.length() == 2);
2510   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2511   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
2512 
2513   // Get the current global object from top.
2514   GlobalObject* global = isolate->context()->global_object();
2515 
2516   // According to ECMA-262, section 12.2, page 62, the property must
2517   // not be deletable. Since it's a const, it must be READ_ONLY too.
2518   PropertyAttributes attributes =
2519       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2520 
2521   // Lookup the property as own on the global object. If it isn't
2522   // there, we add the property and take special precautions to always
2523   // add it even in case of callbacks in the prototype chain (this rules
2524   // out using SetProperty). We use SetOwnPropertyIgnoreAttributes instead
2525   LookupResult lookup(isolate);
2526   global->LookupOwn(name, &lookup);
2527   if (!lookup.IsFound()) {
2528     HandleScope handle_scope(isolate);
2529     Handle<GlobalObject> global(isolate->context()->global_object());
2530     RETURN_FAILURE_ON_EXCEPTION(
2531         isolate,
2532         JSObject::SetOwnPropertyIgnoreAttributes(global, name, value,
2533                                                  attributes));
2534     return *value;
2535   }
2536 
2537   if (!lookup.IsReadOnly()) {
2538     // Restore global object from context (in case of GC) and continue
2539     // with setting the value.
2540     HandleScope handle_scope(isolate);
2541     Handle<GlobalObject> global(isolate->context()->global_object());
2542 
2543     // BUG 1213575: Handle the case where we have to set a read-only
2544     // property through an interceptor and only do it if it's
2545     // uninitialized, e.g. the hole. Nirk...
2546     // Passing sloppy mode because the property is writable.
2547     RETURN_FAILURE_ON_EXCEPTION(
2548         isolate,
2549         JSReceiver::SetProperty(global, name, value, attributes, SLOPPY));
2550     return *value;
2551   }
2552 
2553   // Set the value, but only if we're assigning the initial value to a
2554   // constant. For now, we determine this by checking if the
2555   // current value is the hole.
2556   // Strict mode handling not needed (const is disallowed in strict mode).
2557   if (lookup.IsField()) {
2558     FixedArray* properties = global->properties();
2559     int index = lookup.GetFieldIndex().outobject_array_index();
2560     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2561       properties->set(index, *value);
2562     }
2563   } else if (lookup.IsNormal()) {
2564     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2565         !lookup.IsReadOnly()) {
2566       HandleScope scope(isolate);
2567       JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2568     }
2569   } else {
2570     // Ignore re-initialization of constants that have already been
2571     // assigned a constant value.
2572     ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2573   }
2574 
2575   // Use the set value as the result of the operation.
2576   return *value;
2577 }
2578 
2579 
RUNTIME_FUNCTION(RuntimeHidden_InitializeConstContextSlot)2580 RUNTIME_FUNCTION(RuntimeHidden_InitializeConstContextSlot) {
2581   HandleScope scope(isolate);
2582   ASSERT(args.length() == 3);
2583 
2584   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
2585   ASSERT(!value->IsTheHole());
2586   // Initializations are always done in a function or native context.
2587   CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
2588   Handle<Context> context(context_arg->declaration_context());
2589   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
2590 
2591   int index;
2592   PropertyAttributes attributes;
2593   ContextLookupFlags flags = FOLLOW_CHAINS;
2594   BindingFlags binding_flags;
2595   Handle<Object> holder =
2596       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2597 
2598   if (index >= 0) {
2599     ASSERT(holder->IsContext());
2600     // Property was found in a context.  Perform the assignment if we
2601     // found some non-constant or an uninitialized constant.
2602     Handle<Context> context = Handle<Context>::cast(holder);
2603     if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
2604       context->set(index, *value);
2605     }
2606     return *value;
2607   }
2608 
2609   // The property could not be found, we introduce it as a property of the
2610   // global object.
2611   if (attributes == ABSENT) {
2612     Handle<JSObject> global = Handle<JSObject>(
2613         isolate->context()->global_object());
2614     // Strict mode not needed (const disallowed in strict mode).
2615     RETURN_FAILURE_ON_EXCEPTION(
2616         isolate,
2617         JSReceiver::SetProperty(global, name, value, NONE, SLOPPY));
2618     return *value;
2619   }
2620 
2621   // The property was present in some function's context extension object,
2622   // as a property on the subject of a with, or as a property of the global
2623   // object.
2624   //
2625   // In most situations, eval-introduced consts should still be present in
2626   // the context extension object.  However, because declaration and
2627   // initialization are separate, the property might have been deleted
2628   // before we reach the initialization point.
2629   //
2630   // Example:
2631   //
2632   //    function f() { eval("delete x; const x;"); }
2633   //
2634   // In that case, the initialization behaves like a normal assignment.
2635   Handle<JSObject> object = Handle<JSObject>::cast(holder);
2636 
2637   if (*object == context->extension()) {
2638     // This is the property that was introduced by the const declaration.
2639     // Set it if it hasn't been set before.  NOTE: We cannot use
2640     // GetProperty() to get the current value as it 'unholes' the value.
2641     LookupResult lookup(isolate);
2642     object->LookupOwnRealNamedProperty(name, &lookup);
2643     ASSERT(lookup.IsFound());  // the property was declared
2644     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
2645 
2646     if (lookup.IsField()) {
2647       FixedArray* properties = object->properties();
2648       FieldIndex index = lookup.GetFieldIndex();
2649       ASSERT(!index.is_inobject());
2650       if (properties->get(index.outobject_array_index())->IsTheHole()) {
2651         properties->set(index.outobject_array_index(), *value);
2652       }
2653     } else if (lookup.IsNormal()) {
2654       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2655         JSObject::SetNormalizedProperty(object, &lookup, value);
2656       }
2657     } else {
2658       // We should not reach here. Any real, named property should be
2659       // either a field or a dictionary slot.
2660       UNREACHABLE();
2661     }
2662   } else {
2663     // The property was found on some other object.  Set it if it is not a
2664     // read-only property.
2665     if ((attributes & READ_ONLY) == 0) {
2666       // Strict mode not needed (const disallowed in strict mode).
2667       RETURN_FAILURE_ON_EXCEPTION(
2668           isolate,
2669           JSReceiver::SetProperty(object, name, value, attributes, SLOPPY));
2670     }
2671   }
2672 
2673   return *value;
2674 }
2675 
2676 
RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties)2677 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
2678   HandleScope scope(isolate);
2679   ASSERT(args.length() == 2);
2680   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2681   CONVERT_SMI_ARG_CHECKED(properties, 1);
2682   // Conservative upper limit to prevent fuzz tests from going OOM.
2683   RUNTIME_ASSERT(properties <= 100000);
2684   if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
2685     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
2686   }
2687   return *object;
2688 }
2689 
2690 
RUNTIME_FUNCTION(RuntimeHidden_RegExpExec)2691 RUNTIME_FUNCTION(RuntimeHidden_RegExpExec) {
2692   HandleScope scope(isolate);
2693   ASSERT(args.length() == 4);
2694   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2695   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2696   // Due to the way the JS calls are constructed this must be less than the
2697   // length of a string, i.e. it is always a Smi.  We check anyway for security.
2698   CONVERT_SMI_ARG_CHECKED(index, 2);
2699   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2700   RUNTIME_ASSERT(index >= 0);
2701   RUNTIME_ASSERT(index <= subject->length());
2702   isolate->counters()->regexp_entry_runtime()->Increment();
2703   Handle<Object> result;
2704   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2705       isolate, result,
2706       RegExpImpl::Exec(regexp, subject, index, last_match_info));
2707   return *result;
2708 }
2709 
2710 
RUNTIME_FUNCTION(RuntimeHidden_RegExpConstructResult)2711 RUNTIME_FUNCTION(RuntimeHidden_RegExpConstructResult) {
2712   HandleScope handle_scope(isolate);
2713   ASSERT(args.length() == 3);
2714   CONVERT_SMI_ARG_CHECKED(size, 0);
2715   RUNTIME_ASSERT(size >= 0 && size <= FixedArray::kMaxLength);
2716   CONVERT_ARG_HANDLE_CHECKED(Object, index, 1);
2717   CONVERT_ARG_HANDLE_CHECKED(Object, input, 2);
2718   Handle<FixedArray> elements =  isolate->factory()->NewFixedArray(size);
2719   Handle<Map> regexp_map(isolate->native_context()->regexp_result_map());
2720   Handle<JSObject> object =
2721       isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED, false);
2722   Handle<JSArray> array = Handle<JSArray>::cast(object);
2723   array->set_elements(*elements);
2724   array->set_length(Smi::FromInt(size));
2725   // Write in-object properties after the length of the array.
2726   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, *index);
2727   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, *input);
2728   return *array;
2729 }
2730 
2731 
RUNTIME_FUNCTION(Runtime_RegExpInitializeObject)2732 RUNTIME_FUNCTION(Runtime_RegExpInitializeObject) {
2733   HandleScope scope(isolate);
2734   ASSERT(args.length() == 5);
2735   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2736   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2737   // If source is the empty string we set it to "(?:)" instead as
2738   // suggested by ECMA-262, 5th, section 15.10.4.1.
2739   if (source->length() == 0) source = isolate->factory()->query_colon_string();
2740 
2741   CONVERT_ARG_HANDLE_CHECKED(Object, global, 2);
2742   if (!global->IsTrue()) global = isolate->factory()->false_value();
2743 
2744   CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3);
2745   if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value();
2746 
2747   CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4);
2748   if (!multiline->IsTrue()) multiline = isolate->factory()->false_value();
2749 
2750   Map* map = regexp->map();
2751   Object* constructor = map->constructor();
2752   if (constructor->IsJSFunction() &&
2753       JSFunction::cast(constructor)->initial_map() == map) {
2754     // If we still have the original map, set in-object properties directly.
2755     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source);
2756     // Both true and false are immovable immortal objects so no need for write
2757     // barrier.
2758     regexp->InObjectPropertyAtPut(
2759         JSRegExp::kGlobalFieldIndex, *global, SKIP_WRITE_BARRIER);
2760     regexp->InObjectPropertyAtPut(
2761         JSRegExp::kIgnoreCaseFieldIndex, *ignoreCase, SKIP_WRITE_BARRIER);
2762     regexp->InObjectPropertyAtPut(
2763         JSRegExp::kMultilineFieldIndex, *multiline, SKIP_WRITE_BARRIER);
2764     regexp->InObjectPropertyAtPut(
2765         JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
2766     return *regexp;
2767   }
2768 
2769   // Map has changed, so use generic, but slower, method.
2770   PropertyAttributes final =
2771       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2772   PropertyAttributes writable =
2773       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2774   Handle<Object> zero(Smi::FromInt(0), isolate);
2775   Factory* factory = isolate->factory();
2776   JSObject::SetOwnPropertyIgnoreAttributes(
2777       regexp, factory->source_string(), source, final).Check();
2778   JSObject::SetOwnPropertyIgnoreAttributes(
2779       regexp, factory->global_string(), global, final).Check();
2780   JSObject::SetOwnPropertyIgnoreAttributes(
2781       regexp, factory->ignore_case_string(), ignoreCase, final).Check();
2782   JSObject::SetOwnPropertyIgnoreAttributes(
2783       regexp, factory->multiline_string(), multiline, final).Check();
2784   JSObject::SetOwnPropertyIgnoreAttributes(
2785       regexp, factory->last_index_string(), zero, writable).Check();
2786   return *regexp;
2787 }
2788 
2789 
RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup)2790 RUNTIME_FUNCTION(Runtime_FinishArrayPrototypeSetup) {
2791   HandleScope scope(isolate);
2792   ASSERT(args.length() == 1);
2793   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2794   Object* length = prototype->length();
2795   RUNTIME_ASSERT(length->IsSmi() && Smi::cast(length)->value() == 0);
2796   RUNTIME_ASSERT(prototype->HasFastSmiOrObjectElements());
2797   // This is necessary to enable fast checks for absence of elements
2798   // on Array.prototype and below.
2799   prototype->set_elements(isolate->heap()->empty_fixed_array());
2800   return Smi::FromInt(0);
2801 }
2802 
2803 
InstallBuiltin(Isolate * isolate,Handle<JSObject> holder,const char * name,Builtins::Name builtin_name)2804 static void InstallBuiltin(Isolate* isolate,
2805                            Handle<JSObject> holder,
2806                            const char* name,
2807                            Builtins::Name builtin_name) {
2808   Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2809   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2810   Handle<JSFunction> optimized =
2811       isolate->factory()->NewFunctionWithoutPrototype(key, code);
2812   optimized->shared()->DontAdaptArguments();
2813   JSReceiver::SetProperty(holder, key, optimized, NONE, STRICT).Assert();
2814 }
2815 
2816 
RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions)2817 RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
2818   HandleScope scope(isolate);
2819   ASSERT(args.length() == 0);
2820   Handle<JSObject> holder =
2821       isolate->factory()->NewJSObject(isolate->object_function());
2822 
2823   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2824   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2825   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2826   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2827   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2828   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2829   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2830 
2831   return *holder;
2832 }
2833 
2834 
RUNTIME_FUNCTION(Runtime_IsSloppyModeFunction)2835 RUNTIME_FUNCTION(Runtime_IsSloppyModeFunction) {
2836   SealHandleScope shs(isolate);
2837   ASSERT(args.length() == 1);
2838   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2839   if (!callable->IsJSFunction()) {
2840     HandleScope scope(isolate);
2841     Handle<Object> delegate;
2842     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2843         isolate, delegate,
2844         Execution::TryGetFunctionDelegate(
2845             isolate, Handle<JSReceiver>(callable)));
2846     callable = JSFunction::cast(*delegate);
2847   }
2848   JSFunction* function = JSFunction::cast(callable);
2849   SharedFunctionInfo* shared = function->shared();
2850   return isolate->heap()->ToBoolean(shared->strict_mode() == SLOPPY);
2851 }
2852 
2853 
RUNTIME_FUNCTION(Runtime_GetDefaultReceiver)2854 RUNTIME_FUNCTION(Runtime_GetDefaultReceiver) {
2855   SealHandleScope shs(isolate);
2856   ASSERT(args.length() == 1);
2857   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2858 
2859   if (!callable->IsJSFunction()) {
2860     HandleScope scope(isolate);
2861     Handle<Object> delegate;
2862     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2863         isolate, delegate,
2864         Execution::TryGetFunctionDelegate(
2865             isolate, Handle<JSReceiver>(callable)));
2866     callable = JSFunction::cast(*delegate);
2867   }
2868   JSFunction* function = JSFunction::cast(callable);
2869 
2870   SharedFunctionInfo* shared = function->shared();
2871   if (shared->native() || shared->strict_mode() == STRICT) {
2872     return isolate->heap()->undefined_value();
2873   }
2874   // Returns undefined for strict or native functions, or
2875   // the associated global receiver for "normal" functions.
2876 
2877   Context* native_context =
2878       function->context()->global_object()->native_context();
2879   return native_context->global_object()->global_receiver();
2880 }
2881 
2882 
RUNTIME_FUNCTION(RuntimeHidden_MaterializeRegExpLiteral)2883 RUNTIME_FUNCTION(RuntimeHidden_MaterializeRegExpLiteral) {
2884   HandleScope scope(isolate);
2885   ASSERT(args.length() == 4);
2886   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2887   CONVERT_SMI_ARG_CHECKED(index, 1);
2888   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
2889   CONVERT_ARG_HANDLE_CHECKED(String, flags, 3);
2890 
2891   // Get the RegExp function from the context in the literals array.
2892   // This is the RegExp function from the context in which the
2893   // function was created.  We do not use the RegExp function from the
2894   // current native context because this might be the RegExp function
2895   // from another context which we should not have access to.
2896   Handle<JSFunction> constructor =
2897       Handle<JSFunction>(
2898           JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2899   // Compute the regular expression literal.
2900   Handle<Object> regexp;
2901   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2902       isolate, regexp,
2903       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags));
2904   literals->set(index, *regexp);
2905   return *regexp;
2906 }
2907 
2908 
RUNTIME_FUNCTION(Runtime_FunctionGetName)2909 RUNTIME_FUNCTION(Runtime_FunctionGetName) {
2910   SealHandleScope shs(isolate);
2911   ASSERT(args.length() == 1);
2912 
2913   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2914   return f->shared()->name();
2915 }
2916 
2917 
RUNTIME_FUNCTION(Runtime_FunctionSetName)2918 RUNTIME_FUNCTION(Runtime_FunctionSetName) {
2919   SealHandleScope shs(isolate);
2920   ASSERT(args.length() == 2);
2921 
2922   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2923   CONVERT_ARG_CHECKED(String, name, 1);
2924   f->shared()->set_name(name);
2925   return isolate->heap()->undefined_value();
2926 }
2927 
2928 
RUNTIME_FUNCTION(Runtime_FunctionNameShouldPrintAsAnonymous)2929 RUNTIME_FUNCTION(Runtime_FunctionNameShouldPrintAsAnonymous) {
2930   SealHandleScope shs(isolate);
2931   ASSERT(args.length() == 1);
2932   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2933   return isolate->heap()->ToBoolean(
2934       f->shared()->name_should_print_as_anonymous());
2935 }
2936 
2937 
RUNTIME_FUNCTION(Runtime_FunctionMarkNameShouldPrintAsAnonymous)2938 RUNTIME_FUNCTION(Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2939   SealHandleScope shs(isolate);
2940   ASSERT(args.length() == 1);
2941   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2942   f->shared()->set_name_should_print_as_anonymous(true);
2943   return isolate->heap()->undefined_value();
2944 }
2945 
2946 
RUNTIME_FUNCTION(Runtime_FunctionIsGenerator)2947 RUNTIME_FUNCTION(Runtime_FunctionIsGenerator) {
2948   SealHandleScope shs(isolate);
2949   ASSERT(args.length() == 1);
2950   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2951   return isolate->heap()->ToBoolean(f->shared()->is_generator());
2952 }
2953 
2954 
RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype)2955 RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
2956   SealHandleScope shs(isolate);
2957   ASSERT(args.length() == 1);
2958 
2959   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2960   RUNTIME_ASSERT(f->RemovePrototype());
2961 
2962   return isolate->heap()->undefined_value();
2963 }
2964 
2965 
RUNTIME_FUNCTION(Runtime_FunctionGetScript)2966 RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
2967   HandleScope scope(isolate);
2968   ASSERT(args.length() == 1);
2969 
2970   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2971   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2972   if (!script->IsScript()) return isolate->heap()->undefined_value();
2973 
2974   return *Script::GetWrapper(Handle<Script>::cast(script));
2975 }
2976 
2977 
RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode)2978 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
2979   HandleScope scope(isolate);
2980   ASSERT(args.length() == 1);
2981 
2982   CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2983   Handle<SharedFunctionInfo> shared(f->shared());
2984   return *shared->GetSourceCode();
2985 }
2986 
2987 
RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition)2988 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
2989   SealHandleScope shs(isolate);
2990   ASSERT(args.length() == 1);
2991 
2992   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2993   int pos = fun->shared()->start_position();
2994   return Smi::FromInt(pos);
2995 }
2996 
2997 
RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset)2998 RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset) {
2999   SealHandleScope shs(isolate);
3000   ASSERT(args.length() == 2);
3001 
3002   CONVERT_ARG_CHECKED(Code, code, 0);
3003   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
3004 
3005   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
3006 
3007   Address pc = code->address() + offset;
3008   return Smi::FromInt(code->SourcePosition(pc));
3009 }
3010 
3011 
RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName)3012 RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName) {
3013   SealHandleScope shs(isolate);
3014   ASSERT(args.length() == 2);
3015 
3016   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
3017   CONVERT_ARG_CHECKED(String, name, 1);
3018   fun->SetInstanceClassName(name);
3019   return isolate->heap()->undefined_value();
3020 }
3021 
3022 
RUNTIME_FUNCTION(Runtime_FunctionSetLength)3023 RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
3024   SealHandleScope shs(isolate);
3025   ASSERT(args.length() == 2);
3026 
3027   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
3028   CONVERT_SMI_ARG_CHECKED(length, 1);
3029   RUNTIME_ASSERT((length & 0xC0000000) == 0xC0000000 ||
3030                  (length & 0xC0000000) == 0x0);
3031   fun->shared()->set_length(length);
3032   return isolate->heap()->undefined_value();
3033 }
3034 
3035 
RUNTIME_FUNCTION(Runtime_FunctionSetPrototype)3036 RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) {
3037   HandleScope scope(isolate);
3038   ASSERT(args.length() == 2);
3039 
3040   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
3041   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
3042   RUNTIME_ASSERT(fun->should_have_prototype());
3043   Accessors::FunctionSetPrototype(fun, value);
3044   return args[0];  // return TOS
3045 }
3046 
3047 
RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction)3048 RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
3049   SealHandleScope shs(isolate);
3050   ASSERT(args.length() == 1);
3051 
3052   CONVERT_ARG_CHECKED(JSFunction, f, 0);
3053   return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
3054 }
3055 
3056 
RUNTIME_FUNCTION(Runtime_FunctionIsBuiltin)3057 RUNTIME_FUNCTION(Runtime_FunctionIsBuiltin) {
3058   SealHandleScope shs(isolate);
3059   ASSERT(args.length() == 1);
3060 
3061   CONVERT_ARG_CHECKED(JSFunction, f, 0);
3062   return isolate->heap()->ToBoolean(f->IsBuiltin());
3063 }
3064 
3065 
RUNTIME_FUNCTION(Runtime_SetCode)3066 RUNTIME_FUNCTION(Runtime_SetCode) {
3067   HandleScope scope(isolate);
3068   ASSERT(args.length() == 2);
3069 
3070   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
3071   CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1);
3072 
3073   Handle<SharedFunctionInfo> target_shared(target->shared());
3074   Handle<SharedFunctionInfo> source_shared(source->shared());
3075   RUNTIME_ASSERT(!source_shared->bound());
3076 
3077   if (!Compiler::EnsureCompiled(source, KEEP_EXCEPTION)) {
3078     return isolate->heap()->exception();
3079   }
3080 
3081   // Mark both, the source and the target, as un-flushable because the
3082   // shared unoptimized code makes them impossible to enqueue in a list.
3083   ASSERT(target_shared->code()->gc_metadata() == NULL);
3084   ASSERT(source_shared->code()->gc_metadata() == NULL);
3085   target_shared->set_dont_flush(true);
3086   source_shared->set_dont_flush(true);
3087 
3088   // Set the code, scope info, formal parameter count, and the length
3089   // of the target shared function info.
3090   target_shared->ReplaceCode(source_shared->code());
3091   target_shared->set_scope_info(source_shared->scope_info());
3092   target_shared->set_length(source_shared->length());
3093   target_shared->set_feedback_vector(source_shared->feedback_vector());
3094   target_shared->set_formal_parameter_count(
3095       source_shared->formal_parameter_count());
3096   target_shared->set_script(source_shared->script());
3097   target_shared->set_start_position_and_type(
3098       source_shared->start_position_and_type());
3099   target_shared->set_end_position(source_shared->end_position());
3100   bool was_native = target_shared->native();
3101   target_shared->set_compiler_hints(source_shared->compiler_hints());
3102   target_shared->set_native(was_native);
3103   target_shared->set_profiler_ticks(source_shared->profiler_ticks());
3104 
3105   // Set the code of the target function.
3106   target->ReplaceCode(source_shared->code());
3107   ASSERT(target->next_function_link()->IsUndefined());
3108 
3109   // Make sure we get a fresh copy of the literal vector to avoid cross
3110   // context contamination.
3111   Handle<Context> context(source->context());
3112   int number_of_literals = source->NumberOfLiterals();
3113   Handle<FixedArray> literals =
3114       isolate->factory()->NewFixedArray(number_of_literals, TENURED);
3115   if (number_of_literals > 0) {
3116     literals->set(JSFunction::kLiteralNativeContextIndex,
3117                   context->native_context());
3118   }
3119   target->set_context(*context);
3120   target->set_literals(*literals);
3121 
3122   if (isolate->logger()->is_logging_code_events() ||
3123       isolate->cpu_profiler()->is_profiling()) {
3124     isolate->logger()->LogExistingFunction(
3125         source_shared, Handle<Code>(source_shared->code()));
3126   }
3127 
3128   return *target;
3129 }
3130 
3131 
RUNTIME_FUNCTION(RuntimeHidden_CreateJSGeneratorObject)3132 RUNTIME_FUNCTION(RuntimeHidden_CreateJSGeneratorObject) {
3133   HandleScope scope(isolate);
3134   ASSERT(args.length() == 0);
3135 
3136   JavaScriptFrameIterator it(isolate);
3137   JavaScriptFrame* frame = it.frame();
3138   Handle<JSFunction> function(frame->function());
3139   RUNTIME_ASSERT(function->shared()->is_generator());
3140 
3141   Handle<JSGeneratorObject> generator;
3142   if (frame->IsConstructor()) {
3143     generator = handle(JSGeneratorObject::cast(frame->receiver()));
3144   } else {
3145     generator = isolate->factory()->NewJSGeneratorObject(function);
3146   }
3147   generator->set_function(*function);
3148   generator->set_context(Context::cast(frame->context()));
3149   generator->set_receiver(frame->receiver());
3150   generator->set_continuation(0);
3151   generator->set_operand_stack(isolate->heap()->empty_fixed_array());
3152   generator->set_stack_handler_index(-1);
3153 
3154   return *generator;
3155 }
3156 
3157 
RUNTIME_FUNCTION(RuntimeHidden_SuspendJSGeneratorObject)3158 RUNTIME_FUNCTION(RuntimeHidden_SuspendJSGeneratorObject) {
3159   HandleScope handle_scope(isolate);
3160   ASSERT(args.length() == 1);
3161   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator_object, 0);
3162 
3163   JavaScriptFrameIterator stack_iterator(isolate);
3164   JavaScriptFrame* frame = stack_iterator.frame();
3165   RUNTIME_ASSERT(frame->function()->shared()->is_generator());
3166   ASSERT_EQ(frame->function(), generator_object->function());
3167 
3168   // The caller should have saved the context and continuation already.
3169   ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
3170   ASSERT_LT(0, generator_object->continuation());
3171 
3172   // We expect there to be at least two values on the operand stack: the return
3173   // value of the yield expression, and the argument to this runtime call.
3174   // Neither of those should be saved.
3175   int operands_count = frame->ComputeOperandsCount();
3176   ASSERT_GE(operands_count, 2);
3177   operands_count -= 2;
3178 
3179   if (operands_count == 0) {
3180     // Although it's semantically harmless to call this function with an
3181     // operands_count of zero, it is also unnecessary.
3182     ASSERT_EQ(generator_object->operand_stack(),
3183               isolate->heap()->empty_fixed_array());
3184     ASSERT_EQ(generator_object->stack_handler_index(), -1);
3185     // If there are no operands on the stack, there shouldn't be a handler
3186     // active either.
3187     ASSERT(!frame->HasHandler());
3188   } else {
3189     int stack_handler_index = -1;
3190     Handle<FixedArray> operand_stack =
3191         isolate->factory()->NewFixedArray(operands_count);
3192     frame->SaveOperandStack(*operand_stack, &stack_handler_index);
3193     generator_object->set_operand_stack(*operand_stack);
3194     generator_object->set_stack_handler_index(stack_handler_index);
3195   }
3196 
3197   return isolate->heap()->undefined_value();
3198 }
3199 
3200 
3201 // Note that this function is the slow path for resuming generators.  It is only
3202 // called if the suspended activation had operands on the stack, stack handlers
3203 // needing rewinding, or if the resume should throw an exception.  The fast path
3204 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3205 // inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
3206 // called in any case, as it needs to reconstruct the stack frame and make space
3207 // for arguments and operands.
RUNTIME_FUNCTION(RuntimeHidden_ResumeJSGeneratorObject)3208 RUNTIME_FUNCTION(RuntimeHidden_ResumeJSGeneratorObject) {
3209   SealHandleScope shs(isolate);
3210   ASSERT(args.length() == 3);
3211   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3212   CONVERT_ARG_CHECKED(Object, value, 1);
3213   CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3214   JavaScriptFrameIterator stack_iterator(isolate);
3215   JavaScriptFrame* frame = stack_iterator.frame();
3216 
3217   ASSERT_EQ(frame->function(), generator_object->function());
3218   ASSERT(frame->function()->is_compiled());
3219 
3220   STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
3221   STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
3222 
3223   Address pc = generator_object->function()->code()->instruction_start();
3224   int offset = generator_object->continuation();
3225   ASSERT(offset > 0);
3226   frame->set_pc(pc + offset);
3227   if (FLAG_enable_ool_constant_pool) {
3228     frame->set_constant_pool(
3229         generator_object->function()->code()->constant_pool());
3230   }
3231   generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3232 
3233   FixedArray* operand_stack = generator_object->operand_stack();
3234   int operands_count = operand_stack->length();
3235   if (operands_count != 0) {
3236     frame->RestoreOperandStack(operand_stack,
3237                                generator_object->stack_handler_index());
3238     generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3239     generator_object->set_stack_handler_index(-1);
3240   }
3241 
3242   JSGeneratorObject::ResumeMode resume_mode =
3243       static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3244   switch (resume_mode) {
3245     case JSGeneratorObject::NEXT:
3246       return value;
3247     case JSGeneratorObject::THROW:
3248       return isolate->Throw(value);
3249   }
3250 
3251   UNREACHABLE();
3252   return isolate->ThrowIllegalOperation();
3253 }
3254 
3255 
RUNTIME_FUNCTION(RuntimeHidden_ThrowGeneratorStateError)3256 RUNTIME_FUNCTION(RuntimeHidden_ThrowGeneratorStateError) {
3257   HandleScope scope(isolate);
3258   ASSERT(args.length() == 1);
3259   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
3260   int continuation = generator->continuation();
3261   const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3262       "generator_finished" : "generator_running";
3263   Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3264   Handle<Object> error = isolate->factory()->NewError(message, argv);
3265   return isolate->Throw(*error);
3266 }
3267 
3268 
RUNTIME_FUNCTION(Runtime_ObjectFreeze)3269 RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
3270   HandleScope scope(isolate);
3271   ASSERT(args.length() == 1);
3272   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
3273 
3274   // %ObjectFreeze is a fast path and these cases are handled elsewhere.
3275   RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
3276                  !object->map()->is_observed() &&
3277                  !object->IsJSProxy());
3278 
3279   Handle<Object> result;
3280   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
3281   return *result;
3282 }
3283 
3284 
RUNTIME_FUNCTION(RuntimeHidden_StringCharCodeAt)3285 RUNTIME_FUNCTION(RuntimeHidden_StringCharCodeAt) {
3286   HandleScope handle_scope(isolate);
3287   ASSERT(args.length() == 2);
3288 
3289   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3290   CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3291 
3292   // Flatten the string.  If someone wants to get a char at an index
3293   // in a cons string, it is likely that more indices will be
3294   // accessed.
3295   subject = String::Flatten(subject);
3296 
3297   if (i >= static_cast<uint32_t>(subject->length())) {
3298     return isolate->heap()->nan_value();
3299   }
3300 
3301   return Smi::FromInt(subject->Get(i));
3302 }
3303 
3304 
RUNTIME_FUNCTION(Runtime_CharFromCode)3305 RUNTIME_FUNCTION(Runtime_CharFromCode) {
3306   HandleScope handlescope(isolate);
3307   ASSERT(args.length() == 1);
3308   if (args[0]->IsNumber()) {
3309     CONVERT_NUMBER_CHECKED(uint32_t, code, Uint32, args[0]);
3310     code &= 0xffff;
3311     return *isolate->factory()->LookupSingleCharacterStringFromCode(code);
3312   }
3313   return isolate->heap()->empty_string();
3314 }
3315 
3316 
3317 class FixedArrayBuilder {
3318  public:
FixedArrayBuilder(Isolate * isolate,int initial_capacity)3319   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3320       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3321         length_(0),
3322         has_non_smi_elements_(false) {
3323     // Require a non-zero initial size. Ensures that doubling the size to
3324     // extend the array will work.
3325     ASSERT(initial_capacity > 0);
3326   }
3327 
FixedArrayBuilder(Handle<FixedArray> backing_store)3328   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3329       : array_(backing_store),
3330         length_(0),
3331         has_non_smi_elements_(false) {
3332     // Require a non-zero initial size. Ensures that doubling the size to
3333     // extend the array will work.
3334     ASSERT(backing_store->length() > 0);
3335   }
3336 
HasCapacity(int elements)3337   bool HasCapacity(int elements) {
3338     int length = array_->length();
3339     int required_length = length_ + elements;
3340     return (length >= required_length);
3341   }
3342 
EnsureCapacity(int elements)3343   void EnsureCapacity(int elements) {
3344     int length = array_->length();
3345     int required_length = length_ + elements;
3346     if (length < required_length) {
3347       int new_length = length;
3348       do {
3349         new_length *= 2;
3350       } while (new_length < required_length);
3351       Handle<FixedArray> extended_array =
3352           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3353       array_->CopyTo(0, *extended_array, 0, length_);
3354       array_ = extended_array;
3355     }
3356   }
3357 
Add(Object * value)3358   void Add(Object* value) {
3359     ASSERT(!value->IsSmi());
3360     ASSERT(length_ < capacity());
3361     array_->set(length_, value);
3362     length_++;
3363     has_non_smi_elements_ = true;
3364   }
3365 
Add(Smi * value)3366   void Add(Smi* value) {
3367     ASSERT(value->IsSmi());
3368     ASSERT(length_ < capacity());
3369     array_->set(length_, value);
3370     length_++;
3371   }
3372 
array()3373   Handle<FixedArray> array() {
3374     return array_;
3375   }
3376 
length()3377   int length() {
3378     return length_;
3379   }
3380 
capacity()3381   int capacity() {
3382     return array_->length();
3383   }
3384 
ToJSArray(Handle<JSArray> target_array)3385   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
3386     JSArray::SetContent(target_array, array_);
3387     target_array->set_length(Smi::FromInt(length_));
3388     return target_array;
3389   }
3390 
3391 
3392  private:
3393   Handle<FixedArray> array_;
3394   int length_;
3395   bool has_non_smi_elements_;
3396 };
3397 
3398 
3399 // Forward declarations.
3400 const int kStringBuilderConcatHelperLengthBits = 11;
3401 const int kStringBuilderConcatHelperPositionBits = 19;
3402 
3403 template <typename schar>
3404 static inline void StringBuilderConcatHelper(String*,
3405                                              schar*,
3406                                              FixedArray*,
3407                                              int);
3408 
3409 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
3410     StringBuilderSubstringLength;
3411 typedef BitField<int,
3412                  kStringBuilderConcatHelperLengthBits,
3413                  kStringBuilderConcatHelperPositionBits>
3414     StringBuilderSubstringPosition;
3415 
3416 
3417 class ReplacementStringBuilder {
3418  public:
ReplacementStringBuilder(Heap * heap,Handle<String> subject,int estimated_part_count)3419   ReplacementStringBuilder(Heap* heap,
3420                            Handle<String> subject,
3421                            int estimated_part_count)
3422       : heap_(heap),
3423         array_builder_(heap->isolate(), estimated_part_count),
3424         subject_(subject),
3425         character_count_(0),
3426         is_ascii_(subject->IsOneByteRepresentation()) {
3427     // Require a non-zero initial size. Ensures that doubling the size to
3428     // extend the array will work.
3429     ASSERT(estimated_part_count > 0);
3430   }
3431 
AddSubjectSlice(FixedArrayBuilder * builder,int from,int to)3432   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3433                                      int from,
3434                                      int to) {
3435     ASSERT(from >= 0);
3436     int length = to - from;
3437     ASSERT(length > 0);
3438     if (StringBuilderSubstringLength::is_valid(length) &&
3439         StringBuilderSubstringPosition::is_valid(from)) {
3440       int encoded_slice = StringBuilderSubstringLength::encode(length) |
3441           StringBuilderSubstringPosition::encode(from);
3442       builder->Add(Smi::FromInt(encoded_slice));
3443     } else {
3444       // Otherwise encode as two smis.
3445       builder->Add(Smi::FromInt(-length));
3446       builder->Add(Smi::FromInt(from));
3447     }
3448   }
3449 
3450 
EnsureCapacity(int elements)3451   void EnsureCapacity(int elements) {
3452     array_builder_.EnsureCapacity(elements);
3453   }
3454 
3455 
AddSubjectSlice(int from,int to)3456   void AddSubjectSlice(int from, int to) {
3457     AddSubjectSlice(&array_builder_, from, to);
3458     IncrementCharacterCount(to - from);
3459   }
3460 
3461 
AddString(Handle<String> string)3462   void AddString(Handle<String> string) {
3463     int length = string->length();
3464     ASSERT(length > 0);
3465     AddElement(*string);
3466     if (!string->IsOneByteRepresentation()) {
3467       is_ascii_ = false;
3468     }
3469     IncrementCharacterCount(length);
3470   }
3471 
3472 
ToString()3473   MaybeHandle<String> ToString() {
3474     Isolate* isolate = heap_->isolate();
3475     if (array_builder_.length() == 0) {
3476       return isolate->factory()->empty_string();
3477     }
3478 
3479     Handle<String> joined_string;
3480     if (is_ascii_) {
3481       Handle<SeqOneByteString> seq;
3482       ASSIGN_RETURN_ON_EXCEPTION(
3483           isolate, seq,
3484           isolate->factory()->NewRawOneByteString(character_count_),
3485           String);
3486 
3487       DisallowHeapAllocation no_gc;
3488       uint8_t* char_buffer = seq->GetChars();
3489       StringBuilderConcatHelper(*subject_,
3490                                 char_buffer,
3491                                 *array_builder_.array(),
3492                                 array_builder_.length());
3493       joined_string = Handle<String>::cast(seq);
3494     } else {
3495       // Non-ASCII.
3496       Handle<SeqTwoByteString> seq;
3497       ASSIGN_RETURN_ON_EXCEPTION(
3498           isolate, seq,
3499           isolate->factory()->NewRawTwoByteString(character_count_),
3500           String);
3501 
3502       DisallowHeapAllocation no_gc;
3503       uc16* char_buffer = seq->GetChars();
3504       StringBuilderConcatHelper(*subject_,
3505                                 char_buffer,
3506                                 *array_builder_.array(),
3507                                 array_builder_.length());
3508       joined_string = Handle<String>::cast(seq);
3509     }
3510     return joined_string;
3511   }
3512 
3513 
IncrementCharacterCount(int by)3514   void IncrementCharacterCount(int by) {
3515     if (character_count_ > String::kMaxLength - by) {
3516       STATIC_ASSERT(String::kMaxLength < kMaxInt);
3517       character_count_ = kMaxInt;
3518     } else {
3519       character_count_ += by;
3520     }
3521   }
3522 
3523  private:
AddElement(Object * element)3524   void AddElement(Object* element) {
3525     ASSERT(element->IsSmi() || element->IsString());
3526     ASSERT(array_builder_.capacity() > array_builder_.length());
3527     array_builder_.Add(element);
3528   }
3529 
3530   Heap* heap_;
3531   FixedArrayBuilder array_builder_;
3532   Handle<String> subject_;
3533   int character_count_;
3534   bool is_ascii_;
3535 };
3536 
3537 
3538 class CompiledReplacement {
3539  public:
CompiledReplacement(Zone * zone)3540   explicit CompiledReplacement(Zone* zone)
3541       : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3542 
3543   // Return whether the replacement is simple.
3544   bool Compile(Handle<String> replacement,
3545                int capture_count,
3546                int subject_length);
3547 
3548   // Use Apply only if Compile returned false.
3549   void Apply(ReplacementStringBuilder* builder,
3550              int match_from,
3551              int match_to,
3552              int32_t* match);
3553 
3554   // Number of distinct parts of the replacement pattern.
parts()3555   int parts() {
3556     return parts_.length();
3557   }
3558 
zone() const3559   Zone* zone() const { return zone_; }
3560 
3561  private:
3562   enum PartType {
3563     SUBJECT_PREFIX = 1,
3564     SUBJECT_SUFFIX,
3565     SUBJECT_CAPTURE,
3566     REPLACEMENT_SUBSTRING,
3567     REPLACEMENT_STRING,
3568 
3569     NUMBER_OF_PART_TYPES
3570   };
3571 
3572   struct ReplacementPart {
SubjectMatchv8::internal::CompiledReplacement::ReplacementPart3573     static inline ReplacementPart SubjectMatch() {
3574       return ReplacementPart(SUBJECT_CAPTURE, 0);
3575     }
SubjectCapturev8::internal::CompiledReplacement::ReplacementPart3576     static inline ReplacementPart SubjectCapture(int capture_index) {
3577       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3578     }
SubjectPrefixv8::internal::CompiledReplacement::ReplacementPart3579     static inline ReplacementPart SubjectPrefix() {
3580       return ReplacementPart(SUBJECT_PREFIX, 0);
3581     }
SubjectSuffixv8::internal::CompiledReplacement::ReplacementPart3582     static inline ReplacementPart SubjectSuffix(int subject_length) {
3583       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3584     }
ReplacementStringv8::internal::CompiledReplacement::ReplacementPart3585     static inline ReplacementPart ReplacementString() {
3586       return ReplacementPart(REPLACEMENT_STRING, 0);
3587     }
ReplacementSubStringv8::internal::CompiledReplacement::ReplacementPart3588     static inline ReplacementPart ReplacementSubString(int from, int to) {
3589       ASSERT(from >= 0);
3590       ASSERT(to > from);
3591       return ReplacementPart(-from, to);
3592     }
3593 
3594     // If tag <= 0 then it is the negation of a start index of a substring of
3595     // the replacement pattern, otherwise it's a value from PartType.
ReplacementPartv8::internal::CompiledReplacement::ReplacementPart3596     ReplacementPart(int tag, int data)
3597         : tag(tag), data(data) {
3598       // Must be non-positive or a PartType value.
3599       ASSERT(tag < NUMBER_OF_PART_TYPES);
3600     }
3601     // Either a value of PartType or a non-positive number that is
3602     // the negation of an index into the replacement string.
3603     int tag;
3604     // The data value's interpretation depends on the value of tag:
3605     // tag == SUBJECT_PREFIX ||
3606     // tag == SUBJECT_SUFFIX:  data is unused.
3607     // tag == SUBJECT_CAPTURE: data is the number of the capture.
3608     // tag == REPLACEMENT_SUBSTRING ||
3609     // tag == REPLACEMENT_STRING:    data is index into array of substrings
3610     //                               of the replacement string.
3611     // tag <= 0: Temporary representation of the substring of the replacement
3612     //           string ranging over -tag .. data.
3613     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3614     //           substring objects.
3615     int data;
3616   };
3617 
3618   template<typename Char>
ParseReplacementPattern(ZoneList<ReplacementPart> * parts,Vector<Char> characters,int capture_count,int subject_length,Zone * zone)3619   bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3620                                Vector<Char> characters,
3621                                int capture_count,
3622                                int subject_length,
3623                                Zone* zone) {
3624     int length = characters.length();
3625     int last = 0;
3626     for (int i = 0; i < length; i++) {
3627       Char c = characters[i];
3628       if (c == '$') {
3629         int next_index = i + 1;
3630         if (next_index == length) {  // No next character!
3631           break;
3632         }
3633         Char c2 = characters[next_index];
3634         switch (c2) {
3635         case '$':
3636           if (i > last) {
3637             // There is a substring before. Include the first "$".
3638             parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3639                        zone);
3640             last = next_index + 1;  // Continue after the second "$".
3641           } else {
3642             // Let the next substring start with the second "$".
3643             last = next_index;
3644           }
3645           i = next_index;
3646           break;
3647         case '`':
3648           if (i > last) {
3649             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3650           }
3651           parts->Add(ReplacementPart::SubjectPrefix(), zone);
3652           i = next_index;
3653           last = i + 1;
3654           break;
3655         case '\'':
3656           if (i > last) {
3657             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3658           }
3659           parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3660           i = next_index;
3661           last = i + 1;
3662           break;
3663         case '&':
3664           if (i > last) {
3665             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3666           }
3667           parts->Add(ReplacementPart::SubjectMatch(), zone);
3668           i = next_index;
3669           last = i + 1;
3670           break;
3671         case '0':
3672         case '1':
3673         case '2':
3674         case '3':
3675         case '4':
3676         case '5':
3677         case '6':
3678         case '7':
3679         case '8':
3680         case '9': {
3681           int capture_ref = c2 - '0';
3682           if (capture_ref > capture_count) {
3683             i = next_index;
3684             continue;
3685           }
3686           int second_digit_index = next_index + 1;
3687           if (second_digit_index < length) {
3688             // Peek ahead to see if we have two digits.
3689             Char c3 = characters[second_digit_index];
3690             if ('0' <= c3 && c3 <= '9') {  // Double digits.
3691               int double_digit_ref = capture_ref * 10 + c3 - '0';
3692               if (double_digit_ref <= capture_count) {
3693                 next_index = second_digit_index;
3694                 capture_ref = double_digit_ref;
3695               }
3696             }
3697           }
3698           if (capture_ref > 0) {
3699             if (i > last) {
3700               parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3701             }
3702             ASSERT(capture_ref <= capture_count);
3703             parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3704             last = next_index + 1;
3705           }
3706           i = next_index;
3707           break;
3708         }
3709         default:
3710           i = next_index;
3711           break;
3712         }
3713       }
3714     }
3715     if (length > last) {
3716       if (last == 0) {
3717         // Replacement is simple.  Do not use Apply to do the replacement.
3718         return true;
3719       } else {
3720         parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3721       }
3722     }
3723     return false;
3724   }
3725 
3726   ZoneList<ReplacementPart> parts_;
3727   ZoneList<Handle<String> > replacement_substrings_;
3728   Zone* zone_;
3729 };
3730 
3731 
Compile(Handle<String> replacement,int capture_count,int subject_length)3732 bool CompiledReplacement::Compile(Handle<String> replacement,
3733                                   int capture_count,
3734                                   int subject_length) {
3735   {
3736     DisallowHeapAllocation no_gc;
3737     String::FlatContent content = replacement->GetFlatContent();
3738     ASSERT(content.IsFlat());
3739     bool simple = false;
3740     if (content.IsAscii()) {
3741       simple = ParseReplacementPattern(&parts_,
3742                                        content.ToOneByteVector(),
3743                                        capture_count,
3744                                        subject_length,
3745                                        zone());
3746     } else {
3747       ASSERT(content.IsTwoByte());
3748       simple = ParseReplacementPattern(&parts_,
3749                                        content.ToUC16Vector(),
3750                                        capture_count,
3751                                        subject_length,
3752                                        zone());
3753     }
3754     if (simple) return true;
3755   }
3756 
3757   Isolate* isolate = replacement->GetIsolate();
3758   // Find substrings of replacement string and create them as String objects.
3759   int substring_index = 0;
3760   for (int i = 0, n = parts_.length(); i < n; i++) {
3761     int tag = parts_[i].tag;
3762     if (tag <= 0) {  // A replacement string slice.
3763       int from = -tag;
3764       int to = parts_[i].data;
3765       replacement_substrings_.Add(
3766           isolate->factory()->NewSubString(replacement, from, to), zone());
3767       parts_[i].tag = REPLACEMENT_SUBSTRING;
3768       parts_[i].data = substring_index;
3769       substring_index++;
3770     } else if (tag == REPLACEMENT_STRING) {
3771       replacement_substrings_.Add(replacement, zone());
3772       parts_[i].data = substring_index;
3773       substring_index++;
3774     }
3775   }
3776   return false;
3777 }
3778 
3779 
Apply(ReplacementStringBuilder * builder,int match_from,int match_to,int32_t * match)3780 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
3781                                 int match_from,
3782                                 int match_to,
3783                                 int32_t* match) {
3784   ASSERT_LT(0, parts_.length());
3785   for (int i = 0, n = parts_.length(); i < n; i++) {
3786     ReplacementPart part = parts_[i];
3787     switch (part.tag) {
3788       case SUBJECT_PREFIX:
3789         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3790         break;
3791       case SUBJECT_SUFFIX: {
3792         int subject_length = part.data;
3793         if (match_to < subject_length) {
3794           builder->AddSubjectSlice(match_to, subject_length);
3795         }
3796         break;
3797       }
3798       case SUBJECT_CAPTURE: {
3799         int capture = part.data;
3800         int from = match[capture * 2];
3801         int to = match[capture * 2 + 1];
3802         if (from >= 0 && to > from) {
3803           builder->AddSubjectSlice(from, to);
3804         }
3805         break;
3806       }
3807       case REPLACEMENT_SUBSTRING:
3808       case REPLACEMENT_STRING:
3809         builder->AddString(replacement_substrings_[part.data]);
3810         break;
3811       default:
3812         UNREACHABLE();
3813     }
3814   }
3815 }
3816 
3817 
FindAsciiStringIndices(Vector<const uint8_t> subject,char pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3818 void FindAsciiStringIndices(Vector<const uint8_t> subject,
3819                             char pattern,
3820                             ZoneList<int>* indices,
3821                             unsigned int limit,
3822                             Zone* zone) {
3823   ASSERT(limit > 0);
3824   // Collect indices of pattern in subject using memchr.
3825   // Stop after finding at most limit values.
3826   const uint8_t* subject_start = subject.start();
3827   const uint8_t* subject_end = subject_start + subject.length();
3828   const uint8_t* pos = subject_start;
3829   while (limit > 0) {
3830     pos = reinterpret_cast<const uint8_t*>(
3831         memchr(pos, pattern, subject_end - pos));
3832     if (pos == NULL) return;
3833     indices->Add(static_cast<int>(pos - subject_start), zone);
3834     pos++;
3835     limit--;
3836   }
3837 }
3838 
3839 
FindTwoByteStringIndices(const Vector<const uc16> subject,uc16 pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3840 void FindTwoByteStringIndices(const Vector<const uc16> subject,
3841                               uc16 pattern,
3842                               ZoneList<int>* indices,
3843                               unsigned int limit,
3844                               Zone* zone) {
3845   ASSERT(limit > 0);
3846   const uc16* subject_start = subject.start();
3847   const uc16* subject_end = subject_start + subject.length();
3848   for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3849     if (*pos == pattern) {
3850       indices->Add(static_cast<int>(pos - subject_start), zone);
3851       limit--;
3852     }
3853   }
3854 }
3855 
3856 
3857 template <typename SubjectChar, typename PatternChar>
FindStringIndices(Isolate * isolate,Vector<const SubjectChar> subject,Vector<const PatternChar> pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3858 void FindStringIndices(Isolate* isolate,
3859                        Vector<const SubjectChar> subject,
3860                        Vector<const PatternChar> pattern,
3861                        ZoneList<int>* indices,
3862                        unsigned int limit,
3863                        Zone* zone) {
3864   ASSERT(limit > 0);
3865   // Collect indices of pattern in subject.
3866   // Stop after finding at most limit values.
3867   int pattern_length = pattern.length();
3868   int index = 0;
3869   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3870   while (limit > 0) {
3871     index = search.Search(subject, index);
3872     if (index < 0) return;
3873     indices->Add(index, zone);
3874     index += pattern_length;
3875     limit--;
3876   }
3877 }
3878 
3879 
FindStringIndicesDispatch(Isolate * isolate,String * subject,String * pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3880 void FindStringIndicesDispatch(Isolate* isolate,
3881                                String* subject,
3882                                String* pattern,
3883                                ZoneList<int>* indices,
3884                                unsigned int limit,
3885                                Zone* zone) {
3886   {
3887     DisallowHeapAllocation no_gc;
3888     String::FlatContent subject_content = subject->GetFlatContent();
3889     String::FlatContent pattern_content = pattern->GetFlatContent();
3890     ASSERT(subject_content.IsFlat());
3891     ASSERT(pattern_content.IsFlat());
3892     if (subject_content.IsAscii()) {
3893       Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3894       if (pattern_content.IsAscii()) {
3895         Vector<const uint8_t> pattern_vector =
3896             pattern_content.ToOneByteVector();
3897         if (pattern_vector.length() == 1) {
3898           FindAsciiStringIndices(subject_vector,
3899                                  pattern_vector[0],
3900                                  indices,
3901                                  limit,
3902                                  zone);
3903         } else {
3904           FindStringIndices(isolate,
3905                             subject_vector,
3906                             pattern_vector,
3907                             indices,
3908                             limit,
3909                             zone);
3910         }
3911       } else {
3912         FindStringIndices(isolate,
3913                           subject_vector,
3914                           pattern_content.ToUC16Vector(),
3915                           indices,
3916                           limit,
3917                           zone);
3918       }
3919     } else {
3920       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3921       if (pattern_content.IsAscii()) {
3922         Vector<const uint8_t> pattern_vector =
3923             pattern_content.ToOneByteVector();
3924         if (pattern_vector.length() == 1) {
3925           FindTwoByteStringIndices(subject_vector,
3926                                    pattern_vector[0],
3927                                    indices,
3928                                    limit,
3929                                    zone);
3930         } else {
3931           FindStringIndices(isolate,
3932                             subject_vector,
3933                             pattern_vector,
3934                             indices,
3935                             limit,
3936                             zone);
3937         }
3938       } else {
3939         Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3940         if (pattern_vector.length() == 1) {
3941           FindTwoByteStringIndices(subject_vector,
3942                                    pattern_vector[0],
3943                                    indices,
3944                                    limit,
3945                                    zone);
3946         } else {
3947           FindStringIndices(isolate,
3948                             subject_vector,
3949                             pattern_vector,
3950                             indices,
3951                             limit,
3952                             zone);
3953         }
3954       }
3955     }
3956   }
3957 }
3958 
3959 
3960 template<typename ResultSeqString>
StringReplaceGlobalAtomRegExpWithString(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> pattern_regexp,Handle<String> replacement,Handle<JSArray> last_match_info)3961 MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
3962     Isolate* isolate,
3963     Handle<String> subject,
3964     Handle<JSRegExp> pattern_regexp,
3965     Handle<String> replacement,
3966     Handle<JSArray> last_match_info) {
3967   ASSERT(subject->IsFlat());
3968   ASSERT(replacement->IsFlat());
3969 
3970   ZoneScope zone_scope(isolate->runtime_zone());
3971   ZoneList<int> indices(8, zone_scope.zone());
3972   ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3973   String* pattern =
3974       String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
3975   int subject_len = subject->length();
3976   int pattern_len = pattern->length();
3977   int replacement_len = replacement->length();
3978 
3979   FindStringIndicesDispatch(
3980       isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3981 
3982   int matches = indices.length();
3983   if (matches == 0) return *subject;
3984 
3985   // Detect integer overflow.
3986   int64_t result_len_64 =
3987       (static_cast<int64_t>(replacement_len) -
3988        static_cast<int64_t>(pattern_len)) *
3989       static_cast<int64_t>(matches) +
3990       static_cast<int64_t>(subject_len);
3991   int result_len;
3992   if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
3993     STATIC_ASSERT(String::kMaxLength < kMaxInt);
3994     result_len = kMaxInt;  // Provoke exception.
3995   } else {
3996     result_len = static_cast<int>(result_len_64);
3997   }
3998 
3999   int subject_pos = 0;
4000   int result_pos = 0;
4001 
4002   MaybeHandle<SeqString> maybe_res;
4003   if (ResultSeqString::kHasAsciiEncoding) {
4004     maybe_res = isolate->factory()->NewRawOneByteString(result_len);
4005   } else {
4006     maybe_res = isolate->factory()->NewRawTwoByteString(result_len);
4007   }
4008   Handle<SeqString> untyped_res;
4009   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, untyped_res, maybe_res);
4010   Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(untyped_res);
4011 
4012   for (int i = 0; i < matches; i++) {
4013     // Copy non-matched subject content.
4014     if (subject_pos < indices.at(i)) {
4015       String::WriteToFlat(*subject,
4016                           result->GetChars() + result_pos,
4017                           subject_pos,
4018                           indices.at(i));
4019       result_pos += indices.at(i) - subject_pos;
4020     }
4021 
4022     // Replace match.
4023     if (replacement_len > 0) {
4024       String::WriteToFlat(*replacement,
4025                           result->GetChars() + result_pos,
4026                           0,
4027                           replacement_len);
4028       result_pos += replacement_len;
4029     }
4030 
4031     subject_pos = indices.at(i) + pattern_len;
4032   }
4033   // Add remaining subject content at the end.
4034   if (subject_pos < subject_len) {
4035     String::WriteToFlat(*subject,
4036                         result->GetChars() + result_pos,
4037                         subject_pos,
4038                         subject_len);
4039   }
4040 
4041   int32_t match_indices[] = { indices.at(matches - 1),
4042                               indices.at(matches - 1) + pattern_len };
4043   RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
4044 
4045   return *result;
4046 }
4047 
4048 
StringReplaceGlobalRegExpWithString(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<String> replacement,Handle<JSArray> last_match_info)4049 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
4050     Isolate* isolate,
4051     Handle<String> subject,
4052     Handle<JSRegExp> regexp,
4053     Handle<String> replacement,
4054     Handle<JSArray> last_match_info) {
4055   ASSERT(subject->IsFlat());
4056   ASSERT(replacement->IsFlat());
4057 
4058   int capture_count = regexp->CaptureCount();
4059   int subject_length = subject->length();
4060 
4061   // CompiledReplacement uses zone allocation.
4062   ZoneScope zone_scope(isolate->runtime_zone());
4063   CompiledReplacement compiled_replacement(zone_scope.zone());
4064   bool simple_replace = compiled_replacement.Compile(replacement,
4065                                                      capture_count,
4066                                                      subject_length);
4067 
4068   // Shortcut for simple non-regexp global replacements
4069   if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
4070     if (subject->HasOnlyOneByteChars() &&
4071         replacement->HasOnlyOneByteChars()) {
4072       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4073           isolate, subject, regexp, replacement, last_match_info);
4074     } else {
4075       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4076           isolate, subject, regexp, replacement, last_match_info);
4077     }
4078   }
4079 
4080   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4081   if (global_cache.HasException()) return isolate->heap()->exception();
4082 
4083   int32_t* current_match = global_cache.FetchNext();
4084   if (current_match == NULL) {
4085     if (global_cache.HasException()) return isolate->heap()->exception();
4086     return *subject;
4087   }
4088 
4089   // Guessing the number of parts that the final result string is built
4090   // from. Global regexps can match any number of times, so we guess
4091   // conservatively.
4092   int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
4093   ReplacementStringBuilder builder(isolate->heap(),
4094                                    subject,
4095                                    expected_parts);
4096 
4097   // Number of parts added by compiled replacement plus preceeding
4098   // string and possibly suffix after last match.  It is possible for
4099   // all components to use two elements when encoded as two smis.
4100   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
4101 
4102   int prev = 0;
4103 
4104   do {
4105     builder.EnsureCapacity(parts_added_per_loop);
4106 
4107     int start = current_match[0];
4108     int end = current_match[1];
4109 
4110     if (prev < start) {
4111       builder.AddSubjectSlice(prev, start);
4112     }
4113 
4114     if (simple_replace) {
4115       builder.AddString(replacement);
4116     } else {
4117       compiled_replacement.Apply(&builder,
4118                                  start,
4119                                  end,
4120                                  current_match);
4121     }
4122     prev = end;
4123 
4124     current_match = global_cache.FetchNext();
4125   } while (current_match != NULL);
4126 
4127   if (global_cache.HasException()) return isolate->heap()->exception();
4128 
4129   if (prev < subject_length) {
4130     builder.EnsureCapacity(2);
4131     builder.AddSubjectSlice(prev, subject_length);
4132   }
4133 
4134   RegExpImpl::SetLastMatchInfo(last_match_info,
4135                                subject,
4136                                capture_count,
4137                                global_cache.LastSuccessfulMatch());
4138 
4139   Handle<String> result;
4140   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, builder.ToString());
4141   return *result;
4142 }
4143 
4144 
4145 template <typename ResultSeqString>
StringReplaceGlobalRegExpWithEmptyString(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_info)4146 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
4147     Isolate* isolate,
4148     Handle<String> subject,
4149     Handle<JSRegExp> regexp,
4150     Handle<JSArray> last_match_info) {
4151   ASSERT(subject->IsFlat());
4152 
4153   // Shortcut for simple non-regexp global replacements
4154   if (regexp->TypeTag() == JSRegExp::ATOM) {
4155     Handle<String> empty_string = isolate->factory()->empty_string();
4156     if (subject->IsOneByteRepresentation()) {
4157       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4158           isolate, subject, regexp, empty_string, last_match_info);
4159     } else {
4160       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4161           isolate, subject, regexp, empty_string, last_match_info);
4162     }
4163   }
4164 
4165   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4166   if (global_cache.HasException()) return isolate->heap()->exception();
4167 
4168   int32_t* current_match = global_cache.FetchNext();
4169   if (current_match == NULL) {
4170     if (global_cache.HasException()) return isolate->heap()->exception();
4171     return *subject;
4172   }
4173 
4174   int start = current_match[0];
4175   int end = current_match[1];
4176   int capture_count = regexp->CaptureCount();
4177   int subject_length = subject->length();
4178 
4179   int new_length = subject_length - (end - start);
4180   if (new_length == 0) return isolate->heap()->empty_string();
4181 
4182   Handle<ResultSeqString> answer;
4183   if (ResultSeqString::kHasAsciiEncoding) {
4184     answer = Handle<ResultSeqString>::cast(
4185         isolate->factory()->NewRawOneByteString(new_length).ToHandleChecked());
4186   } else {
4187     answer = Handle<ResultSeqString>::cast(
4188         isolate->factory()->NewRawTwoByteString(new_length).ToHandleChecked());
4189   }
4190 
4191   int prev = 0;
4192   int position = 0;
4193 
4194   do {
4195     start = current_match[0];
4196     end = current_match[1];
4197     if (prev < start) {
4198       // Add substring subject[prev;start] to answer string.
4199       String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
4200       position += start - prev;
4201     }
4202     prev = end;
4203 
4204     current_match = global_cache.FetchNext();
4205   } while (current_match != NULL);
4206 
4207   if (global_cache.HasException()) return isolate->heap()->exception();
4208 
4209   RegExpImpl::SetLastMatchInfo(last_match_info,
4210                                subject,
4211                                capture_count,
4212                                global_cache.LastSuccessfulMatch());
4213 
4214   if (prev < subject_length) {
4215     // Add substring subject[prev;length] to answer string.
4216     String::WriteToFlat(
4217         *subject, answer->GetChars() + position, prev, subject_length);
4218     position += subject_length - prev;
4219   }
4220 
4221   if (position == 0) return isolate->heap()->empty_string();
4222 
4223   // Shorten string and fill
4224   int string_size = ResultSeqString::SizeFor(position);
4225   int allocated_string_size = ResultSeqString::SizeFor(new_length);
4226   int delta = allocated_string_size - string_size;
4227 
4228   answer->set_length(position);
4229   if (delta == 0) return *answer;
4230 
4231   Address end_of_string = answer->address() + string_size;
4232   Heap* heap = isolate->heap();
4233 
4234   // The trimming is performed on a newly allocated object, which is on a
4235   // fresly allocated page or on an already swept page. Hence, the sweeper
4236   // thread can not get confused with the filler creation. No synchronization
4237   // needed.
4238   heap->CreateFillerObjectAt(end_of_string, delta);
4239   heap->AdjustLiveBytes(answer->address(), -delta, Heap::FROM_MUTATOR);
4240   return *answer;
4241 }
4242 
4243 
RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString)4244 RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) {
4245   HandleScope scope(isolate);
4246   ASSERT(args.length() == 4);
4247 
4248   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4249   CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4250   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4251   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4252 
4253   RUNTIME_ASSERT(regexp->GetFlags().is_global());
4254   RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
4255 
4256   subject = String::Flatten(subject);
4257 
4258   if (replacement->length() == 0) {
4259     if (subject->HasOnlyOneByteChars()) {
4260       return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4261           isolate, subject, regexp, last_match_info);
4262     } else {
4263       return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4264           isolate, subject, regexp, last_match_info);
4265     }
4266   }
4267 
4268   replacement = String::Flatten(replacement);
4269 
4270   return StringReplaceGlobalRegExpWithString(
4271       isolate, subject, regexp, replacement, last_match_info);
4272 }
4273 
4274 
4275 // This may return an empty MaybeHandle if an exception is thrown or
4276 // we abort due to reaching the recursion limit.
StringReplaceOneCharWithString(Isolate * isolate,Handle<String> subject,Handle<String> search,Handle<String> replace,bool * found,int recursion_limit)4277 MaybeHandle<String> StringReplaceOneCharWithString(Isolate* isolate,
4278                                                    Handle<String> subject,
4279                                                    Handle<String> search,
4280                                                    Handle<String> replace,
4281                                                    bool* found,
4282                                                    int recursion_limit) {
4283   StackLimitCheck stackLimitCheck(isolate);
4284   if (stackLimitCheck.HasOverflowed() || (recursion_limit == 0)) {
4285     return MaybeHandle<String>();
4286   }
4287   recursion_limit--;
4288   if (subject->IsConsString()) {
4289     ConsString* cons = ConsString::cast(*subject);
4290     Handle<String> first = Handle<String>(cons->first());
4291     Handle<String> second = Handle<String>(cons->second());
4292     Handle<String> new_first;
4293     if (!StringReplaceOneCharWithString(
4294             isolate, first, search, replace, found, recursion_limit)
4295             .ToHandle(&new_first)) {
4296       return MaybeHandle<String>();
4297     }
4298     if (*found) return isolate->factory()->NewConsString(new_first, second);
4299 
4300     Handle<String> new_second;
4301     if (!StringReplaceOneCharWithString(
4302             isolate, second, search, replace, found, recursion_limit)
4303             .ToHandle(&new_second)) {
4304       return MaybeHandle<String>();
4305     }
4306     if (*found) return isolate->factory()->NewConsString(first, new_second);
4307 
4308     return subject;
4309   } else {
4310     int index = Runtime::StringMatch(isolate, subject, search, 0);
4311     if (index == -1) return subject;
4312     *found = true;
4313     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4314     Handle<String> cons1;
4315     ASSIGN_RETURN_ON_EXCEPTION(
4316         isolate, cons1,
4317         isolate->factory()->NewConsString(first, replace),
4318         String);
4319     Handle<String> second =
4320         isolate->factory()->NewSubString(subject, index + 1, subject->length());
4321     return isolate->factory()->NewConsString(cons1, second);
4322   }
4323 }
4324 
4325 
RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString)4326 RUNTIME_FUNCTION(Runtime_StringReplaceOneCharWithString) {
4327   HandleScope scope(isolate);
4328   ASSERT(args.length() == 3);
4329   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4330   CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4331   CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4332 
4333   // If the cons string tree is too deep, we simply abort the recursion and
4334   // retry with a flattened subject string.
4335   const int kRecursionLimit = 0x1000;
4336   bool found = false;
4337   Handle<String> result;
4338   if (StringReplaceOneCharWithString(
4339           isolate, subject, search, replace, &found, kRecursionLimit)
4340           .ToHandle(&result)) {
4341     return *result;
4342   }
4343   if (isolate->has_pending_exception()) return isolate->heap()->exception();
4344 
4345   subject = String::Flatten(subject);
4346   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
4347       isolate, result,
4348       StringReplaceOneCharWithString(
4349           isolate, subject, search, replace, &found, kRecursionLimit));
4350   return *result;
4351 }
4352 
4353 
4354 // Perform string match of pattern on subject, starting at start index.
4355 // Caller must ensure that 0 <= start_index <= sub->length(),
4356 // and should check that pat->length() + start_index <= sub->length().
StringMatch(Isolate * isolate,Handle<String> sub,Handle<String> pat,int start_index)4357 int Runtime::StringMatch(Isolate* isolate,
4358                          Handle<String> sub,
4359                          Handle<String> pat,
4360                          int start_index) {
4361   ASSERT(0 <= start_index);
4362   ASSERT(start_index <= sub->length());
4363 
4364   int pattern_length = pat->length();
4365   if (pattern_length == 0) return start_index;
4366 
4367   int subject_length = sub->length();
4368   if (start_index + pattern_length > subject_length) return -1;
4369 
4370   sub = String::Flatten(sub);
4371   pat = String::Flatten(pat);
4372 
4373   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4374   // Extract flattened substrings of cons strings before determining asciiness.
4375   String::FlatContent seq_sub = sub->GetFlatContent();
4376   String::FlatContent seq_pat = pat->GetFlatContent();
4377 
4378   // dispatch on type of strings
4379   if (seq_pat.IsAscii()) {
4380     Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4381     if (seq_sub.IsAscii()) {
4382       return SearchString(isolate,
4383                           seq_sub.ToOneByteVector(),
4384                           pat_vector,
4385                           start_index);
4386     }
4387     return SearchString(isolate,
4388                         seq_sub.ToUC16Vector(),
4389                         pat_vector,
4390                         start_index);
4391   }
4392   Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4393   if (seq_sub.IsAscii()) {
4394     return SearchString(isolate,
4395                         seq_sub.ToOneByteVector(),
4396                         pat_vector,
4397                         start_index);
4398   }
4399   return SearchString(isolate,
4400                       seq_sub.ToUC16Vector(),
4401                       pat_vector,
4402                       start_index);
4403 }
4404 
4405 
RUNTIME_FUNCTION(Runtime_StringIndexOf)4406 RUNTIME_FUNCTION(Runtime_StringIndexOf) {
4407   HandleScope scope(isolate);
4408   ASSERT(args.length() == 3);
4409 
4410   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4411   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4412   CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
4413 
4414   uint32_t start_index;
4415   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4416 
4417   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4418   int position = Runtime::StringMatch(isolate, sub, pat, start_index);
4419   return Smi::FromInt(position);
4420 }
4421 
4422 
4423 template <typename schar, typename pchar>
StringMatchBackwards(Vector<const schar> subject,Vector<const pchar> pattern,int idx)4424 static int StringMatchBackwards(Vector<const schar> subject,
4425                                 Vector<const pchar> pattern,
4426                                 int idx) {
4427   int pattern_length = pattern.length();
4428   ASSERT(pattern_length >= 1);
4429   ASSERT(idx + pattern_length <= subject.length());
4430 
4431   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4432     for (int i = 0; i < pattern_length; i++) {
4433       uc16 c = pattern[i];
4434       if (c > String::kMaxOneByteCharCode) {
4435         return -1;
4436       }
4437     }
4438   }
4439 
4440   pchar pattern_first_char = pattern[0];
4441   for (int i = idx; i >= 0; i--) {
4442     if (subject[i] != pattern_first_char) continue;
4443     int j = 1;
4444     while (j < pattern_length) {
4445       if (pattern[j] != subject[i+j]) {
4446         break;
4447       }
4448       j++;
4449     }
4450     if (j == pattern_length) {
4451       return i;
4452     }
4453   }
4454   return -1;
4455 }
4456 
4457 
RUNTIME_FUNCTION(Runtime_StringLastIndexOf)4458 RUNTIME_FUNCTION(Runtime_StringLastIndexOf) {
4459   HandleScope scope(isolate);
4460   ASSERT(args.length() == 3);
4461 
4462   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4463   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4464   CONVERT_ARG_HANDLE_CHECKED(Object, index, 2);
4465 
4466   uint32_t start_index;
4467   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4468 
4469   uint32_t pat_length = pat->length();
4470   uint32_t sub_length = sub->length();
4471 
4472   if (start_index + pat_length > sub_length) {
4473     start_index = sub_length - pat_length;
4474   }
4475 
4476   if (pat_length == 0) {
4477     return Smi::FromInt(start_index);
4478   }
4479 
4480   sub = String::Flatten(sub);
4481   pat = String::Flatten(pat);
4482 
4483   int position = -1;
4484   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4485 
4486   String::FlatContent sub_content = sub->GetFlatContent();
4487   String::FlatContent pat_content = pat->GetFlatContent();
4488 
4489   if (pat_content.IsAscii()) {
4490     Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4491     if (sub_content.IsAscii()) {
4492       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4493                                       pat_vector,
4494                                       start_index);
4495     } else {
4496       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4497                                       pat_vector,
4498                                       start_index);
4499     }
4500   } else {
4501     Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4502     if (sub_content.IsAscii()) {
4503       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4504                                       pat_vector,
4505                                       start_index);
4506     } else {
4507       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4508                                       pat_vector,
4509                                       start_index);
4510     }
4511   }
4512 
4513   return Smi::FromInt(position);
4514 }
4515 
4516 
RUNTIME_FUNCTION(Runtime_StringLocaleCompare)4517 RUNTIME_FUNCTION(Runtime_StringLocaleCompare) {
4518   HandleScope handle_scope(isolate);
4519   ASSERT(args.length() == 2);
4520 
4521   CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
4522   CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
4523 
4524   if (str1.is_identical_to(str2)) return Smi::FromInt(0);  // Equal.
4525   int str1_length = str1->length();
4526   int str2_length = str2->length();
4527 
4528   // Decide trivial cases without flattening.
4529   if (str1_length == 0) {
4530     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
4531     return Smi::FromInt(-str2_length);
4532   } else {
4533     if (str2_length == 0) return Smi::FromInt(str1_length);
4534   }
4535 
4536   int end = str1_length < str2_length ? str1_length : str2_length;
4537 
4538   // No need to flatten if we are going to find the answer on the first
4539   // character.  At this point we know there is at least one character
4540   // in each string, due to the trivial case handling above.
4541   int d = str1->Get(0) - str2->Get(0);
4542   if (d != 0) return Smi::FromInt(d);
4543 
4544   str1 = String::Flatten(str1);
4545   str2 = String::Flatten(str2);
4546 
4547   DisallowHeapAllocation no_gc;
4548   String::FlatContent flat1 = str1->GetFlatContent();
4549   String::FlatContent flat2 = str2->GetFlatContent();
4550 
4551   for (int i = 0; i < end; i++) {
4552     if (flat1.Get(i) != flat2.Get(i)) {
4553       return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
4554     }
4555   }
4556 
4557   return Smi::FromInt(str1_length - str2_length);
4558 }
4559 
4560 
RUNTIME_FUNCTION(RuntimeHidden_SubString)4561 RUNTIME_FUNCTION(RuntimeHidden_SubString) {
4562   HandleScope scope(isolate);
4563   ASSERT(args.length() == 3);
4564 
4565   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
4566   int start, end;
4567   // We have a fast integer-only case here to avoid a conversion to double in
4568   // the common case where from and to are Smis.
4569   if (args[1]->IsSmi() && args[2]->IsSmi()) {
4570     CONVERT_SMI_ARG_CHECKED(from_number, 1);
4571     CONVERT_SMI_ARG_CHECKED(to_number, 2);
4572     start = from_number;
4573     end = to_number;
4574   } else {
4575     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4576     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4577     start = FastD2IChecked(from_number);
4578     end = FastD2IChecked(to_number);
4579   }
4580   RUNTIME_ASSERT(end >= start);
4581   RUNTIME_ASSERT(start >= 0);
4582   RUNTIME_ASSERT(end <= string->length());
4583   isolate->counters()->sub_string_runtime()->Increment();
4584 
4585   return *isolate->factory()->NewSubString(string, start, end);
4586 }
4587 
4588 
RUNTIME_FUNCTION(Runtime_StringMatch)4589 RUNTIME_FUNCTION(Runtime_StringMatch) {
4590   HandleScope handles(isolate);
4591   ASSERT(args.length() == 3);
4592 
4593   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4594   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4595   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4596 
4597   RUNTIME_ASSERT(regexp_info->HasFastObjectElements());
4598 
4599   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4600   if (global_cache.HasException()) return isolate->heap()->exception();
4601 
4602   int capture_count = regexp->CaptureCount();
4603 
4604   ZoneScope zone_scope(isolate->runtime_zone());
4605   ZoneList<int> offsets(8, zone_scope.zone());
4606 
4607   while (true) {
4608     int32_t* match = global_cache.FetchNext();
4609     if (match == NULL) break;
4610     offsets.Add(match[0], zone_scope.zone());  // start
4611     offsets.Add(match[1], zone_scope.zone());  // end
4612   }
4613 
4614   if (global_cache.HasException()) return isolate->heap()->exception();
4615 
4616   if (offsets.length() == 0) {
4617     // Not a single match.
4618     return isolate->heap()->null_value();
4619   }
4620 
4621   RegExpImpl::SetLastMatchInfo(regexp_info,
4622                                subject,
4623                                capture_count,
4624                                global_cache.LastSuccessfulMatch());
4625 
4626   int matches = offsets.length() / 2;
4627   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4628   Handle<String> substring =
4629       isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4630   elements->set(0, *substring);
4631   for (int i = 1; i < matches; i++) {
4632     HandleScope temp_scope(isolate);
4633     int from = offsets.at(i * 2);
4634     int to = offsets.at(i * 2 + 1);
4635     Handle<String> substring =
4636         isolate->factory()->NewProperSubString(subject, from, to);
4637     elements->set(i, *substring);
4638   }
4639   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4640   result->set_length(Smi::FromInt(matches));
4641   return *result;
4642 }
4643 
4644 
4645 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4646 // separate last match info.  See comment on that function.
4647 template<bool has_capture>
SearchRegExpMultiple(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_array,Handle<JSArray> result_array)4648 static Object* SearchRegExpMultiple(
4649     Isolate* isolate,
4650     Handle<String> subject,
4651     Handle<JSRegExp> regexp,
4652     Handle<JSArray> last_match_array,
4653     Handle<JSArray> result_array) {
4654   ASSERT(subject->IsFlat());
4655   ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
4656 
4657   int capture_count = regexp->CaptureCount();
4658   int subject_length = subject->length();
4659 
4660   static const int kMinLengthToCache = 0x1000;
4661 
4662   if (subject_length > kMinLengthToCache) {
4663     Handle<Object> cached_answer(RegExpResultsCache::Lookup(
4664         isolate->heap(),
4665         *subject,
4666         regexp->data(),
4667         RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
4668     if (*cached_answer != Smi::FromInt(0)) {
4669       Handle<FixedArray> cached_fixed_array =
4670           Handle<FixedArray>(FixedArray::cast(*cached_answer));
4671       // The cache FixedArray is a COW-array and can therefore be reused.
4672       JSArray::SetContent(result_array, cached_fixed_array);
4673       // The actual length of the result array is stored in the last element of
4674       // the backing store (the backing FixedArray may have a larger capacity).
4675       Object* cached_fixed_array_last_element =
4676           cached_fixed_array->get(cached_fixed_array->length() - 1);
4677       Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4678       result_array->set_length(js_array_length);
4679       RegExpImpl::SetLastMatchInfo(
4680           last_match_array, subject, capture_count, NULL);
4681       return *result_array;
4682     }
4683   }
4684 
4685   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4686   if (global_cache.HasException()) return isolate->heap()->exception();
4687 
4688   // Ensured in Runtime_RegExpExecMultiple.
4689   ASSERT(result_array->HasFastObjectElements());
4690   Handle<FixedArray> result_elements(
4691       FixedArray::cast(result_array->elements()));
4692   if (result_elements->length() < 16) {
4693     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4694   }
4695 
4696   FixedArrayBuilder builder(result_elements);
4697 
4698   // Position to search from.
4699   int match_start = -1;
4700   int match_end = 0;
4701   bool first = true;
4702 
4703   // Two smis before and after the match, for very long strings.
4704   static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4705 
4706   while (true) {
4707     int32_t* current_match = global_cache.FetchNext();
4708     if (current_match == NULL) break;
4709     match_start = current_match[0];
4710     builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4711     if (match_end < match_start) {
4712       ReplacementStringBuilder::AddSubjectSlice(&builder,
4713                                                 match_end,
4714                                                 match_start);
4715     }
4716     match_end = current_match[1];
4717     {
4718       // Avoid accumulating new handles inside loop.
4719       HandleScope temp_scope(isolate);
4720       Handle<String> match;
4721       if (!first) {
4722         match = isolate->factory()->NewProperSubString(subject,
4723                                                        match_start,
4724                                                        match_end);
4725       } else {
4726         match = isolate->factory()->NewSubString(subject,
4727                                                  match_start,
4728                                                  match_end);
4729         first = false;
4730       }
4731 
4732       if (has_capture) {
4733         // Arguments array to replace function is match, captures, index and
4734         // subject, i.e., 3 + capture count in total.
4735         Handle<FixedArray> elements =
4736             isolate->factory()->NewFixedArray(3 + capture_count);
4737 
4738         elements->set(0, *match);
4739         for (int i = 1; i <= capture_count; i++) {
4740           int start = current_match[i * 2];
4741           if (start >= 0) {
4742             int end = current_match[i * 2 + 1];
4743             ASSERT(start <= end);
4744             Handle<String> substring =
4745                 isolate->factory()->NewSubString(subject, start, end);
4746             elements->set(i, *substring);
4747           } else {
4748             ASSERT(current_match[i * 2 + 1] < 0);
4749             elements->set(i, isolate->heap()->undefined_value());
4750           }
4751         }
4752         elements->set(capture_count + 1, Smi::FromInt(match_start));
4753         elements->set(capture_count + 2, *subject);
4754         builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4755       } else {
4756         builder.Add(*match);
4757       }
4758     }
4759   }
4760 
4761   if (global_cache.HasException()) return isolate->heap()->exception();
4762 
4763   if (match_start >= 0) {
4764     // Finished matching, with at least one match.
4765     if (match_end < subject_length) {
4766       ReplacementStringBuilder::AddSubjectSlice(&builder,
4767                                                 match_end,
4768                                                 subject_length);
4769     }
4770 
4771     RegExpImpl::SetLastMatchInfo(
4772         last_match_array, subject, capture_count, NULL);
4773 
4774     if (subject_length > kMinLengthToCache) {
4775       // Store the length of the result array into the last element of the
4776       // backing FixedArray.
4777       builder.EnsureCapacity(1);
4778       Handle<FixedArray> fixed_array = builder.array();
4779       fixed_array->set(fixed_array->length() - 1,
4780                        Smi::FromInt(builder.length()));
4781       // Cache the result and turn the FixedArray into a COW array.
4782       RegExpResultsCache::Enter(isolate,
4783                                 subject,
4784                                 handle(regexp->data(), isolate),
4785                                 fixed_array,
4786                                 RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
4787     }
4788     return *builder.ToJSArray(result_array);
4789   } else {
4790     return isolate->heap()->null_value();  // No matches at all.
4791   }
4792 }
4793 
4794 
4795 // This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4796 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4797 // set any other last match array info.
RUNTIME_FUNCTION(Runtime_RegExpExecMultiple)4798 RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
4799   HandleScope handles(isolate);
4800   ASSERT(args.length() == 4);
4801 
4802   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4803   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4804   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4805   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4806   RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
4807   RUNTIME_ASSERT(result_array->HasFastObjectElements());
4808 
4809   subject = String::Flatten(subject);
4810   RUNTIME_ASSERT(regexp->GetFlags().is_global());
4811 
4812   if (regexp->CaptureCount() == 0) {
4813     return SearchRegExpMultiple<false>(
4814         isolate, subject, regexp, last_match_info, result_array);
4815   } else {
4816     return SearchRegExpMultiple<true>(
4817         isolate, subject, regexp, last_match_info, result_array);
4818   }
4819 }
4820 
4821 
RUNTIME_FUNCTION(Runtime_NumberToRadixString)4822 RUNTIME_FUNCTION(Runtime_NumberToRadixString) {
4823   HandleScope scope(isolate);
4824   ASSERT(args.length() == 2);
4825   CONVERT_SMI_ARG_CHECKED(radix, 1);
4826   RUNTIME_ASSERT(2 <= radix && radix <= 36);
4827 
4828   // Fast case where the result is a one character string.
4829   if (args[0]->IsSmi()) {
4830     int value = args.smi_at(0);
4831     if (value >= 0 && value < radix) {
4832       // Character array used for conversion.
4833       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4834       return *isolate->factory()->
4835           LookupSingleCharacterStringFromCode(kCharTable[value]);
4836     }
4837   }
4838 
4839   // Slow case.
4840   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4841   if (std::isnan(value)) {
4842     return isolate->heap()->nan_string();
4843   }
4844   if (std::isinf(value)) {
4845     if (value < 0) {
4846       return isolate->heap()->minus_infinity_string();
4847     }
4848     return isolate->heap()->infinity_string();
4849   }
4850   char* str = DoubleToRadixCString(value, radix);
4851   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4852   DeleteArray(str);
4853   return *result;
4854 }
4855 
4856 
RUNTIME_FUNCTION(Runtime_NumberToFixed)4857 RUNTIME_FUNCTION(Runtime_NumberToFixed) {
4858   HandleScope scope(isolate);
4859   ASSERT(args.length() == 2);
4860 
4861   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4862   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4863   int f = FastD2IChecked(f_number);
4864   // See DoubleToFixedCString for these constants:
4865   RUNTIME_ASSERT(f >= 0 && f <= 20);
4866   RUNTIME_ASSERT(!Double(value).IsSpecial());
4867   char* str = DoubleToFixedCString(value, f);
4868   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4869   DeleteArray(str);
4870   return *result;
4871 }
4872 
4873 
RUNTIME_FUNCTION(Runtime_NumberToExponential)4874 RUNTIME_FUNCTION(Runtime_NumberToExponential) {
4875   HandleScope scope(isolate);
4876   ASSERT(args.length() == 2);
4877 
4878   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4879   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4880   int f = FastD2IChecked(f_number);
4881   RUNTIME_ASSERT(f >= -1 && f <= 20);
4882   RUNTIME_ASSERT(!Double(value).IsSpecial());
4883   char* str = DoubleToExponentialCString(value, f);
4884   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4885   DeleteArray(str);
4886   return *result;
4887 }
4888 
4889 
RUNTIME_FUNCTION(Runtime_NumberToPrecision)4890 RUNTIME_FUNCTION(Runtime_NumberToPrecision) {
4891   HandleScope scope(isolate);
4892   ASSERT(args.length() == 2);
4893 
4894   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4895   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4896   int f = FastD2IChecked(f_number);
4897   RUNTIME_ASSERT(f >= 1 && f <= 21);
4898   RUNTIME_ASSERT(!Double(value).IsSpecial());
4899   char* str = DoubleToPrecisionCString(value, f);
4900   Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
4901   DeleteArray(str);
4902   return *result;
4903 }
4904 
4905 
RUNTIME_FUNCTION(Runtime_IsValidSmi)4906 RUNTIME_FUNCTION(Runtime_IsValidSmi) {
4907   SealHandleScope shs(isolate);
4908   ASSERT(args.length() == 1);
4909 
4910   CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
4911   return isolate->heap()->ToBoolean(Smi::IsValid(number));
4912 }
4913 
4914 
4915 // Returns a single character string where first character equals
4916 // string->Get(index).
GetCharAt(Handle<String> string,uint32_t index)4917 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4918   if (index < static_cast<uint32_t>(string->length())) {
4919     Factory* factory = string->GetIsolate()->factory();
4920     return factory->LookupSingleCharacterStringFromCode(
4921         String::Flatten(string)->Get(index));
4922   }
4923   return Execution::CharAt(string, index);
4924 }
4925 
4926 
GetElementOrCharAt(Isolate * isolate,Handle<Object> object,uint32_t index)4927 MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
4928                                                 Handle<Object> object,
4929                                                 uint32_t index) {
4930   // Handle [] indexing on Strings
4931   if (object->IsString()) {
4932     Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4933     if (!result->IsUndefined()) return result;
4934   }
4935 
4936   // Handle [] indexing on String objects
4937   if (object->IsStringObjectWithCharacterAt(index)) {
4938     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4939     Handle<Object> result =
4940         GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4941     if (!result->IsUndefined()) return result;
4942   }
4943 
4944   Handle<Object> result;
4945   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4946     Handle<Object> proto(object->GetPrototype(isolate), isolate);
4947     return Object::GetElement(isolate, proto, index);
4948   } else {
4949     return Object::GetElement(isolate, object, index);
4950   }
4951 }
4952 
4953 
4954 MUST_USE_RESULT
ToName(Isolate * isolate,Handle<Object> key)4955 static MaybeHandle<Name> ToName(Isolate* isolate, Handle<Object> key) {
4956   if (key->IsName()) {
4957     return Handle<Name>::cast(key);
4958   } else {
4959     Handle<Object> converted;
4960     ASSIGN_RETURN_ON_EXCEPTION(
4961         isolate, converted, Execution::ToString(isolate, key), Name);
4962     return Handle<Name>::cast(converted);
4963   }
4964 }
4965 
4966 
HasObjectProperty(Isolate * isolate,Handle<JSReceiver> object,Handle<Object> key)4967 MaybeHandle<Object> Runtime::HasObjectProperty(Isolate* isolate,
4968                                                Handle<JSReceiver> object,
4969                                                Handle<Object> key) {
4970   // Check if the given key is an array index.
4971   uint32_t index;
4972   if (key->ToArrayIndex(&index)) {
4973     return isolate->factory()->ToBoolean(JSReceiver::HasElement(object, index));
4974   }
4975 
4976   // Convert the key to a name - possibly by calling back into JavaScript.
4977   Handle<Name> name;
4978   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
4979 
4980   return isolate->factory()->ToBoolean(JSReceiver::HasProperty(object, name));
4981 }
4982 
4983 
GetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key)4984 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
4985                                                Handle<Object> object,
4986                                                Handle<Object> key) {
4987   if (object->IsUndefined() || object->IsNull()) {
4988     Handle<Object> args[2] = { key, object };
4989     return isolate->Throw<Object>(
4990         isolate->factory()->NewTypeError("non_object_property_load",
4991                                          HandleVector(args, 2)));
4992   }
4993 
4994   // Check if the given key is an array index.
4995   uint32_t index;
4996   if (key->ToArrayIndex(&index)) {
4997     return GetElementOrCharAt(isolate, object, index);
4998   }
4999 
5000   // Convert the key to a name - possibly by calling back into JavaScript.
5001   Handle<Name> name;
5002   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
5003 
5004   // Check if the name is trivially convertible to an index and get
5005   // the element if so.
5006   if (name->AsArrayIndex(&index)) {
5007     return GetElementOrCharAt(isolate, object, index);
5008   } else {
5009     return Object::GetProperty(object, name);
5010   }
5011 }
5012 
5013 
RUNTIME_FUNCTION(Runtime_GetProperty)5014 RUNTIME_FUNCTION(Runtime_GetProperty) {
5015   HandleScope scope(isolate);
5016   ASSERT(args.length() == 2);
5017 
5018   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5019   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5020   Handle<Object> result;
5021   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5022       isolate, result,
5023       Runtime::GetObjectProperty(isolate, object, key));
5024   return *result;
5025 }
5026 
5027 
5028 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(Runtime_KeyedGetProperty)5029 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
5030   HandleScope scope(isolate);
5031   ASSERT(args.length() == 2);
5032 
5033   CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
5034   CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
5035 
5036   // Fast cases for getting named properties of the receiver JSObject
5037   // itself.
5038   //
5039   // The global proxy objects has to be excluded since LookupOwn on
5040   // the global proxy object can return a valid result even though the
5041   // global proxy object never has properties.  This is the case
5042   // because the global proxy object forwards everything to its hidden
5043   // prototype including own lookups.
5044   //
5045   // Additionally, we need to make sure that we do not cache results
5046   // for objects that require access checks.
5047   if (receiver_obj->IsJSObject()) {
5048     if (!receiver_obj->IsJSGlobalProxy() &&
5049         !receiver_obj->IsAccessCheckNeeded() &&
5050         key_obj->IsName()) {
5051       DisallowHeapAllocation no_allocation;
5052       Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
5053       Handle<Name> key = Handle<Name>::cast(key_obj);
5054       if (receiver->HasFastProperties()) {
5055         // Attempt to use lookup cache.
5056         Handle<Map> receiver_map(receiver->map(), isolate);
5057         KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
5058         int index = keyed_lookup_cache->Lookup(receiver_map, key);
5059         if (index != -1) {
5060           // Doubles are not cached, so raw read the value.
5061           Object* value = receiver->RawFastPropertyAt(
5062               FieldIndex::ForKeyedLookupCacheIndex(*receiver_map, index));
5063           return value->IsTheHole()
5064               ? isolate->heap()->undefined_value()
5065               : value;
5066         }
5067         // Lookup cache miss.  Perform lookup and update the cache if
5068         // appropriate.
5069         LookupResult result(isolate);
5070         receiver->LookupOwn(key, &result);
5071         if (result.IsField()) {
5072           FieldIndex field_index = result.GetFieldIndex();
5073           // Do not track double fields in the keyed lookup cache. Reading
5074           // double values requires boxing.
5075           if (!result.representation().IsDouble()) {
5076             keyed_lookup_cache->Update(receiver_map, key,
5077                 field_index.GetKeyedLookupCacheIndex());
5078           }
5079           AllowHeapAllocation allow_allocation;
5080           return *JSObject::FastPropertyAt(receiver, result.representation(),
5081                                            field_index);
5082         }
5083       } else {
5084         // Attempt dictionary lookup.
5085         NameDictionary* dictionary = receiver->property_dictionary();
5086         int entry = dictionary->FindEntry(key);
5087         if ((entry != NameDictionary::kNotFound) &&
5088             (dictionary->DetailsAt(entry).type() == NORMAL)) {
5089           Object* value = dictionary->ValueAt(entry);
5090           if (!receiver->IsGlobalObject()) return value;
5091           value = PropertyCell::cast(value)->value();
5092           if (!value->IsTheHole()) return value;
5093           // If value is the hole do the general lookup.
5094         }
5095       }
5096     } else if (FLAG_smi_only_arrays && key_obj->IsSmi()) {
5097       // JSObject without a name key. If the key is a Smi, check for a
5098       // definite out-of-bounds access to elements, which is a strong indicator
5099       // that subsequent accesses will also call the runtime. Proactively
5100       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
5101       // doubles for those future calls in the case that the elements would
5102       // become FAST_DOUBLE_ELEMENTS.
5103       Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
5104       ElementsKind elements_kind = js_object->GetElementsKind();
5105       if (IsFastDoubleElementsKind(elements_kind)) {
5106         Handle<Smi> key = Handle<Smi>::cast(key_obj);
5107         if (key->value() >= js_object->elements()->length()) {
5108           if (IsFastHoleyElementsKind(elements_kind)) {
5109             elements_kind = FAST_HOLEY_ELEMENTS;
5110           } else {
5111             elements_kind = FAST_ELEMENTS;
5112           }
5113           RETURN_FAILURE_ON_EXCEPTION(
5114               isolate, TransitionElements(js_object, elements_kind, isolate));
5115         }
5116       } else {
5117         ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
5118                !IsFastElementsKind(elements_kind));
5119       }
5120     }
5121   } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
5122     // Fast case for string indexing using [] with a smi index.
5123     Handle<String> str = Handle<String>::cast(receiver_obj);
5124     int index = args.smi_at(1);
5125     if (index >= 0 && index < str->length()) {
5126       return *GetCharAt(str, index);
5127     }
5128   }
5129 
5130   // Fall back to GetObjectProperty.
5131   Handle<Object> result;
5132   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5133       isolate, result,
5134       Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
5135   return *result;
5136 }
5137 
5138 
IsValidAccessor(Handle<Object> obj)5139 static bool IsValidAccessor(Handle<Object> obj) {
5140   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
5141 }
5142 
5143 
5144 // Implements part of 8.12.9 DefineOwnProperty.
5145 // There are 3 cases that lead here:
5146 // Step 4b - define a new accessor property.
5147 // Steps 9c & 12 - replace an existing data property with an accessor property.
5148 // Step 12 - update an existing accessor property with an accessor or generic
5149 //           descriptor.
RUNTIME_FUNCTION(Runtime_DefineOrRedefineAccessorProperty)5150 RUNTIME_FUNCTION(Runtime_DefineOrRedefineAccessorProperty) {
5151   HandleScope scope(isolate);
5152   ASSERT(args.length() == 5);
5153   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5154   RUNTIME_ASSERT(!obj->IsNull());
5155   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5156   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
5157   RUNTIME_ASSERT(IsValidAccessor(getter));
5158   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
5159   RUNTIME_ASSERT(IsValidAccessor(setter));
5160   CONVERT_SMI_ARG_CHECKED(unchecked, 4);
5161   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5162   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5163 
5164   bool fast = obj->HasFastProperties();
5165   // DefineAccessor checks access rights.
5166   JSObject::DefineAccessor(obj, name, getter, setter, attr);
5167   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5168   if (fast) JSObject::TransformToFastProperties(obj, 0);
5169   return isolate->heap()->undefined_value();
5170 }
5171 
5172 
5173 // Implements part of 8.12.9 DefineOwnProperty.
5174 // There are 3 cases that lead here:
5175 // Step 4a - define a new data property.
5176 // Steps 9b & 12 - replace an existing accessor property with a data property.
5177 // Step 12 - update an existing data property with a data or generic
5178 //           descriptor.
RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty)5179 RUNTIME_FUNCTION(Runtime_DefineOrRedefineDataProperty) {
5180   HandleScope scope(isolate);
5181   ASSERT(args.length() == 4);
5182   CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
5183   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5184   CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
5185   CONVERT_SMI_ARG_CHECKED(unchecked, 3);
5186   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5187   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5188 
5189   // Check access rights if needed.
5190   if (js_object->IsAccessCheckNeeded() &&
5191       !isolate->MayNamedAccess(js_object, name, v8::ACCESS_SET)) {
5192     return isolate->heap()->undefined_value();
5193   }
5194 
5195   LookupResult lookup(isolate);
5196   js_object->LookupOwnRealNamedProperty(name, &lookup);
5197 
5198   // Take special care when attributes are different and there is already
5199   // a property. For simplicity we normalize the property which enables us
5200   // to not worry about changing the instance_descriptor and creating a new
5201   // map. The current version of SetObjectProperty does not handle attributes
5202   // correctly in the case where a property is a field and is reset with
5203   // new attributes.
5204   if (lookup.IsFound() &&
5205       (attr != lookup.GetAttributes() || lookup.IsPropertyCallbacks())) {
5206     // New attributes - normalize to avoid writing to instance descriptor
5207     if (js_object->IsJSGlobalProxy()) {
5208       // Since the result is a property, the prototype will exist so
5209       // we don't have to check for null.
5210       js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5211     }
5212 
5213     if (attr != lookup.GetAttributes() ||
5214         (lookup.IsPropertyCallbacks() &&
5215          !lookup.GetCallbackObject()->IsAccessorInfo())) {
5216       JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
5217     }
5218 
5219     // Use IgnoreAttributes version since a readonly property may be
5220     // overridden and SetProperty does not allow this.
5221     Handle<Object> result;
5222     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5223         isolate, result,
5224         JSObject::SetOwnPropertyIgnoreAttributes(
5225             js_object, name, obj_value, attr,
5226             Object::OPTIMAL_REPRESENTATION,
5227             ALLOW_AS_CONSTANT,
5228             JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
5229             JSReceiver::MAY_BE_STORE_FROM_KEYED,
5230             JSObject::DONT_FORCE_FIELD));
5231     return *result;
5232   }
5233 
5234   Handle<Object> result;
5235   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5236       isolate, result,
5237       Runtime::ForceSetObjectProperty(
5238           js_object, name, obj_value, attr,
5239           JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED));
5240   return *result;
5241 }
5242 
5243 
5244 // Return property without being observable by accessors or interceptors.
RUNTIME_FUNCTION(Runtime_GetDataProperty)5245 RUNTIME_FUNCTION(Runtime_GetDataProperty) {
5246   HandleScope scope(isolate);
5247   ASSERT(args.length() == 2);
5248   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5249   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5250   return *JSObject::GetDataProperty(object, key);
5251 }
5252 
5253 
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr,StrictMode strict_mode)5254 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
5255                                                Handle<Object> object,
5256                                                Handle<Object> key,
5257                                                Handle<Object> value,
5258                                                PropertyAttributes attr,
5259                                                StrictMode strict_mode) {
5260   SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5261 
5262   if (object->IsUndefined() || object->IsNull()) {
5263     Handle<Object> args[2] = { key, object };
5264     Handle<Object> error =
5265         isolate->factory()->NewTypeError("non_object_property_store",
5266                                          HandleVector(args, 2));
5267     return isolate->Throw<Object>(error);
5268   }
5269 
5270   if (object->IsJSProxy()) {
5271     Handle<Object> name_object;
5272     if (key->IsSymbol()) {
5273       name_object = key;
5274     } else {
5275       ASSIGN_RETURN_ON_EXCEPTION(
5276           isolate, name_object, Execution::ToString(isolate, key), Object);
5277     }
5278     Handle<Name> name = Handle<Name>::cast(name_object);
5279     return JSReceiver::SetProperty(Handle<JSProxy>::cast(object), name, value,
5280                                    attr,
5281                                    strict_mode);
5282   }
5283 
5284   // If the object isn't a JavaScript object, we ignore the store.
5285   if (!object->IsJSObject()) return value;
5286 
5287   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5288 
5289   // Check if the given key is an array index.
5290   uint32_t index;
5291   if (key->ToArrayIndex(&index)) {
5292     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5293     // of a string using [] notation.  We need to support this too in
5294     // JavaScript.
5295     // In the case of a String object we just need to redirect the assignment to
5296     // the underlying string if the index is in range.  Since the underlying
5297     // string does nothing with the assignment then we can ignore such
5298     // assignments.
5299     if (js_object->IsStringObjectWithCharacterAt(index)) {
5300       return value;
5301     }
5302 
5303     JSObject::ValidateElements(js_object);
5304     if (js_object->HasExternalArrayElements() ||
5305         js_object->HasFixedTypedArrayElements()) {
5306       if (!value->IsNumber() && !value->IsUndefined()) {
5307         ASSIGN_RETURN_ON_EXCEPTION(
5308             isolate, value, Execution::ToNumber(isolate, value), Object);
5309       }
5310     }
5311 
5312     MaybeHandle<Object> result = JSObject::SetElement(
5313         js_object, index, value, attr, strict_mode, true, set_mode);
5314     JSObject::ValidateElements(js_object);
5315 
5316     return result.is_null() ? result : value;
5317   }
5318 
5319   if (key->IsName()) {
5320     Handle<Name> name = Handle<Name>::cast(key);
5321     if (name->AsArrayIndex(&index)) {
5322       if (js_object->HasExternalArrayElements()) {
5323         if (!value->IsNumber() && !value->IsUndefined()) {
5324           ASSIGN_RETURN_ON_EXCEPTION(
5325               isolate, value, Execution::ToNumber(isolate, value), Object);
5326         }
5327       }
5328       return JSObject::SetElement(js_object, index, value, attr,
5329                                   strict_mode, true, set_mode);
5330     } else {
5331       if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
5332       return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5333     }
5334   }
5335 
5336   // Call-back into JavaScript to convert the key to a string.
5337   Handle<Object> converted;
5338   ASSIGN_RETURN_ON_EXCEPTION(
5339       isolate, converted, Execution::ToString(isolate, key), Object);
5340   Handle<String> name = Handle<String>::cast(converted);
5341 
5342   if (name->AsArrayIndex(&index)) {
5343     return JSObject::SetElement(js_object, index, value, attr,
5344                                 strict_mode, true, set_mode);
5345   } else {
5346     return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5347   }
5348 }
5349 
5350 
ForceSetObjectProperty(Handle<JSObject> js_object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr,JSReceiver::StoreFromKeyed store_from_keyed)5351 MaybeHandle<Object> Runtime::ForceSetObjectProperty(
5352     Handle<JSObject> js_object,
5353     Handle<Object> key,
5354     Handle<Object> value,
5355     PropertyAttributes attr,
5356     JSReceiver::StoreFromKeyed store_from_keyed) {
5357   Isolate* isolate = js_object->GetIsolate();
5358   // Check if the given key is an array index.
5359   uint32_t index;
5360   if (key->ToArrayIndex(&index)) {
5361     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5362     // of a string using [] notation.  We need to support this too in
5363     // JavaScript.
5364     // In the case of a String object we just need to redirect the assignment to
5365     // the underlying string if the index is in range.  Since the underlying
5366     // string does nothing with the assignment then we can ignore such
5367     // assignments.
5368     if (js_object->IsStringObjectWithCharacterAt(index)) {
5369       return value;
5370     }
5371 
5372     return JSObject::SetElement(js_object, index, value, attr,
5373                                 SLOPPY, false, DEFINE_PROPERTY);
5374   }
5375 
5376   if (key->IsName()) {
5377     Handle<Name> name = Handle<Name>::cast(key);
5378     if (name->AsArrayIndex(&index)) {
5379       return JSObject::SetElement(js_object, index, value, attr,
5380                                   SLOPPY, false, DEFINE_PROPERTY);
5381     } else {
5382       if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
5383       return JSObject::SetOwnPropertyIgnoreAttributes(
5384           js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION,
5385           ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
5386           store_from_keyed);
5387     }
5388   }
5389 
5390   // Call-back into JavaScript to convert the key to a string.
5391   Handle<Object> converted;
5392   ASSIGN_RETURN_ON_EXCEPTION(
5393       isolate, converted, Execution::ToString(isolate, key), Object);
5394   Handle<String> name = Handle<String>::cast(converted);
5395 
5396   if (name->AsArrayIndex(&index)) {
5397     return JSObject::SetElement(js_object, index, value, attr,
5398                                 SLOPPY, false, DEFINE_PROPERTY);
5399   } else {
5400     return JSObject::SetOwnPropertyIgnoreAttributes(
5401         js_object, name, value, attr, Object::OPTIMAL_REPRESENTATION,
5402         ALLOW_AS_CONSTANT, JSReceiver::PERFORM_EXTENSIBILITY_CHECK,
5403         store_from_keyed);
5404   }
5405 }
5406 
5407 
DeleteObjectProperty(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> key,JSReceiver::DeleteMode mode)5408 MaybeHandle<Object> Runtime::DeleteObjectProperty(Isolate* isolate,
5409                                                   Handle<JSReceiver> receiver,
5410                                                   Handle<Object> key,
5411                                                   JSReceiver::DeleteMode mode) {
5412   // Check if the given key is an array index.
5413   uint32_t index;
5414   if (key->ToArrayIndex(&index)) {
5415     // In Firefox/SpiderMonkey, Safari and Opera you can access the
5416     // characters of a string using [] notation.  In the case of a
5417     // String object we just need to redirect the deletion to the
5418     // underlying string if the index is in range.  Since the
5419     // underlying string does nothing with the deletion, we can ignore
5420     // such deletions.
5421     if (receiver->IsStringObjectWithCharacterAt(index)) {
5422       return isolate->factory()->true_value();
5423     }
5424 
5425     return JSReceiver::DeleteElement(receiver, index, mode);
5426   }
5427 
5428   Handle<Name> name;
5429   if (key->IsName()) {
5430     name = Handle<Name>::cast(key);
5431   } else {
5432     // Call-back into JavaScript to convert the key to a string.
5433     Handle<Object> converted;
5434     ASSIGN_RETURN_ON_EXCEPTION(
5435         isolate, converted, Execution::ToString(isolate, key), Object);
5436     name = Handle<String>::cast(converted);
5437   }
5438 
5439   if (name->IsString()) name = String::Flatten(Handle<String>::cast(name));
5440   return JSReceiver::DeleteProperty(receiver, name, mode);
5441 }
5442 
5443 
RUNTIME_FUNCTION(Runtime_SetHiddenProperty)5444 RUNTIME_FUNCTION(Runtime_SetHiddenProperty) {
5445   HandleScope scope(isolate);
5446   RUNTIME_ASSERT(args.length() == 3);
5447 
5448   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5449   CONVERT_ARG_HANDLE_CHECKED(String, key, 1);
5450   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5451   RUNTIME_ASSERT(key->IsUniqueName());
5452   return *JSObject::SetHiddenProperty(object, key, value);
5453 }
5454 
5455 
RUNTIME_FUNCTION(Runtime_SetProperty)5456 RUNTIME_FUNCTION(Runtime_SetProperty) {
5457   HandleScope scope(isolate);
5458   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5459 
5460   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5461   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5462   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5463   CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5464   RUNTIME_ASSERT(
5465       (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5466   // Compute attributes.
5467   PropertyAttributes attributes =
5468       static_cast<PropertyAttributes>(unchecked_attributes);
5469 
5470   StrictMode strict_mode = SLOPPY;
5471   if (args.length() == 5) {
5472     CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_arg, 4);
5473     strict_mode = strict_mode_arg;
5474   }
5475 
5476   Handle<Object> result;
5477   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5478       isolate, result,
5479       Runtime::SetObjectProperty(
5480           isolate, object, key, value, attributes, strict_mode));
5481   return *result;
5482 }
5483 
5484 
RUNTIME_FUNCTION(Runtime_TransitionElementsKind)5485 RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
5486   HandleScope scope(isolate);
5487   RUNTIME_ASSERT(args.length() == 2);
5488   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5489   CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5490   JSObject::TransitionElementsKind(array, map->elements_kind());
5491   return *array;
5492 }
5493 
5494 
5495 // Set the native flag on the function.
5496 // This is used to decide if we should transform null and undefined
5497 // into the global object when doing call and apply.
RUNTIME_FUNCTION(Runtime_SetNativeFlag)5498 RUNTIME_FUNCTION(Runtime_SetNativeFlag) {
5499   SealHandleScope shs(isolate);
5500   RUNTIME_ASSERT(args.length() == 1);
5501 
5502   CONVERT_ARG_CHECKED(Object, object, 0);
5503 
5504   if (object->IsJSFunction()) {
5505     JSFunction* func = JSFunction::cast(object);
5506     func->shared()->set_native(true);
5507   }
5508   return isolate->heap()->undefined_value();
5509 }
5510 
5511 
RUNTIME_FUNCTION(Runtime_SetInlineBuiltinFlag)5512 RUNTIME_FUNCTION(Runtime_SetInlineBuiltinFlag) {
5513   SealHandleScope shs(isolate);
5514   RUNTIME_ASSERT(args.length() == 1);
5515   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5516 
5517   if (object->IsJSFunction()) {
5518     JSFunction* func = JSFunction::cast(*object);
5519     func->shared()->set_inline_builtin(true);
5520   }
5521   return isolate->heap()->undefined_value();
5522 }
5523 
5524 
RUNTIME_FUNCTION(Runtime_StoreArrayLiteralElement)5525 RUNTIME_FUNCTION(Runtime_StoreArrayLiteralElement) {
5526   HandleScope scope(isolate);
5527   RUNTIME_ASSERT(args.length() == 5);
5528   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5529   CONVERT_SMI_ARG_CHECKED(store_index, 1);
5530   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5531   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5532   CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5533 
5534   Object* raw_literal_cell = literals->get(literal_index);
5535   JSArray* boilerplate = NULL;
5536   if (raw_literal_cell->IsAllocationSite()) {
5537     AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5538     boilerplate = JSArray::cast(site->transition_info());
5539   } else {
5540     boilerplate = JSArray::cast(raw_literal_cell);
5541   }
5542   Handle<JSArray> boilerplate_object(boilerplate);
5543   ElementsKind elements_kind = object->GetElementsKind();
5544   ASSERT(IsFastElementsKind(elements_kind));
5545   // Smis should never trigger transitions.
5546   ASSERT(!value->IsSmi());
5547 
5548   if (value->IsNumber()) {
5549     ASSERT(IsFastSmiElementsKind(elements_kind));
5550     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5551         ? FAST_HOLEY_DOUBLE_ELEMENTS
5552         : FAST_DOUBLE_ELEMENTS;
5553     if (IsMoreGeneralElementsKindTransition(
5554             boilerplate_object->GetElementsKind(),
5555             transitioned_kind)) {
5556       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5557     }
5558     JSObject::TransitionElementsKind(object, transitioned_kind);
5559     ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
5560     FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5561     HeapNumber* number = HeapNumber::cast(*value);
5562     double_array->set(store_index, number->Number());
5563   } else {
5564     if (!IsFastObjectElementsKind(elements_kind)) {
5565       ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5566           ? FAST_HOLEY_ELEMENTS
5567           : FAST_ELEMENTS;
5568       JSObject::TransitionElementsKind(object, transitioned_kind);
5569       ElementsKind boilerplate_elements_kind =
5570           boilerplate_object->GetElementsKind();
5571       if (IsMoreGeneralElementsKindTransition(boilerplate_elements_kind,
5572                                               transitioned_kind)) {
5573         JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5574       }
5575     }
5576     FixedArray* object_array = FixedArray::cast(object->elements());
5577     object_array->set(store_index, *value);
5578   }
5579   return *object;
5580 }
5581 
5582 
5583 // Check whether debugger and is about to step into the callback that is passed
5584 // to a built-in function such as Array.forEach.
RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping)5585 RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
5586   ASSERT(args.length() == 1);
5587   if (!isolate->debug()->is_active() || !isolate->debug()->StepInActive()) {
5588     return isolate->heap()->false_value();
5589   }
5590   CONVERT_ARG_CHECKED(Object, callback, 0);
5591   // We do not step into the callback if it's a builtin or not even a function.
5592   return isolate->heap()->ToBoolean(
5593       callback->IsJSFunction() && !JSFunction::cast(callback)->IsBuiltin());
5594 }
5595 
5596 
5597 // Set one shot breakpoints for the callback function that is passed to a
5598 // built-in function such as Array.forEach to enable stepping into the callback.
RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping)5599 RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
5600   ASSERT(args.length() == 1);
5601   Debug* debug = isolate->debug();
5602   if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5603   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
5604   HandleScope scope(isolate);
5605   // When leaving the callback, step out has been activated, but not performed
5606   // if we do not leave the builtin.  To be able to step into the callback
5607   // again, we need to clear the step out at this point.
5608   debug->ClearStepOut();
5609   debug->FloodWithOneShot(callback);
5610   return isolate->heap()->undefined_value();
5611 }
5612 
5613 
5614 // The argument is a closure that is kept until the epilogue is called.
5615 // On exception, the closure is called, which returns the promise if the
5616 // exception is considered uncaught, or undefined otherwise.
RUNTIME_FUNCTION(Runtime_DebugPromiseHandlePrologue)5617 RUNTIME_FUNCTION(Runtime_DebugPromiseHandlePrologue) {
5618   ASSERT(args.length() == 1);
5619   HandleScope scope(isolate);
5620   CONVERT_ARG_HANDLE_CHECKED(JSFunction, promise_getter, 0);
5621   isolate->debug()->PromiseHandlePrologue(promise_getter);
5622   return isolate->heap()->undefined_value();
5623 }
5624 
5625 
RUNTIME_FUNCTION(Runtime_DebugPromiseHandleEpilogue)5626 RUNTIME_FUNCTION(Runtime_DebugPromiseHandleEpilogue) {
5627   ASSERT(args.length() == 0);
5628   SealHandleScope shs(isolate);
5629   isolate->debug()->PromiseHandleEpilogue();
5630   return isolate->heap()->undefined_value();
5631 }
5632 
5633 
5634 // Set an own property, even if it is READ_ONLY.  If the property does not
5635 // exist, it will be added with attributes NONE.
RUNTIME_FUNCTION(Runtime_IgnoreAttributesAndSetProperty)5636 RUNTIME_FUNCTION(Runtime_IgnoreAttributesAndSetProperty) {
5637   HandleScope scope(isolate);
5638   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
5639   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5640   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5641   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5642   // Compute attributes.
5643   PropertyAttributes attributes = NONE;
5644   if (args.length() == 4) {
5645     CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
5646     // Only attribute bits should be set.
5647     RUNTIME_ASSERT(
5648         (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5649     attributes = static_cast<PropertyAttributes>(unchecked_value);
5650   }
5651   Handle<Object> result;
5652   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5653       isolate, result,
5654       JSObject::SetOwnPropertyIgnoreAttributes(
5655           object, name, value, attributes));
5656   return *result;
5657 }
5658 
5659 
RUNTIME_FUNCTION(Runtime_DeleteProperty)5660 RUNTIME_FUNCTION(Runtime_DeleteProperty) {
5661   HandleScope scope(isolate);
5662   ASSERT(args.length() == 3);
5663   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5664   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5665   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5666   JSReceiver::DeleteMode delete_mode = strict_mode == STRICT
5667       ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
5668   Handle<Object> result;
5669   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5670       isolate, result,
5671       JSReceiver::DeleteProperty(object, key, delete_mode));
5672   return *result;
5673 }
5674 
5675 
HasOwnPropertyImplementation(Isolate * isolate,Handle<JSObject> object,Handle<Name> key)5676 static Object* HasOwnPropertyImplementation(Isolate* isolate,
5677                                             Handle<JSObject> object,
5678                                             Handle<Name> key) {
5679   if (JSReceiver::HasOwnProperty(object, key)) {
5680     return isolate->heap()->true_value();
5681   }
5682   // Handle hidden prototypes.  If there's a hidden prototype above this thing
5683   // then we have to check it for properties, because they are supposed to
5684   // look like they are on this object.
5685   Handle<Object> proto(object->GetPrototype(), isolate);
5686   if (proto->IsJSObject() &&
5687       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
5688     return HasOwnPropertyImplementation(isolate,
5689                                         Handle<JSObject>::cast(proto),
5690                                         key);
5691   }
5692   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5693   return isolate->heap()->false_value();
5694 }
5695 
5696 
RUNTIME_FUNCTION(Runtime_HasOwnProperty)5697 RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
5698   HandleScope scope(isolate);
5699   ASSERT(args.length() == 2);
5700   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
5701   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5702 
5703   uint32_t index;
5704   const bool key_is_array_index = key->AsArrayIndex(&index);
5705 
5706   // Only JS objects can have properties.
5707   if (object->IsJSObject()) {
5708     Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
5709     // Fast case: either the key is a real named property or it is not
5710     // an array index and there are no interceptors or hidden
5711     // prototypes.
5712     if (JSObject::HasRealNamedProperty(js_obj, key)) {
5713       ASSERT(!isolate->has_scheduled_exception());
5714       return isolate->heap()->true_value();
5715     } else {
5716       RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5717     }
5718     Map* map = js_obj->map();
5719     if (!key_is_array_index &&
5720         !map->has_named_interceptor() &&
5721         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5722       return isolate->heap()->false_value();
5723     }
5724     // Slow case.
5725     return HasOwnPropertyImplementation(isolate,
5726                                         Handle<JSObject>(js_obj),
5727                                         Handle<Name>(key));
5728   } else if (object->IsString() && key_is_array_index) {
5729     // Well, there is one exception:  Handle [] on strings.
5730     Handle<String> string = Handle<String>::cast(object);
5731     if (index < static_cast<uint32_t>(string->length())) {
5732       return isolate->heap()->true_value();
5733     }
5734   }
5735   return isolate->heap()->false_value();
5736 }
5737 
5738 
RUNTIME_FUNCTION(Runtime_HasProperty)5739 RUNTIME_FUNCTION(Runtime_HasProperty) {
5740   HandleScope scope(isolate);
5741   ASSERT(args.length() == 2);
5742   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5743   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5744 
5745   bool result = JSReceiver::HasProperty(receiver, key);
5746   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5747   if (isolate->has_pending_exception()) return isolate->heap()->exception();
5748   return isolate->heap()->ToBoolean(result);
5749 }
5750 
5751 
RUNTIME_FUNCTION(Runtime_HasElement)5752 RUNTIME_FUNCTION(Runtime_HasElement) {
5753   HandleScope scope(isolate);
5754   ASSERT(args.length() == 2);
5755   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5756   CONVERT_SMI_ARG_CHECKED(index, 1);
5757 
5758   bool result = JSReceiver::HasElement(receiver, index);
5759   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5760   return isolate->heap()->ToBoolean(result);
5761 }
5762 
5763 
RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable)5764 RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) {
5765   HandleScope scope(isolate);
5766   ASSERT(args.length() == 2);
5767 
5768   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5769   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5770 
5771   PropertyAttributes att = JSReceiver::GetOwnPropertyAttributes(object, key);
5772   if (att == ABSENT || (att & DONT_ENUM) != 0) {
5773     RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5774     return isolate->heap()->false_value();
5775   }
5776   ASSERT(!isolate->has_scheduled_exception());
5777   return isolate->heap()->true_value();
5778 }
5779 
5780 
RUNTIME_FUNCTION(Runtime_GetPropertyNames)5781 RUNTIME_FUNCTION(Runtime_GetPropertyNames) {
5782   HandleScope scope(isolate);
5783   ASSERT(args.length() == 1);
5784   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5785   Handle<JSArray> result;
5786 
5787   isolate->counters()->for_in()->Increment();
5788   Handle<FixedArray> elements;
5789   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5790       isolate, elements,
5791       JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
5792   return *isolate->factory()->NewJSArrayWithElements(elements);
5793 }
5794 
5795 
5796 // Returns either a FixedArray as Runtime_GetPropertyNames,
5797 // or, if the given object has an enum cache that contains
5798 // all enumerable properties of the object and its prototypes
5799 // have none, the map of the object. This is used to speed up
5800 // the check for deletions during a for-in.
RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast)5801 RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
5802   SealHandleScope shs(isolate);
5803   ASSERT(args.length() == 1);
5804 
5805   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5806 
5807   if (raw_object->IsSimpleEnum()) return raw_object->map();
5808 
5809   HandleScope scope(isolate);
5810   Handle<JSReceiver> object(raw_object);
5811   Handle<FixedArray> content;
5812   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
5813       isolate, content,
5814       JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS));
5815 
5816   // Test again, since cache may have been built by preceding call.
5817   if (object->IsSimpleEnum()) return object->map();
5818 
5819   return *content;
5820 }
5821 
5822 
5823 // Find the length of the prototype chain that is to be handled as one. If a
5824 // prototype object is hidden it is to be viewed as part of the the object it
5825 // is prototype for.
OwnPrototypeChainLength(JSObject * obj)5826 static int OwnPrototypeChainLength(JSObject* obj) {
5827   int count = 1;
5828   Object* proto = obj->GetPrototype();
5829   while (proto->IsJSObject() &&
5830          JSObject::cast(proto)->map()->is_hidden_prototype()) {
5831     count++;
5832     proto = JSObject::cast(proto)->GetPrototype();
5833   }
5834   return count;
5835 }
5836 
5837 
5838 // Return the names of the own named properties.
5839 // args[0]: object
5840 // args[1]: PropertyAttributes as int
RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames)5841 RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
5842   HandleScope scope(isolate);
5843   ASSERT(args.length() == 2);
5844   if (!args[0]->IsJSObject()) {
5845     return isolate->heap()->undefined_value();
5846   }
5847   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5848   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
5849   PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
5850 
5851   // Skip the global proxy as it has no properties and always delegates to the
5852   // real global object.
5853   if (obj->IsJSGlobalProxy()) {
5854     // Only collect names if access is permitted.
5855     if (obj->IsAccessCheckNeeded() &&
5856         !isolate->MayNamedAccess(
5857             obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5858       isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS);
5859       RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5860       return *isolate->factory()->NewJSArray(0);
5861     }
5862     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5863   }
5864 
5865   // Find the number of objects making up this.
5866   int length = OwnPrototypeChainLength(*obj);
5867 
5868   // Find the number of own properties for each of the objects.
5869   ScopedVector<int> own_property_count(length);
5870   int total_property_count = 0;
5871   Handle<JSObject> jsproto = obj;
5872   for (int i = 0; i < length; i++) {
5873     // Only collect names if access is permitted.
5874     if (jsproto->IsAccessCheckNeeded() &&
5875         !isolate->MayNamedAccess(
5876             jsproto, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
5877       isolate->ReportFailedAccessCheck(jsproto, v8::ACCESS_KEYS);
5878       RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
5879       return *isolate->factory()->NewJSArray(0);
5880     }
5881     int n;
5882     n = jsproto->NumberOfOwnProperties(filter);
5883     own_property_count[i] = n;
5884     total_property_count += n;
5885     if (i < length - 1) {
5886       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5887     }
5888   }
5889 
5890   // Allocate an array with storage for all the property names.
5891   Handle<FixedArray> names =
5892       isolate->factory()->NewFixedArray(total_property_count);
5893 
5894   // Get the property names.
5895   jsproto = obj;
5896   int next_copy_index = 0;
5897   int hidden_strings = 0;
5898   for (int i = 0; i < length; i++) {
5899     jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
5900     if (i > 0) {
5901       // Names from hidden prototypes may already have been added
5902       // for inherited function template instances. Count the duplicates
5903       // and stub them out; the final copy pass at the end ignores holes.
5904       for (int j = next_copy_index;
5905            j < next_copy_index + own_property_count[i];
5906            j++) {
5907         Object* name_from_hidden_proto = names->get(j);
5908         for (int k = 0; k < next_copy_index; k++) {
5909           if (names->get(k) != isolate->heap()->hidden_string()) {
5910             Object* name = names->get(k);
5911             if (name_from_hidden_proto == name) {
5912               names->set(j, isolate->heap()->hidden_string());
5913               hidden_strings++;
5914               break;
5915             }
5916           }
5917         }
5918       }
5919     }
5920     next_copy_index += own_property_count[i];
5921 
5922     // Hidden properties only show up if the filter does not skip strings.
5923     if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
5924       hidden_strings++;
5925     }
5926     if (i < length - 1) {
5927       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5928     }
5929   }
5930 
5931   // Filter out name of hidden properties object and
5932   // hidden prototype duplicates.
5933   if (hidden_strings > 0) {
5934     Handle<FixedArray> old_names = names;
5935     names = isolate->factory()->NewFixedArray(
5936         names->length() - hidden_strings);
5937     int dest_pos = 0;
5938     for (int i = 0; i < total_property_count; i++) {
5939       Object* name = old_names->get(i);
5940       if (name == isolate->heap()->hidden_string()) {
5941         hidden_strings--;
5942         continue;
5943       }
5944       names->set(dest_pos++, name);
5945     }
5946     ASSERT_EQ(0, hidden_strings);
5947   }
5948 
5949   return *isolate->factory()->NewJSArrayWithElements(names);
5950 }
5951 
5952 
5953 // Return the names of the own indexed properties.
5954 // args[0]: object
RUNTIME_FUNCTION(Runtime_GetOwnElementNames)5955 RUNTIME_FUNCTION(Runtime_GetOwnElementNames) {
5956   HandleScope scope(isolate);
5957   ASSERT(args.length() == 1);
5958   if (!args[0]->IsJSObject()) {
5959     return isolate->heap()->undefined_value();
5960   }
5961   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5962 
5963   int n = obj->NumberOfOwnElements(static_cast<PropertyAttributes>(NONE));
5964   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5965   obj->GetOwnElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5966   return *isolate->factory()->NewJSArrayWithElements(names);
5967 }
5968 
5969 
5970 // Return information on whether an object has a named or indexed interceptor.
5971 // args[0]: object
RUNTIME_FUNCTION(Runtime_GetInterceptorInfo)5972 RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
5973   HandleScope scope(isolate);
5974   ASSERT(args.length() == 1);
5975   if (!args[0]->IsJSObject()) {
5976     return Smi::FromInt(0);
5977   }
5978   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5979 
5980   int result = 0;
5981   if (obj->HasNamedInterceptor()) result |= 2;
5982   if (obj->HasIndexedInterceptor()) result |= 1;
5983 
5984   return Smi::FromInt(result);
5985 }
5986 
5987 
5988 // Return property names from named interceptor.
5989 // args[0]: object
RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames)5990 RUNTIME_FUNCTION(Runtime_GetNamedInterceptorPropertyNames) {
5991   HandleScope scope(isolate);
5992   ASSERT(args.length() == 1);
5993   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5994 
5995   if (obj->HasNamedInterceptor()) {
5996     Handle<JSObject> result;
5997     if (JSObject::GetKeysForNamedInterceptor(obj, obj).ToHandle(&result)) {
5998       return *result;
5999     }
6000   }
6001   return isolate->heap()->undefined_value();
6002 }
6003 
6004 
6005 // Return element names from indexed interceptor.
6006 // args[0]: object
RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames)6007 RUNTIME_FUNCTION(Runtime_GetIndexedInterceptorElementNames) {
6008   HandleScope scope(isolate);
6009   ASSERT(args.length() == 1);
6010   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
6011 
6012   if (obj->HasIndexedInterceptor()) {
6013     Handle<JSObject> result;
6014     if (JSObject::GetKeysForIndexedInterceptor(obj, obj).ToHandle(&result)) {
6015       return *result;
6016     }
6017   }
6018   return isolate->heap()->undefined_value();
6019 }
6020 
6021 
RUNTIME_FUNCTION(Runtime_OwnKeys)6022 RUNTIME_FUNCTION(Runtime_OwnKeys) {
6023   HandleScope scope(isolate);
6024   ASSERT(args.length() == 1);
6025   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
6026   Handle<JSObject> object(raw_object);
6027 
6028   if (object->IsJSGlobalProxy()) {
6029     // Do access checks before going to the global object.
6030     if (object->IsAccessCheckNeeded() &&
6031         !isolate->MayNamedAccess(
6032             object, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) {
6033       isolate->ReportFailedAccessCheck(object, v8::ACCESS_KEYS);
6034       RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
6035       return *isolate->factory()->NewJSArray(0);
6036     }
6037 
6038     Handle<Object> proto(object->GetPrototype(), isolate);
6039     // If proxy is detached we simply return an empty array.
6040     if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
6041     object = Handle<JSObject>::cast(proto);
6042   }
6043 
6044   Handle<FixedArray> contents;
6045   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6046       isolate, contents,
6047       JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY));
6048 
6049   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
6050   // property array and since the result is mutable we have to create
6051   // a fresh clone on each invocation.
6052   int length = contents->length();
6053   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
6054   for (int i = 0; i < length; i++) {
6055     Object* entry = contents->get(i);
6056     if (entry->IsString()) {
6057       copy->set(i, entry);
6058     } else {
6059       ASSERT(entry->IsNumber());
6060       HandleScope scope(isolate);
6061       Handle<Object> entry_handle(entry, isolate);
6062       Handle<Object> entry_str =
6063           isolate->factory()->NumberToString(entry_handle);
6064       copy->set(i, *entry_str);
6065     }
6066   }
6067   return *isolate->factory()->NewJSArrayWithElements(copy);
6068 }
6069 
6070 
RUNTIME_FUNCTION(Runtime_GetArgumentsProperty)6071 RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) {
6072   SealHandleScope shs(isolate);
6073   ASSERT(args.length() == 1);
6074   CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
6075 
6076   // Compute the frame holding the arguments.
6077   JavaScriptFrameIterator it(isolate);
6078   it.AdvanceToArgumentsFrame();
6079   JavaScriptFrame* frame = it.frame();
6080 
6081   // Get the actual number of provided arguments.
6082   const uint32_t n = frame->ComputeParametersCount();
6083 
6084   // Try to convert the key to an index. If successful and within
6085   // index return the the argument from the frame.
6086   uint32_t index;
6087   if (raw_key->ToArrayIndex(&index) && index < n) {
6088     return frame->GetParameter(index);
6089   }
6090 
6091   HandleScope scope(isolate);
6092   if (raw_key->IsSymbol()) {
6093     // Lookup in the initial Object.prototype object.
6094     Handle<Object> result;
6095     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6096         isolate, result,
6097         Object::GetProperty(isolate->initial_object_prototype(),
6098                             Handle<Symbol>::cast(raw_key)));
6099     return *result;
6100   }
6101 
6102   // Convert the key to a string.
6103   Handle<Object> converted;
6104   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6105       isolate, converted, Execution::ToString(isolate, raw_key));
6106   Handle<String> key = Handle<String>::cast(converted);
6107 
6108   // Try to convert the string key into an array index.
6109   if (key->AsArrayIndex(&index)) {
6110     if (index < n) {
6111       return frame->GetParameter(index);
6112     } else {
6113       Handle<Object> initial_prototype(isolate->initial_object_prototype());
6114       Handle<Object> result;
6115       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6116           isolate, result,
6117           Object::GetElement(isolate, initial_prototype, index));
6118       return *result;
6119     }
6120   }
6121 
6122   // Handle special arguments properties.
6123   if (String::Equals(isolate->factory()->length_string(), key)) {
6124     return Smi::FromInt(n);
6125   }
6126   if (String::Equals(isolate->factory()->callee_string(), key)) {
6127     JSFunction* function = frame->function();
6128     if (function->shared()->strict_mode() == STRICT) {
6129       return isolate->Throw(*isolate->factory()->NewTypeError(
6130           "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
6131     }
6132     return function;
6133   }
6134 
6135   // Lookup in the initial Object.prototype object.
6136   Handle<Object> result;
6137   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6138       isolate, result,
6139       Object::GetProperty(isolate->initial_object_prototype(), key));
6140   return *result;
6141 }
6142 
6143 
RUNTIME_FUNCTION(Runtime_ToFastProperties)6144 RUNTIME_FUNCTION(Runtime_ToFastProperties) {
6145   HandleScope scope(isolate);
6146   ASSERT(args.length() == 1);
6147   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
6148   if (object->IsJSObject() && !object->IsGlobalObject()) {
6149     JSObject::TransformToFastProperties(Handle<JSObject>::cast(object), 0);
6150   }
6151   return *object;
6152 }
6153 
6154 
RUNTIME_FUNCTION(Runtime_ToBool)6155 RUNTIME_FUNCTION(Runtime_ToBool) {
6156   SealHandleScope shs(isolate);
6157   ASSERT(args.length() == 1);
6158   CONVERT_ARG_CHECKED(Object, object, 0);
6159 
6160   return isolate->heap()->ToBoolean(object->BooleanValue());
6161 }
6162 
6163 
6164 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
6165 // Possible optimizations: put the type string into the oddballs.
RUNTIME_FUNCTION(Runtime_Typeof)6166 RUNTIME_FUNCTION(Runtime_Typeof) {
6167   SealHandleScope shs(isolate);
6168   ASSERT(args.length() == 1);
6169   CONVERT_ARG_CHECKED(Object, obj, 0);
6170   if (obj->IsNumber()) return isolate->heap()->number_string();
6171   HeapObject* heap_obj = HeapObject::cast(obj);
6172 
6173   // typeof an undetectable object is 'undefined'
6174   if (heap_obj->map()->is_undetectable()) {
6175     return isolate->heap()->undefined_string();
6176   }
6177 
6178   InstanceType instance_type = heap_obj->map()->instance_type();
6179   if (instance_type < FIRST_NONSTRING_TYPE) {
6180     return isolate->heap()->string_string();
6181   }
6182 
6183   switch (instance_type) {
6184     case ODDBALL_TYPE:
6185       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
6186         return isolate->heap()->boolean_string();
6187       }
6188       if (heap_obj->IsNull()) {
6189         return FLAG_harmony_typeof
6190             ? isolate->heap()->null_string()
6191             : isolate->heap()->object_string();
6192       }
6193       ASSERT(heap_obj->IsUndefined());
6194       return isolate->heap()->undefined_string();
6195     case SYMBOL_TYPE:
6196       return isolate->heap()->symbol_string();
6197     case JS_FUNCTION_TYPE:
6198     case JS_FUNCTION_PROXY_TYPE:
6199       return isolate->heap()->function_string();
6200     default:
6201       // For any kind of object not handled above, the spec rule for
6202       // host objects gives that it is okay to return "object"
6203       return isolate->heap()->object_string();
6204   }
6205 }
6206 
6207 
AreDigits(const uint8_t * s,int from,int to)6208 static bool AreDigits(const uint8_t*s, int from, int to) {
6209   for (int i = from; i < to; i++) {
6210     if (s[i] < '0' || s[i] > '9') return false;
6211   }
6212 
6213   return true;
6214 }
6215 
6216 
ParseDecimalInteger(const uint8_t * s,int from,int to)6217 static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
6218   ASSERT(to - from < 10);  // Overflow is not possible.
6219   ASSERT(from < to);
6220   int d = s[from] - '0';
6221 
6222   for (int i = from + 1; i < to; i++) {
6223     d = 10 * d + (s[i] - '0');
6224   }
6225 
6226   return d;
6227 }
6228 
6229 
RUNTIME_FUNCTION(Runtime_StringToNumber)6230 RUNTIME_FUNCTION(Runtime_StringToNumber) {
6231   HandleScope handle_scope(isolate);
6232   ASSERT(args.length() == 1);
6233   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6234   subject = String::Flatten(subject);
6235 
6236   // Fast case: short integer or some sorts of junk values.
6237   if (subject->IsSeqOneByteString()) {
6238     int len = subject->length();
6239     if (len == 0) return Smi::FromInt(0);
6240 
6241     DisallowHeapAllocation no_gc;
6242     uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
6243     bool minus = (data[0] == '-');
6244     int start_pos = (minus ? 1 : 0);
6245 
6246     if (start_pos == len) {
6247       return isolate->heap()->nan_value();
6248     } else if (data[start_pos] > '9') {
6249       // Fast check for a junk value. A valid string may start from a
6250       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
6251       // or the 'I' character ('Infinity'). All of that have codes not greater
6252       // than '9' except 'I' and &nbsp;.
6253       if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
6254         return isolate->heap()->nan_value();
6255       }
6256     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
6257       // The maximal/minimal smi has 10 digits. If the string has less digits
6258       // we know it will fit into the smi-data type.
6259       int d = ParseDecimalInteger(data, start_pos, len);
6260       if (minus) {
6261         if (d == 0) return isolate->heap()->minus_zero_value();
6262         d = -d;
6263       } else if (!subject->HasHashCode() &&
6264                  len <= String::kMaxArrayIndexSize &&
6265                  (len == 1 || data[0] != '0')) {
6266         // String hash is not calculated yet but all the data are present.
6267         // Update the hash field to speed up sequential convertions.
6268         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
6269 #ifdef DEBUG
6270         subject->Hash();  // Force hash calculation.
6271         ASSERT_EQ(static_cast<int>(subject->hash_field()),
6272                   static_cast<int>(hash));
6273 #endif
6274         subject->set_hash_field(hash);
6275       }
6276       return Smi::FromInt(d);
6277     }
6278   }
6279 
6280   // Slower case.
6281   int flags = ALLOW_HEX;
6282   if (FLAG_harmony_numeric_literals) {
6283     // The current spec draft has not updated "ToNumber Applied to the String
6284     // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6285     flags |= ALLOW_OCTAL | ALLOW_BINARY;
6286   }
6287 
6288   return *isolate->factory()->NewNumber(StringToDouble(
6289       isolate->unicode_cache(), *subject, flags));
6290 }
6291 
6292 
RUNTIME_FUNCTION(Runtime_NewString)6293 RUNTIME_FUNCTION(Runtime_NewString) {
6294   HandleScope scope(isolate);
6295   ASSERT(args.length() == 2);
6296   CONVERT_SMI_ARG_CHECKED(length, 0);
6297   CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6298   if (length == 0) return isolate->heap()->empty_string();
6299   Handle<String> result;
6300   if (is_one_byte) {
6301     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6302         isolate, result, isolate->factory()->NewRawOneByteString(length));
6303   } else {
6304     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6305         isolate, result, isolate->factory()->NewRawTwoByteString(length));
6306   }
6307   return *result;
6308 }
6309 
6310 
RUNTIME_FUNCTION(Runtime_TruncateString)6311 RUNTIME_FUNCTION(Runtime_TruncateString) {
6312   HandleScope scope(isolate);
6313   ASSERT(args.length() == 2);
6314   CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
6315   CONVERT_SMI_ARG_CHECKED(new_length, 1);
6316   RUNTIME_ASSERT(new_length >= 0);
6317   return *SeqString::Truncate(string, new_length);
6318 }
6319 
6320 
RUNTIME_FUNCTION(Runtime_URIEscape)6321 RUNTIME_FUNCTION(Runtime_URIEscape) {
6322   HandleScope scope(isolate);
6323   ASSERT(args.length() == 1);
6324   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6325   Handle<String> string = String::Flatten(source);
6326   ASSERT(string->IsFlat());
6327   Handle<String> result;
6328   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6329       isolate, result,
6330       string->IsOneByteRepresentationUnderneath()
6331             ? URIEscape::Escape<uint8_t>(isolate, source)
6332             : URIEscape::Escape<uc16>(isolate, source));
6333   return *result;
6334 }
6335 
6336 
RUNTIME_FUNCTION(Runtime_URIUnescape)6337 RUNTIME_FUNCTION(Runtime_URIUnescape) {
6338   HandleScope scope(isolate);
6339   ASSERT(args.length() == 1);
6340   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6341   Handle<String> string = String::Flatten(source);
6342   ASSERT(string->IsFlat());
6343   Handle<String> result;
6344   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6345       isolate, result,
6346       string->IsOneByteRepresentationUnderneath()
6347             ? URIUnescape::Unescape<uint8_t>(isolate, source)
6348             : URIUnescape::Unescape<uc16>(isolate, source));
6349   return *result;
6350 }
6351 
6352 
RUNTIME_FUNCTION(Runtime_QuoteJSONString)6353 RUNTIME_FUNCTION(Runtime_QuoteJSONString) {
6354   HandleScope scope(isolate);
6355   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6356   ASSERT(args.length() == 1);
6357   Handle<Object> result;
6358   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6359       isolate, result, BasicJsonStringifier::StringifyString(isolate, string));
6360   return *result;
6361 }
6362 
6363 
RUNTIME_FUNCTION(Runtime_BasicJSONStringify)6364 RUNTIME_FUNCTION(Runtime_BasicJSONStringify) {
6365   HandleScope scope(isolate);
6366   ASSERT(args.length() == 1);
6367   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
6368   BasicJsonStringifier stringifier(isolate);
6369   Handle<Object> result;
6370   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6371       isolate, result, stringifier.Stringify(object));
6372   return *result;
6373 }
6374 
6375 
RUNTIME_FUNCTION(Runtime_StringParseInt)6376 RUNTIME_FUNCTION(Runtime_StringParseInt) {
6377   HandleScope handle_scope(isolate);
6378   ASSERT(args.length() == 2);
6379   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6380   CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
6381   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6382 
6383   subject = String::Flatten(subject);
6384   double value;
6385 
6386   { DisallowHeapAllocation no_gc;
6387     String::FlatContent flat = subject->GetFlatContent();
6388 
6389     // ECMA-262 section 15.1.2.3, empty string is NaN
6390     if (flat.IsAscii()) {
6391       value = StringToInt(
6392           isolate->unicode_cache(), flat.ToOneByteVector(), radix);
6393     } else {
6394       value = StringToInt(
6395           isolate->unicode_cache(), flat.ToUC16Vector(), radix);
6396     }
6397   }
6398 
6399   return *isolate->factory()->NewNumber(value);
6400 }
6401 
6402 
RUNTIME_FUNCTION(Runtime_StringParseFloat)6403 RUNTIME_FUNCTION(Runtime_StringParseFloat) {
6404   HandleScope shs(isolate);
6405   ASSERT(args.length() == 1);
6406   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6407 
6408   subject = String::Flatten(subject);
6409   double value = StringToDouble(
6410       isolate->unicode_cache(), *subject, ALLOW_TRAILING_JUNK, OS::nan_value());
6411 
6412   return *isolate->factory()->NewNumber(value);
6413 }
6414 
6415 
ToUpperOverflows(uc32 character)6416 static inline bool ToUpperOverflows(uc32 character) {
6417   // y with umlauts and the micro sign are the only characters that stop
6418   // fitting into one-byte when converting to uppercase.
6419   static const uc32 yuml_code = 0xff;
6420   static const uc32 micro_code = 0xb5;
6421   return (character == yuml_code || character == micro_code);
6422 }
6423 
6424 
6425 template <class Converter>
ConvertCaseHelper(Isolate * isolate,String * string,SeqString * result,int result_length,unibrow::Mapping<Converter,128> * mapping)6426 MUST_USE_RESULT static Object* ConvertCaseHelper(
6427     Isolate* isolate,
6428     String* string,
6429     SeqString* result,
6430     int result_length,
6431     unibrow::Mapping<Converter, 128>* mapping) {
6432   DisallowHeapAllocation no_gc;
6433   // We try this twice, once with the assumption that the result is no longer
6434   // than the input and, if that assumption breaks, again with the exact
6435   // length.  This may not be pretty, but it is nicer than what was here before
6436   // and I hereby claim my vaffel-is.
6437   //
6438   // NOTE: This assumes that the upper/lower case of an ASCII
6439   // character is also ASCII.  This is currently the case, but it
6440   // might break in the future if we implement more context and locale
6441   // dependent upper/lower conversions.
6442   bool has_changed_character = false;
6443 
6444   // Convert all characters to upper case, assuming that they will fit
6445   // in the buffer
6446   Access<ConsStringIteratorOp> op(
6447       isolate->runtime_state()->string_iterator());
6448   StringCharacterStream stream(string, op.value());
6449   unibrow::uchar chars[Converter::kMaxWidth];
6450   // We can assume that the string is not empty
6451   uc32 current = stream.GetNext();
6452   bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
6453   for (int i = 0; i < result_length;) {
6454     bool has_next = stream.HasMore();
6455     uc32 next = has_next ? stream.GetNext() : 0;
6456     int char_length = mapping->get(current, next, chars);
6457     if (char_length == 0) {
6458       // The case conversion of this character is the character itself.
6459       result->Set(i, current);
6460       i++;
6461     } else if (char_length == 1 &&
6462                (ignore_overflow || !ToUpperOverflows(current))) {
6463       // Common case: converting the letter resulted in one character.
6464       ASSERT(static_cast<uc32>(chars[0]) != current);
6465       result->Set(i, chars[0]);
6466       has_changed_character = true;
6467       i++;
6468     } else if (result_length == string->length()) {
6469       bool overflows = ToUpperOverflows(current);
6470       // We've assumed that the result would be as long as the
6471       // input but here is a character that converts to several
6472       // characters.  No matter, we calculate the exact length
6473       // of the result and try the whole thing again.
6474       //
6475       // Note that this leaves room for optimization.  We could just
6476       // memcpy what we already have to the result string.  Also,
6477       // the result string is the last object allocated we could
6478       // "realloc" it and probably, in the vast majority of cases,
6479       // extend the existing string to be able to hold the full
6480       // result.
6481       int next_length = 0;
6482       if (has_next) {
6483         next_length = mapping->get(next, 0, chars);
6484         if (next_length == 0) next_length = 1;
6485       }
6486       int current_length = i + char_length + next_length;
6487       while (stream.HasMore()) {
6488         current = stream.GetNext();
6489         overflows |= ToUpperOverflows(current);
6490         // NOTE: we use 0 as the next character here because, while
6491         // the next character may affect what a character converts to,
6492         // it does not in any case affect the length of what it convert
6493         // to.
6494         int char_length = mapping->get(current, 0, chars);
6495         if (char_length == 0) char_length = 1;
6496         current_length += char_length;
6497         if (current_length > String::kMaxLength) {
6498           AllowHeapAllocation allocate_error_and_return;
6499           return isolate->ThrowInvalidStringLength();
6500         }
6501       }
6502       // Try again with the real length.  Return signed if we need
6503       // to allocate a two-byte string for to uppercase.
6504       return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
6505                                              : Smi::FromInt(current_length);
6506     } else {
6507       for (int j = 0; j < char_length; j++) {
6508         result->Set(i, chars[j]);
6509         i++;
6510       }
6511       has_changed_character = true;
6512     }
6513     current = next;
6514   }
6515   if (has_changed_character) {
6516     return result;
6517   } else {
6518     // If we didn't actually change anything in doing the conversion
6519     // we simple return the result and let the converted string
6520     // become garbage; there is no reason to keep two identical strings
6521     // alive.
6522     return string;
6523   }
6524 }
6525 
6526 
6527 namespace {
6528 
6529 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6530 static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6531 
6532 // Given a word and two range boundaries returns a word with high bit
6533 // set in every byte iff the corresponding input byte was strictly in
6534 // the range (m, n). All the other bits in the result are cleared.
6535 // This function is only useful when it can be inlined and the
6536 // boundaries are statically known.
6537 // Requires: all bytes in the input word and the boundaries must be
6538 // ASCII (less than 0x7F).
AsciiRangeMask(uintptr_t w,char m,char n)6539 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6540   // Use strict inequalities since in edge cases the function could be
6541   // further simplified.
6542   ASSERT(0 < m && m < n);
6543   // Has high bit set in every w byte less than n.
6544   uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6545   // Has high bit set in every w byte greater than m.
6546   uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6547   return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6548 }
6549 
6550 
6551 #ifdef DEBUG
CheckFastAsciiConvert(char * dst,const char * src,int length,bool changed,bool is_to_lower)6552 static bool CheckFastAsciiConvert(char* dst,
6553                                   const char* src,
6554                                   int length,
6555                                   bool changed,
6556                                   bool is_to_lower) {
6557   bool expected_changed = false;
6558   for (int i = 0; i < length; i++) {
6559     if (dst[i] == src[i]) continue;
6560     expected_changed = true;
6561     if (is_to_lower) {
6562       ASSERT('A' <= src[i] && src[i] <= 'Z');
6563       ASSERT(dst[i] == src[i] + ('a' - 'A'));
6564     } else {
6565       ASSERT('a' <= src[i] && src[i] <= 'z');
6566       ASSERT(dst[i] == src[i] - ('a' - 'A'));
6567     }
6568   }
6569   return (expected_changed == changed);
6570 }
6571 #endif
6572 
6573 
6574 template<class Converter>
FastAsciiConvert(char * dst,const char * src,int length,bool * changed_out)6575 static bool FastAsciiConvert(char* dst,
6576                              const char* src,
6577                              int length,
6578                              bool* changed_out) {
6579 #ifdef DEBUG
6580     char* saved_dst = dst;
6581     const char* saved_src = src;
6582 #endif
6583   DisallowHeapAllocation no_gc;
6584   // We rely on the distance between upper and lower case letters
6585   // being a known power of 2.
6586   ASSERT('a' - 'A' == (1 << 5));
6587   // Boundaries for the range of input characters than require conversion.
6588   static const char lo = Converter::kIsToLower ? 'A' - 1 : 'a' - 1;
6589   static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
6590   bool changed = false;
6591   uintptr_t or_acc = 0;
6592   const char* const limit = src + length;
6593 #ifdef V8_HOST_CAN_READ_UNALIGNED
6594   // Process the prefix of the input that requires no conversion one
6595   // (machine) word at a time.
6596   while (src <= limit - sizeof(uintptr_t)) {
6597     const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6598     or_acc |= w;
6599     if (AsciiRangeMask(w, lo, hi) != 0) {
6600       changed = true;
6601       break;
6602     }
6603     *reinterpret_cast<uintptr_t*>(dst) = w;
6604     src += sizeof(uintptr_t);
6605     dst += sizeof(uintptr_t);
6606   }
6607   // Process the remainder of the input performing conversion when
6608   // required one word at a time.
6609   while (src <= limit - sizeof(uintptr_t)) {
6610     const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6611     or_acc |= w;
6612     uintptr_t m = AsciiRangeMask(w, lo, hi);
6613     // The mask has high (7th) bit set in every byte that needs
6614     // conversion and we know that the distance between cases is
6615     // 1 << 5.
6616     *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6617     src += sizeof(uintptr_t);
6618     dst += sizeof(uintptr_t);
6619   }
6620 #endif
6621   // Process the last few bytes of the input (or the whole input if
6622   // unaligned access is not supported).
6623   while (src < limit) {
6624     char c = *src;
6625     or_acc |= c;
6626     if (lo < c && c < hi) {
6627       c ^= (1 << 5);
6628       changed = true;
6629     }
6630     *dst = c;
6631     ++src;
6632     ++dst;
6633   }
6634   if ((or_acc & kAsciiMask) != 0) {
6635     return false;
6636   }
6637 
6638   ASSERT(CheckFastAsciiConvert(
6639              saved_dst, saved_src, length, changed, Converter::kIsToLower));
6640 
6641   *changed_out = changed;
6642   return true;
6643 }
6644 
6645 }  // namespace
6646 
6647 
6648 template <class Converter>
ConvertCase(Handle<String> s,Isolate * isolate,unibrow::Mapping<Converter,128> * mapping)6649 MUST_USE_RESULT static Object* ConvertCase(
6650     Handle<String> s,
6651     Isolate* isolate,
6652     unibrow::Mapping<Converter, 128>* mapping) {
6653   s = String::Flatten(s);
6654   int length = s->length();
6655   // Assume that the string is not empty; we need this assumption later
6656   if (length == 0) return *s;
6657 
6658   // Simpler handling of ASCII strings.
6659   //
6660   // NOTE: This assumes that the upper/lower case of an ASCII
6661   // character is also ASCII.  This is currently the case, but it
6662   // might break in the future if we implement more context and locale
6663   // dependent upper/lower conversions.
6664   if (s->IsOneByteRepresentationUnderneath()) {
6665     // Same length as input.
6666     Handle<SeqOneByteString> result =
6667         isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
6668     DisallowHeapAllocation no_gc;
6669     String::FlatContent flat_content = s->GetFlatContent();
6670     ASSERT(flat_content.IsFlat());
6671     bool has_changed_character = false;
6672     bool is_ascii = FastAsciiConvert<Converter>(
6673         reinterpret_cast<char*>(result->GetChars()),
6674         reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
6675         length,
6676         &has_changed_character);
6677     // If not ASCII, we discard the result and take the 2 byte path.
6678     if (is_ascii) return has_changed_character ? *result : *s;
6679   }
6680 
6681   Handle<SeqString> result;  // Same length as input.
6682   if (s->IsOneByteRepresentation()) {
6683     result = isolate->factory()->NewRawOneByteString(length).ToHandleChecked();
6684   } else {
6685     result = isolate->factory()->NewRawTwoByteString(length).ToHandleChecked();
6686   }
6687 
6688   Object* answer = ConvertCaseHelper(isolate, *s, *result, length, mapping);
6689   if (answer->IsException() || answer->IsString()) return answer;
6690 
6691   ASSERT(answer->IsSmi());
6692   length = Smi::cast(answer)->value();
6693   if (s->IsOneByteRepresentation() && length > 0) {
6694     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6695         isolate, result, isolate->factory()->NewRawOneByteString(length));
6696   } else {
6697     if (length < 0) length = -length;
6698     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
6699         isolate, result, isolate->factory()->NewRawTwoByteString(length));
6700   }
6701   return ConvertCaseHelper(isolate, *s, *result, length, mapping);
6702 }
6703 
6704 
RUNTIME_FUNCTION(Runtime_StringToLowerCase)6705 RUNTIME_FUNCTION(Runtime_StringToLowerCase) {
6706   HandleScope scope(isolate);
6707   ASSERT(args.length() == 1);
6708   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6709   return ConvertCase(
6710       s, isolate, isolate->runtime_state()->to_lower_mapping());
6711 }
6712 
6713 
RUNTIME_FUNCTION(Runtime_StringToUpperCase)6714 RUNTIME_FUNCTION(Runtime_StringToUpperCase) {
6715   HandleScope scope(isolate);
6716   ASSERT(args.length() == 1);
6717   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6718   return ConvertCase(
6719       s, isolate, isolate->runtime_state()->to_upper_mapping());
6720 }
6721 
6722 
RUNTIME_FUNCTION(Runtime_StringTrim)6723 RUNTIME_FUNCTION(Runtime_StringTrim) {
6724   HandleScope scope(isolate);
6725   ASSERT(args.length() == 3);
6726 
6727   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6728   CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6729   CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6730 
6731   string = String::Flatten(string);
6732   int length = string->length();
6733 
6734   int left = 0;
6735   UnicodeCache* unicode_cache = isolate->unicode_cache();
6736   if (trimLeft) {
6737     while (left < length &&
6738            unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
6739       left++;
6740     }
6741   }
6742 
6743   int right = length;
6744   if (trimRight) {
6745     while (right > left &&
6746            unicode_cache->IsWhiteSpaceOrLineTerminator(
6747                string->Get(right - 1))) {
6748       right--;
6749     }
6750   }
6751 
6752   return *isolate->factory()->NewSubString(string, left, right);
6753 }
6754 
6755 
RUNTIME_FUNCTION(Runtime_StringSplit)6756 RUNTIME_FUNCTION(Runtime_StringSplit) {
6757   HandleScope handle_scope(isolate);
6758   ASSERT(args.length() == 3);
6759   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6760   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6761   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6762   RUNTIME_ASSERT(limit > 0);
6763 
6764   int subject_length = subject->length();
6765   int pattern_length = pattern->length();
6766   RUNTIME_ASSERT(pattern_length > 0);
6767 
6768   if (limit == 0xffffffffu) {
6769     Handle<Object> cached_answer(
6770         RegExpResultsCache::Lookup(isolate->heap(),
6771                                    *subject,
6772                                    *pattern,
6773                                    RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
6774         isolate);
6775     if (*cached_answer != Smi::FromInt(0)) {
6776       // The cache FixedArray is a COW-array and can therefore be reused.
6777       Handle<JSArray> result =
6778           isolate->factory()->NewJSArrayWithElements(
6779               Handle<FixedArray>::cast(cached_answer));
6780       return *result;
6781     }
6782   }
6783 
6784   // The limit can be very large (0xffffffffu), but since the pattern
6785   // isn't empty, we can never create more parts than ~half the length
6786   // of the subject.
6787 
6788   subject = String::Flatten(subject);
6789   pattern = String::Flatten(pattern);
6790 
6791   static const int kMaxInitialListCapacity = 16;
6792 
6793   ZoneScope zone_scope(isolate->runtime_zone());
6794 
6795   // Find (up to limit) indices of separator and end-of-string in subject
6796   int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6797   ZoneList<int> indices(initial_capacity, zone_scope.zone());
6798 
6799   FindStringIndicesDispatch(isolate, *subject, *pattern,
6800                             &indices, limit, zone_scope.zone());
6801 
6802   if (static_cast<uint32_t>(indices.length()) < limit) {
6803     indices.Add(subject_length, zone_scope.zone());
6804   }
6805 
6806   // The list indices now contains the end of each part to create.
6807 
6808   // Create JSArray of substrings separated by separator.
6809   int part_count = indices.length();
6810 
6811   Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6812   JSObject::EnsureCanContainHeapObjectElements(result);
6813   result->set_length(Smi::FromInt(part_count));
6814 
6815   ASSERT(result->HasFastObjectElements());
6816 
6817   if (part_count == 1 && indices.at(0) == subject_length) {
6818     FixedArray::cast(result->elements())->set(0, *subject);
6819     return *result;
6820   }
6821 
6822   Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6823   int part_start = 0;
6824   for (int i = 0; i < part_count; i++) {
6825     HandleScope local_loop_handle(isolate);
6826     int part_end = indices.at(i);
6827     Handle<String> substring =
6828         isolate->factory()->NewProperSubString(subject, part_start, part_end);
6829     elements->set(i, *substring);
6830     part_start = part_end + pattern_length;
6831   }
6832 
6833   if (limit == 0xffffffffu) {
6834     if (result->HasFastObjectElements()) {
6835       RegExpResultsCache::Enter(isolate,
6836                                 subject,
6837                                 pattern,
6838                                 elements,
6839                                 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
6840     }
6841   }
6842 
6843   return *result;
6844 }
6845 
6846 
6847 // Copies ASCII characters to the given fixed array looking up
6848 // one-char strings in the cache. Gives up on the first char that is
6849 // not in the cache and fills the remainder with smi zeros. Returns
6850 // the length of the successfully copied prefix.
CopyCachedAsciiCharsToArray(Heap * heap,const uint8_t * chars,FixedArray * elements,int length)6851 static int CopyCachedAsciiCharsToArray(Heap* heap,
6852                                        const uint8_t* chars,
6853                                        FixedArray* elements,
6854                                        int length) {
6855   DisallowHeapAllocation no_gc;
6856   FixedArray* ascii_cache = heap->single_character_string_cache();
6857   Object* undefined = heap->undefined_value();
6858   int i;
6859   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6860   for (i = 0; i < length; ++i) {
6861     Object* value = ascii_cache->get(chars[i]);
6862     if (value == undefined) break;
6863     elements->set(i, value, mode);
6864   }
6865   if (i < length) {
6866     ASSERT(Smi::FromInt(0) == 0);
6867     memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6868   }
6869 #ifdef DEBUG
6870   for (int j = 0; j < length; ++j) {
6871     Object* element = elements->get(j);
6872     ASSERT(element == Smi::FromInt(0) ||
6873            (element->IsString() && String::cast(element)->LooksValid()));
6874   }
6875 #endif
6876   return i;
6877 }
6878 
6879 
6880 // Converts a String to JSArray.
6881 // For example, "foo" => ["f", "o", "o"].
RUNTIME_FUNCTION(Runtime_StringToArray)6882 RUNTIME_FUNCTION(Runtime_StringToArray) {
6883   HandleScope scope(isolate);
6884   ASSERT(args.length() == 2);
6885   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6886   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6887 
6888   s = String::Flatten(s);
6889   const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6890 
6891   Handle<FixedArray> elements;
6892   int position = 0;
6893   if (s->IsFlat() && s->IsOneByteRepresentation()) {
6894     // Try using cached chars where possible.
6895     elements = isolate->factory()->NewUninitializedFixedArray(length);
6896 
6897     DisallowHeapAllocation no_gc;
6898     String::FlatContent content = s->GetFlatContent();
6899     if (content.IsAscii()) {
6900       Vector<const uint8_t> chars = content.ToOneByteVector();
6901       // Note, this will initialize all elements (not only the prefix)
6902       // to prevent GC from seeing partially initialized array.
6903       position = CopyCachedAsciiCharsToArray(isolate->heap(),
6904                                              chars.start(),
6905                                              *elements,
6906                                              length);
6907     } else {
6908       MemsetPointer(elements->data_start(),
6909                     isolate->heap()->undefined_value(),
6910                     length);
6911     }
6912   } else {
6913     elements = isolate->factory()->NewFixedArray(length);
6914   }
6915   for (int i = position; i < length; ++i) {
6916     Handle<Object> str =
6917         isolate->factory()->LookupSingleCharacterStringFromCode(s->Get(i));
6918     elements->set(i, *str);
6919   }
6920 
6921 #ifdef DEBUG
6922   for (int i = 0; i < length; ++i) {
6923     ASSERT(String::cast(elements->get(i))->length() == 1);
6924   }
6925 #endif
6926 
6927   return *isolate->factory()->NewJSArrayWithElements(elements);
6928 }
6929 
6930 
RUNTIME_FUNCTION(Runtime_NewStringWrapper)6931 RUNTIME_FUNCTION(Runtime_NewStringWrapper) {
6932   HandleScope scope(isolate);
6933   ASSERT(args.length() == 1);
6934   CONVERT_ARG_HANDLE_CHECKED(String, value, 0);
6935   return *Object::ToObject(isolate, value).ToHandleChecked();
6936 }
6937 
6938 
IsUpperCaseChar(RuntimeState * runtime_state,uint16_t ch)6939 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6940   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6941   int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6942   return char_length == 0;
6943 }
6944 
6945 
RUNTIME_FUNCTION(RuntimeHidden_NumberToString)6946 RUNTIME_FUNCTION(RuntimeHidden_NumberToString) {
6947   HandleScope scope(isolate);
6948   ASSERT(args.length() == 1);
6949   CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
6950 
6951   return *isolate->factory()->NumberToString(number);
6952 }
6953 
6954 
RUNTIME_FUNCTION(RuntimeHidden_NumberToStringSkipCache)6955 RUNTIME_FUNCTION(RuntimeHidden_NumberToStringSkipCache) {
6956   HandleScope scope(isolate);
6957   ASSERT(args.length() == 1);
6958   CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 0);
6959 
6960   return *isolate->factory()->NumberToString(number, false);
6961 }
6962 
6963 
RUNTIME_FUNCTION(Runtime_NumberToInteger)6964 RUNTIME_FUNCTION(Runtime_NumberToInteger) {
6965   HandleScope scope(isolate);
6966   ASSERT(args.length() == 1);
6967 
6968   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6969   return *isolate->factory()->NewNumber(DoubleToInteger(number));
6970 }
6971 
6972 
RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero)6973 RUNTIME_FUNCTION(Runtime_NumberToIntegerMapMinusZero) {
6974   HandleScope scope(isolate);
6975   ASSERT(args.length() == 1);
6976 
6977   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6978   double double_value = DoubleToInteger(number);
6979   // Map both -0 and +0 to +0.
6980   if (double_value == 0) double_value = 0;
6981 
6982   return *isolate->factory()->NewNumber(double_value);
6983 }
6984 
6985 
RUNTIME_FUNCTION(Runtime_NumberToJSUint32)6986 RUNTIME_FUNCTION(Runtime_NumberToJSUint32) {
6987   HandleScope scope(isolate);
6988   ASSERT(args.length() == 1);
6989 
6990   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6991   return *isolate->factory()->NewNumberFromUint(number);
6992 }
6993 
6994 
RUNTIME_FUNCTION(Runtime_NumberToJSInt32)6995 RUNTIME_FUNCTION(Runtime_NumberToJSInt32) {
6996   HandleScope scope(isolate);
6997   ASSERT(args.length() == 1);
6998 
6999   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
7000   return *isolate->factory()->NewNumberFromInt(DoubleToInt32(number));
7001 }
7002 
7003 
7004 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
7005 // a small integer.
RUNTIME_FUNCTION(RuntimeHidden_NumberToSmi)7006 RUNTIME_FUNCTION(RuntimeHidden_NumberToSmi) {
7007   SealHandleScope shs(isolate);
7008   ASSERT(args.length() == 1);
7009   CONVERT_ARG_CHECKED(Object, obj, 0);
7010   if (obj->IsSmi()) {
7011     return obj;
7012   }
7013   if (obj->IsHeapNumber()) {
7014     double value = HeapNumber::cast(obj)->value();
7015     int int_value = FastD2I(value);
7016     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
7017       return Smi::FromInt(int_value);
7018     }
7019   }
7020   return isolate->heap()->nan_value();
7021 }
7022 
7023 
RUNTIME_FUNCTION(RuntimeHidden_AllocateHeapNumber)7024 RUNTIME_FUNCTION(RuntimeHidden_AllocateHeapNumber) {
7025   HandleScope scope(isolate);
7026   ASSERT(args.length() == 0);
7027   return *isolate->factory()->NewHeapNumber(0);
7028 }
7029 
7030 
RUNTIME_FUNCTION(Runtime_NumberAdd)7031 RUNTIME_FUNCTION(Runtime_NumberAdd) {
7032   HandleScope scope(isolate);
7033   ASSERT(args.length() == 2);
7034 
7035   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7036   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7037   return *isolate->factory()->NewNumber(x + y);
7038 }
7039 
7040 
RUNTIME_FUNCTION(Runtime_NumberSub)7041 RUNTIME_FUNCTION(Runtime_NumberSub) {
7042   HandleScope scope(isolate);
7043   ASSERT(args.length() == 2);
7044 
7045   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7046   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7047   return *isolate->factory()->NewNumber(x - y);
7048 }
7049 
7050 
RUNTIME_FUNCTION(Runtime_NumberMul)7051 RUNTIME_FUNCTION(Runtime_NumberMul) {
7052   HandleScope scope(isolate);
7053   ASSERT(args.length() == 2);
7054 
7055   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7056   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7057   return *isolate->factory()->NewNumber(x * y);
7058 }
7059 
7060 
RUNTIME_FUNCTION(Runtime_NumberUnaryMinus)7061 RUNTIME_FUNCTION(Runtime_NumberUnaryMinus) {
7062   HandleScope scope(isolate);
7063   ASSERT(args.length() == 1);
7064 
7065   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7066   return *isolate->factory()->NewNumber(-x);
7067 }
7068 
7069 
RUNTIME_FUNCTION(Runtime_NumberDiv)7070 RUNTIME_FUNCTION(Runtime_NumberDiv) {
7071   HandleScope scope(isolate);
7072   ASSERT(args.length() == 2);
7073 
7074   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7075   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7076   return *isolate->factory()->NewNumber(x / y);
7077 }
7078 
7079 
RUNTIME_FUNCTION(Runtime_NumberMod)7080 RUNTIME_FUNCTION(Runtime_NumberMod) {
7081   HandleScope scope(isolate);
7082   ASSERT(args.length() == 2);
7083 
7084   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7085   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7086   return *isolate->factory()->NewNumber(modulo(x, y));
7087 }
7088 
7089 
RUNTIME_FUNCTION(Runtime_NumberImul)7090 RUNTIME_FUNCTION(Runtime_NumberImul) {
7091   HandleScope scope(isolate);
7092   ASSERT(args.length() == 2);
7093 
7094   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7095   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7096   return *isolate->factory()->NewNumberFromInt(x * y);
7097 }
7098 
7099 
RUNTIME_FUNCTION(RuntimeHidden_StringAdd)7100 RUNTIME_FUNCTION(RuntimeHidden_StringAdd) {
7101   HandleScope scope(isolate);
7102   ASSERT(args.length() == 2);
7103   CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
7104   CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
7105   isolate->counters()->string_add_runtime()->Increment();
7106   Handle<String> result;
7107   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7108       isolate, result, isolate->factory()->NewConsString(str1, str2));
7109   return *result;
7110 }
7111 
7112 
7113 template <typename sinkchar>
StringBuilderConcatHelper(String * special,sinkchar * sink,FixedArray * fixed_array,int array_length)7114 static inline void StringBuilderConcatHelper(String* special,
7115                                              sinkchar* sink,
7116                                              FixedArray* fixed_array,
7117                                              int array_length) {
7118   DisallowHeapAllocation no_gc;
7119   int position = 0;
7120   for (int i = 0; i < array_length; i++) {
7121     Object* element = fixed_array->get(i);
7122     if (element->IsSmi()) {
7123       // Smi encoding of position and length.
7124       int encoded_slice = Smi::cast(element)->value();
7125       int pos;
7126       int len;
7127       if (encoded_slice > 0) {
7128         // Position and length encoded in one smi.
7129         pos = StringBuilderSubstringPosition::decode(encoded_slice);
7130         len = StringBuilderSubstringLength::decode(encoded_slice);
7131       } else {
7132         // Position and length encoded in two smis.
7133         Object* obj = fixed_array->get(++i);
7134         ASSERT(obj->IsSmi());
7135         pos = Smi::cast(obj)->value();
7136         len = -encoded_slice;
7137       }
7138       String::WriteToFlat(special,
7139                           sink + position,
7140                           pos,
7141                           pos + len);
7142       position += len;
7143     } else {
7144       String* string = String::cast(element);
7145       int element_length = string->length();
7146       String::WriteToFlat(string, sink + position, 0, element_length);
7147       position += element_length;
7148     }
7149   }
7150 }
7151 
7152 
7153 // Returns the result length of the concatenation.
7154 // On illegal argument, -1 is returned.
StringBuilderConcatLength(int special_length,FixedArray * fixed_array,int array_length,bool * one_byte)7155 static inline int StringBuilderConcatLength(int special_length,
7156                                             FixedArray* fixed_array,
7157                                             int array_length,
7158                                             bool* one_byte) {
7159   DisallowHeapAllocation no_gc;
7160   int position = 0;
7161   for (int i = 0; i < array_length; i++) {
7162     int increment = 0;
7163     Object* elt = fixed_array->get(i);
7164     if (elt->IsSmi()) {
7165       // Smi encoding of position and length.
7166       int smi_value = Smi::cast(elt)->value();
7167       int pos;
7168       int len;
7169       if (smi_value > 0) {
7170         // Position and length encoded in one smi.
7171         pos = StringBuilderSubstringPosition::decode(smi_value);
7172         len = StringBuilderSubstringLength::decode(smi_value);
7173       } else {
7174         // Position and length encoded in two smis.
7175         len = -smi_value;
7176         // Get the position and check that it is a positive smi.
7177         i++;
7178         if (i >= array_length) return -1;
7179         Object* next_smi = fixed_array->get(i);
7180         if (!next_smi->IsSmi()) return -1;
7181         pos = Smi::cast(next_smi)->value();
7182         if (pos < 0) return -1;
7183       }
7184       ASSERT(pos >= 0);
7185       ASSERT(len >= 0);
7186       if (pos > special_length || len > special_length - pos) return -1;
7187       increment = len;
7188     } else if (elt->IsString()) {
7189       String* element = String::cast(elt);
7190       int element_length = element->length();
7191       increment = element_length;
7192       if (*one_byte && !element->HasOnlyOneByteChars()) {
7193         *one_byte = false;
7194       }
7195     } else {
7196       return -1;
7197     }
7198     if (increment > String::kMaxLength - position) {
7199       return kMaxInt;  // Provoke throw on allocation.
7200     }
7201     position += increment;
7202   }
7203   return position;
7204 }
7205 
7206 
RUNTIME_FUNCTION(Runtime_StringBuilderConcat)7207 RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
7208   HandleScope scope(isolate);
7209   ASSERT(args.length() == 3);
7210   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7211   if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
7212   CONVERT_SMI_ARG_CHECKED(array_length, 1);
7213   CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
7214 
7215   size_t actual_array_length = 0;
7216   RUNTIME_ASSERT(
7217       TryNumberToSize(isolate, array->length(), &actual_array_length));
7218   RUNTIME_ASSERT(array_length >= 0);
7219   RUNTIME_ASSERT(static_cast<size_t>(array_length) <= actual_array_length);
7220 
7221   // This assumption is used by the slice encoding in one or two smis.
7222   ASSERT(Smi::kMaxValue >= String::kMaxLength);
7223 
7224   RUNTIME_ASSERT(array->HasFastElements());
7225   JSObject::EnsureCanContainHeapObjectElements(array);
7226 
7227   int special_length = special->length();
7228   if (!array->HasFastObjectElements()) {
7229     return isolate->Throw(isolate->heap()->illegal_argument_string());
7230   }
7231 
7232   int length;
7233   bool one_byte = special->HasOnlyOneByteChars();
7234 
7235   { DisallowHeapAllocation no_gc;
7236     FixedArray* fixed_array = FixedArray::cast(array->elements());
7237     if (fixed_array->length() < array_length) {
7238       array_length = fixed_array->length();
7239     }
7240 
7241     if (array_length == 0) {
7242       return isolate->heap()->empty_string();
7243     } else if (array_length == 1) {
7244       Object* first = fixed_array->get(0);
7245       if (first->IsString()) return first;
7246     }
7247     length = StringBuilderConcatLength(
7248         special_length, fixed_array, array_length, &one_byte);
7249   }
7250 
7251   if (length == -1) {
7252     return isolate->Throw(isolate->heap()->illegal_argument_string());
7253   }
7254 
7255   if (one_byte) {
7256     Handle<SeqOneByteString> answer;
7257     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7258         isolate, answer,
7259         isolate->factory()->NewRawOneByteString(length));
7260     StringBuilderConcatHelper(*special,
7261                               answer->GetChars(),
7262                               FixedArray::cast(array->elements()),
7263                               array_length);
7264     return *answer;
7265   } else {
7266     Handle<SeqTwoByteString> answer;
7267     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7268         isolate, answer,
7269         isolate->factory()->NewRawTwoByteString(length));
7270     StringBuilderConcatHelper(*special,
7271                               answer->GetChars(),
7272                               FixedArray::cast(array->elements()),
7273                               array_length);
7274     return *answer;
7275   }
7276 }
7277 
7278 
RUNTIME_FUNCTION(Runtime_StringBuilderJoin)7279 RUNTIME_FUNCTION(Runtime_StringBuilderJoin) {
7280   HandleScope scope(isolate);
7281   ASSERT(args.length() == 3);
7282   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7283   if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
7284   CONVERT_SMI_ARG_CHECKED(array_length, 1);
7285   CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
7286   RUNTIME_ASSERT(array->HasFastObjectElements());
7287   RUNTIME_ASSERT(array_length >= 0);
7288 
7289   Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
7290   if (fixed_array->length() < array_length) {
7291     array_length = fixed_array->length();
7292   }
7293 
7294   if (array_length == 0) {
7295     return isolate->heap()->empty_string();
7296   } else if (array_length == 1) {
7297     Object* first = fixed_array->get(0);
7298     RUNTIME_ASSERT(first->IsString());
7299     return first;
7300   }
7301 
7302   int separator_length = separator->length();
7303   RUNTIME_ASSERT(separator_length > 0);
7304   int max_nof_separators =
7305       (String::kMaxLength + separator_length - 1) / separator_length;
7306   if (max_nof_separators < (array_length - 1)) {
7307     return isolate->ThrowInvalidStringLength();
7308   }
7309   int length = (array_length - 1) * separator_length;
7310   for (int i = 0; i < array_length; i++) {
7311     Object* element_obj = fixed_array->get(i);
7312     RUNTIME_ASSERT(element_obj->IsString());
7313     String* element = String::cast(element_obj);
7314     int increment = element->length();
7315     if (increment > String::kMaxLength - length) {
7316       STATIC_ASSERT(String::kMaxLength < kMaxInt);
7317       length = kMaxInt;  // Provoke exception;
7318       break;
7319     }
7320     length += increment;
7321   }
7322 
7323   Handle<SeqTwoByteString> answer;
7324   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
7325       isolate, answer,
7326       isolate->factory()->NewRawTwoByteString(length));
7327 
7328   DisallowHeapAllocation no_gc;
7329 
7330   uc16* sink = answer->GetChars();
7331 #ifdef DEBUG
7332   uc16* end = sink + length;
7333 #endif
7334 
7335   RUNTIME_ASSERT(fixed_array->get(0)->IsString());
7336   String* first = String::cast(fixed_array->get(0));
7337   String* separator_raw = *separator;
7338   int first_length = first->length();
7339   String::WriteToFlat(first, sink, 0, first_length);
7340   sink += first_length;
7341 
7342   for (int i = 1; i < array_length; i++) {
7343     ASSERT(sink + separator_length <= end);
7344     String::WriteToFlat(separator_raw, sink, 0, separator_length);
7345     sink += separator_length;
7346 
7347     RUNTIME_ASSERT(fixed_array->get(i)->IsString());
7348     String* element = String::cast(fixed_array->get(i));
7349     int element_length = element->length();
7350     ASSERT(sink + element_length <= end);
7351     String::WriteToFlat(element, sink, 0, element_length);
7352     sink += element_length;
7353   }
7354   ASSERT(sink == end);
7355 
7356   // Use %_FastAsciiArrayJoin instead.
7357   ASSERT(!answer->IsOneByteRepresentation());
7358   return *answer;
7359 }
7360 
7361 template <typename Char>
JoinSparseArrayWithSeparator(FixedArray * elements,int elements_length,uint32_t array_length,String * separator,Vector<Char> buffer)7362 static void JoinSparseArrayWithSeparator(FixedArray* elements,
7363                                          int elements_length,
7364                                          uint32_t array_length,
7365                                          String* separator,
7366                                          Vector<Char> buffer) {
7367   DisallowHeapAllocation no_gc;
7368   int previous_separator_position = 0;
7369   int separator_length = separator->length();
7370   int cursor = 0;
7371   for (int i = 0; i < elements_length; i += 2) {
7372     int position = NumberToInt32(elements->get(i));
7373     String* string = String::cast(elements->get(i + 1));
7374     int string_length = string->length();
7375     if (string->length() > 0) {
7376       while (previous_separator_position < position) {
7377         String::WriteToFlat<Char>(separator, &buffer[cursor],
7378                                   0, separator_length);
7379         cursor += separator_length;
7380         previous_separator_position++;
7381       }
7382       String::WriteToFlat<Char>(string, &buffer[cursor],
7383                                 0, string_length);
7384       cursor += string->length();
7385     }
7386   }
7387   if (separator_length > 0) {
7388     // Array length must be representable as a signed 32-bit number,
7389     // otherwise the total string length would have been too large.
7390     ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
7391     int last_array_index = static_cast<int>(array_length - 1);
7392     while (previous_separator_position < last_array_index) {
7393       String::WriteToFlat<Char>(separator, &buffer[cursor],
7394                                 0, separator_length);
7395       cursor += separator_length;
7396       previous_separator_position++;
7397     }
7398   }
7399   ASSERT(cursor <= buffer.length());
7400 }
7401 
7402 
RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator)7403 RUNTIME_FUNCTION(Runtime_SparseJoinWithSeparator) {
7404   HandleScope scope(isolate);
7405   ASSERT(args.length() == 3);
7406   CONVERT_ARG_HANDLE_CHECKED(JSArray, elements_array, 0);
7407   CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7408   CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
7409   // elements_array is fast-mode JSarray of alternating positions
7410   // (increasing order) and strings.
7411   RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7412   // array_length is length of original array (used to add separators);
7413   // separator is string to put between elements. Assumed to be non-empty.
7414   RUNTIME_ASSERT(array_length > 0);
7415 
7416   // Find total length of join result.
7417   int string_length = 0;
7418   bool is_ascii = separator->IsOneByteRepresentation();
7419   bool overflow = false;
7420   CONVERT_NUMBER_CHECKED(int, elements_length, Int32, elements_array->length());
7421   RUNTIME_ASSERT(elements_length <= elements_array->elements()->length());
7422   RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7423   FixedArray* elements = FixedArray::cast(elements_array->elements());
7424   for (int i = 0; i < elements_length; i += 2) {
7425     RUNTIME_ASSERT(elements->get(i)->IsNumber());
7426     CONVERT_NUMBER_CHECKED(uint32_t, position, Uint32, elements->get(i));
7427     RUNTIME_ASSERT(position < array_length);
7428     RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7429   }
7430 
7431   { DisallowHeapAllocation no_gc;
7432     for (int i = 0; i < elements_length; i += 2) {
7433       String* string = String::cast(elements->get(i + 1));
7434       int length = string->length();
7435       if (is_ascii && !string->IsOneByteRepresentation()) {
7436         is_ascii = false;
7437       }
7438       if (length > String::kMaxLength ||
7439           String::kMaxLength - length < string_length) {
7440         overflow = true;
7441         break;
7442       }
7443       string_length += length;
7444     }
7445   }
7446 
7447   int separator_length = separator->length();
7448   if (!overflow && separator_length > 0) {
7449     if (array_length <= 0x7fffffffu) {
7450       int separator_count = static_cast<int>(array_length) - 1;
7451       int remaining_length = String::kMaxLength - string_length;
7452       if ((remaining_length / separator_length) >= separator_count) {
7453         string_length += separator_length * (array_length - 1);
7454       } else {
7455         // Not room for the separators within the maximal string length.
7456         overflow = true;
7457       }
7458     } else {
7459       // Nonempty separator and at least 2^31-1 separators necessary
7460       // means that the string is too large to create.
7461       STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7462       overflow = true;
7463     }
7464   }
7465   if (overflow) {
7466     // Throw an exception if the resulting string is too large. See
7467     // https://code.google.com/p/chromium/issues/detail?id=336820
7468     // for details.
7469     return isolate->ThrowInvalidStringLength();
7470   }
7471 
7472   if (is_ascii) {
7473     Handle<SeqOneByteString> result = isolate->factory()->NewRawOneByteString(
7474         string_length).ToHandleChecked();
7475     JoinSparseArrayWithSeparator<uint8_t>(
7476         FixedArray::cast(elements_array->elements()),
7477         elements_length,
7478         array_length,
7479         *separator,
7480         Vector<uint8_t>(result->GetChars(), string_length));
7481     return *result;
7482   } else {
7483     Handle<SeqTwoByteString> result = isolate->factory()->NewRawTwoByteString(
7484         string_length).ToHandleChecked();
7485     JoinSparseArrayWithSeparator<uc16>(
7486         FixedArray::cast(elements_array->elements()),
7487         elements_length,
7488         array_length,
7489         *separator,
7490         Vector<uc16>(result->GetChars(), string_length));
7491     return *result;
7492   }
7493 }
7494 
7495 
RUNTIME_FUNCTION(Runtime_NumberOr)7496 RUNTIME_FUNCTION(Runtime_NumberOr) {
7497   HandleScope scope(isolate);
7498   ASSERT(args.length() == 2);
7499 
7500   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7501   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7502   return *isolate->factory()->NewNumberFromInt(x | y);
7503 }
7504 
7505 
RUNTIME_FUNCTION(Runtime_NumberAnd)7506 RUNTIME_FUNCTION(Runtime_NumberAnd) {
7507   HandleScope scope(isolate);
7508   ASSERT(args.length() == 2);
7509 
7510   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7511   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7512   return *isolate->factory()->NewNumberFromInt(x & y);
7513 }
7514 
7515 
RUNTIME_FUNCTION(Runtime_NumberXor)7516 RUNTIME_FUNCTION(Runtime_NumberXor) {
7517   HandleScope scope(isolate);
7518   ASSERT(args.length() == 2);
7519 
7520   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7521   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7522   return *isolate->factory()->NewNumberFromInt(x ^ y);
7523 }
7524 
7525 
RUNTIME_FUNCTION(Runtime_NumberShl)7526 RUNTIME_FUNCTION(Runtime_NumberShl) {
7527   HandleScope scope(isolate);
7528   ASSERT(args.length() == 2);
7529 
7530   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7531   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7532   return *isolate->factory()->NewNumberFromInt(x << (y & 0x1f));
7533 }
7534 
7535 
RUNTIME_FUNCTION(Runtime_NumberShr)7536 RUNTIME_FUNCTION(Runtime_NumberShr) {
7537   HandleScope scope(isolate);
7538   ASSERT(args.length() == 2);
7539 
7540   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7541   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7542   return *isolate->factory()->NewNumberFromUint(x >> (y & 0x1f));
7543 }
7544 
7545 
RUNTIME_FUNCTION(Runtime_NumberSar)7546 RUNTIME_FUNCTION(Runtime_NumberSar) {
7547   HandleScope scope(isolate);
7548   ASSERT(args.length() == 2);
7549 
7550   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7551   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7552   return *isolate->factory()->NewNumberFromInt(
7553       ArithmeticShiftRight(x, y & 0x1f));
7554 }
7555 
7556 
RUNTIME_FUNCTION(Runtime_NumberEquals)7557 RUNTIME_FUNCTION(Runtime_NumberEquals) {
7558   SealHandleScope shs(isolate);
7559   ASSERT(args.length() == 2);
7560 
7561   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7562   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7563   if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7564   if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7565   if (x == y) return Smi::FromInt(EQUAL);
7566   Object* result;
7567   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7568     result = Smi::FromInt(EQUAL);
7569   } else {
7570     result = Smi::FromInt(NOT_EQUAL);
7571   }
7572   return result;
7573 }
7574 
7575 
RUNTIME_FUNCTION(Runtime_StringEquals)7576 RUNTIME_FUNCTION(Runtime_StringEquals) {
7577   HandleScope handle_scope(isolate);
7578   ASSERT(args.length() == 2);
7579 
7580   CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
7581   CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
7582 
7583   bool not_equal = !String::Equals(x, y);
7584   // This is slightly convoluted because the value that signifies
7585   // equality is 0 and inequality is 1 so we have to negate the result
7586   // from String::Equals.
7587   ASSERT(not_equal == 0 || not_equal == 1);
7588   STATIC_ASSERT(EQUAL == 0);
7589   STATIC_ASSERT(NOT_EQUAL == 1);
7590   return Smi::FromInt(not_equal);
7591 }
7592 
7593 
RUNTIME_FUNCTION(Runtime_NumberCompare)7594 RUNTIME_FUNCTION(Runtime_NumberCompare) {
7595   SealHandleScope shs(isolate);
7596   ASSERT(args.length() == 3);
7597 
7598   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7599   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7600   CONVERT_ARG_HANDLE_CHECKED(Object, uncomparable_result, 2)
7601   if (std::isnan(x) || std::isnan(y)) return *uncomparable_result;
7602   if (x == y) return Smi::FromInt(EQUAL);
7603   if (isless(x, y)) return Smi::FromInt(LESS);
7604   return Smi::FromInt(GREATER);
7605 }
7606 
7607 
7608 // Compare two Smis as if they were converted to strings and then
7609 // compared lexicographically.
RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare)7610 RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
7611   SealHandleScope shs(isolate);
7612   ASSERT(args.length() == 2);
7613   CONVERT_SMI_ARG_CHECKED(x_value, 0);
7614   CONVERT_SMI_ARG_CHECKED(y_value, 1);
7615 
7616   // If the integers are equal so are the string representations.
7617   if (x_value == y_value) return Smi::FromInt(EQUAL);
7618 
7619   // If one of the integers is zero the normal integer order is the
7620   // same as the lexicographic order of the string representations.
7621   if (x_value == 0 || y_value == 0)
7622     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7623 
7624   // If only one of the integers is negative the negative number is
7625   // smallest because the char code of '-' is less than the char code
7626   // of any digit.  Otherwise, we make both values positive.
7627 
7628   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7629   // architectures using 32-bit Smis.
7630   uint32_t x_scaled = x_value;
7631   uint32_t y_scaled = y_value;
7632   if (x_value < 0 || y_value < 0) {
7633     if (y_value >= 0) return Smi::FromInt(LESS);
7634     if (x_value >= 0) return Smi::FromInt(GREATER);
7635     x_scaled = -x_value;
7636     y_scaled = -y_value;
7637   }
7638 
7639   static const uint32_t kPowersOf10[] = {
7640     1, 10, 100, 1000, 10*1000, 100*1000,
7641     1000*1000, 10*1000*1000, 100*1000*1000,
7642     1000*1000*1000
7643   };
7644 
7645   // If the integers have the same number of decimal digits they can be
7646   // compared directly as the numeric order is the same as the
7647   // lexicographic order.  If one integer has fewer digits, it is scaled
7648   // by some power of 10 to have the same number of digits as the longer
7649   // integer.  If the scaled integers are equal it means the shorter
7650   // integer comes first in the lexicographic order.
7651 
7652   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7653   int x_log2 = IntegerLog2(x_scaled);
7654   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7655   x_log10 -= x_scaled < kPowersOf10[x_log10];
7656 
7657   int y_log2 = IntegerLog2(y_scaled);
7658   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7659   y_log10 -= y_scaled < kPowersOf10[y_log10];
7660 
7661   int tie = EQUAL;
7662 
7663   if (x_log10 < y_log10) {
7664     // X has fewer digits.  We would like to simply scale up X but that
7665     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7666     // be scaled up to 9_000_000_000. So we scale up by the next
7667     // smallest power and scale down Y to drop one digit. It is OK to
7668     // drop one digit from the longer integer since the final digit is
7669     // past the length of the shorter integer.
7670     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7671     y_scaled /= 10;
7672     tie = LESS;
7673   } else if (y_log10 < x_log10) {
7674     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7675     x_scaled /= 10;
7676     tie = GREATER;
7677   }
7678 
7679   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7680   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7681   return Smi::FromInt(tie);
7682 }
7683 
7684 
RUNTIME_FUNCTION(RuntimeHidden_StringCompare)7685 RUNTIME_FUNCTION(RuntimeHidden_StringCompare) {
7686   HandleScope handle_scope(isolate);
7687   ASSERT(args.length() == 2);
7688 
7689   CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
7690   CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
7691 
7692   isolate->counters()->string_compare_runtime()->Increment();
7693 
7694   // A few fast case tests before we flatten.
7695   if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
7696   if (y->length() == 0) {
7697     if (x->length() == 0) return Smi::FromInt(EQUAL);
7698     return Smi::FromInt(GREATER);
7699   } else if (x->length() == 0) {
7700     return Smi::FromInt(LESS);
7701   }
7702 
7703   int d = x->Get(0) - y->Get(0);
7704   if (d < 0) return Smi::FromInt(LESS);
7705   else if (d > 0) return Smi::FromInt(GREATER);
7706 
7707   // Slow case.
7708   x = String::Flatten(x);
7709   y = String::Flatten(y);
7710 
7711   DisallowHeapAllocation no_gc;
7712   Object* equal_prefix_result = Smi::FromInt(EQUAL);
7713   int prefix_length = x->length();
7714   if (y->length() < prefix_length) {
7715     prefix_length = y->length();
7716     equal_prefix_result = Smi::FromInt(GREATER);
7717   } else if (y->length() > prefix_length) {
7718     equal_prefix_result = Smi::FromInt(LESS);
7719   }
7720   int r;
7721   String::FlatContent x_content = x->GetFlatContent();
7722   String::FlatContent y_content = y->GetFlatContent();
7723   if (x_content.IsAscii()) {
7724     Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7725     if (y_content.IsAscii()) {
7726       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7727       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7728     } else {
7729       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7730       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7731     }
7732   } else {
7733     Vector<const uc16> x_chars = x_content.ToUC16Vector();
7734     if (y_content.IsAscii()) {
7735       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7736       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7737     } else {
7738       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7739       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7740     }
7741   }
7742   Object* result;
7743   if (r == 0) {
7744     result = equal_prefix_result;
7745   } else {
7746     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7747   }
7748   return result;
7749 }
7750 
7751 
7752 #define RUNTIME_UNARY_MATH(Name, name)                                         \
7753 RUNTIME_FUNCTION(Runtime_Math##Name) {                           \
7754   HandleScope scope(isolate);                                                  \
7755   ASSERT(args.length() == 1);                                                  \
7756   isolate->counters()->math_##name()->Increment();                             \
7757   CONVERT_DOUBLE_ARG_CHECKED(x, 0);                                            \
7758   return *isolate->factory()->NewHeapNumber(std::name(x));                     \
7759 }
7760 
RUNTIME_UNARY_MATH(Acos,acos)7761 RUNTIME_UNARY_MATH(Acos, acos)
7762 RUNTIME_UNARY_MATH(Asin, asin)
7763 RUNTIME_UNARY_MATH(Atan, atan)
7764 RUNTIME_UNARY_MATH(LogRT, log)
7765 #undef RUNTIME_UNARY_MATH
7766 
7767 
7768 RUNTIME_FUNCTION(Runtime_DoubleHi) {
7769   HandleScope scope(isolate);
7770   ASSERT(args.length() == 1);
7771   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7772   uint64_t integer = double_to_uint64(x);
7773   integer = (integer >> 32) & 0xFFFFFFFFu;
7774   return *isolate->factory()->NewNumber(static_cast<int32_t>(integer));
7775 }
7776 
7777 
RUNTIME_FUNCTION(Runtime_DoubleLo)7778 RUNTIME_FUNCTION(Runtime_DoubleLo) {
7779   HandleScope scope(isolate);
7780   ASSERT(args.length() == 1);
7781   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7782   return *isolate->factory()->NewNumber(
7783       static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu));
7784 }
7785 
7786 
RUNTIME_FUNCTION(Runtime_ConstructDouble)7787 RUNTIME_FUNCTION(Runtime_ConstructDouble) {
7788   HandleScope scope(isolate);
7789   ASSERT(args.length() == 2);
7790   CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
7791   CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
7792   uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
7793   return *isolate->factory()->NewNumber(uint64_to_double(result));
7794 }
7795 
7796 
7797 static const double kPiDividedBy4 = 0.78539816339744830962;
7798 
7799 
RUNTIME_FUNCTION(Runtime_MathAtan2)7800 RUNTIME_FUNCTION(Runtime_MathAtan2) {
7801   HandleScope scope(isolate);
7802   ASSERT(args.length() == 2);
7803   isolate->counters()->math_atan2()->Increment();
7804 
7805   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7806   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7807   double result;
7808   if (std::isinf(x) && std::isinf(y)) {
7809     // Make sure that the result in case of two infinite arguments
7810     // is a multiple of Pi / 4. The sign of the result is determined
7811     // by the first argument (x) and the sign of the second argument
7812     // determines the multiplier: one or three.
7813     int multiplier = (x < 0) ? -1 : 1;
7814     if (y < 0) multiplier *= 3;
7815     result = multiplier * kPiDividedBy4;
7816   } else {
7817     result = std::atan2(x, y);
7818   }
7819   return *isolate->factory()->NewNumber(result);
7820 }
7821 
7822 
RUNTIME_FUNCTION(Runtime_MathExpRT)7823 RUNTIME_FUNCTION(Runtime_MathExpRT) {
7824   HandleScope scope(isolate);
7825   ASSERT(args.length() == 1);
7826   isolate->counters()->math_exp()->Increment();
7827 
7828   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7829   lazily_initialize_fast_exp();
7830   return *isolate->factory()->NewNumber(fast_exp(x));
7831 }
7832 
7833 
RUNTIME_FUNCTION(Runtime_MathFloorRT)7834 RUNTIME_FUNCTION(Runtime_MathFloorRT) {
7835   HandleScope scope(isolate);
7836   ASSERT(args.length() == 1);
7837   isolate->counters()->math_floor()->Increment();
7838 
7839   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7840   return *isolate->factory()->NewNumber(std::floor(x));
7841 }
7842 
7843 
7844 // Slow version of Math.pow.  We check for fast paths for special cases.
7845 // Used if VFP3 is not available.
RUNTIME_FUNCTION(RuntimeHidden_MathPowSlow)7846 RUNTIME_FUNCTION(RuntimeHidden_MathPowSlow) {
7847   HandleScope scope(isolate);
7848   ASSERT(args.length() == 2);
7849   isolate->counters()->math_pow()->Increment();
7850 
7851   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7852 
7853   // If the second argument is a smi, it is much faster to call the
7854   // custom powi() function than the generic pow().
7855   if (args[1]->IsSmi()) {
7856     int y = args.smi_at(1);
7857     return *isolate->factory()->NewNumber(power_double_int(x, y));
7858   }
7859 
7860   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7861   double result = power_helper(x, y);
7862   if (std::isnan(result)) return isolate->heap()->nan_value();
7863   return *isolate->factory()->NewNumber(result);
7864 }
7865 
7866 
7867 // Fast version of Math.pow if we know that y is not an integer and y is not
7868 // -0.5 or 0.5.  Used as slow case from full codegen.
RUNTIME_FUNCTION(RuntimeHidden_MathPow)7869 RUNTIME_FUNCTION(RuntimeHidden_MathPow) {
7870   HandleScope scope(isolate);
7871   ASSERT(args.length() == 2);
7872   isolate->counters()->math_pow()->Increment();
7873 
7874   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7875   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7876   if (y == 0) {
7877     return Smi::FromInt(1);
7878   } else {
7879     double result = power_double_double(x, y);
7880     if (std::isnan(result)) return isolate->heap()->nan_value();
7881     return *isolate->factory()->NewNumber(result);
7882   }
7883 }
7884 
7885 
RUNTIME_FUNCTION(Runtime_RoundNumber)7886 RUNTIME_FUNCTION(Runtime_RoundNumber) {
7887   HandleScope scope(isolate);
7888   ASSERT(args.length() == 1);
7889   CONVERT_NUMBER_ARG_HANDLE_CHECKED(input, 0);
7890   isolate->counters()->math_round()->Increment();
7891 
7892   if (!input->IsHeapNumber()) {
7893     ASSERT(input->IsSmi());
7894     return *input;
7895   }
7896 
7897   Handle<HeapNumber> number = Handle<HeapNumber>::cast(input);
7898 
7899   double value = number->value();
7900   int exponent = number->get_exponent();
7901   int sign = number->get_sign();
7902 
7903   if (exponent < -1) {
7904     // Number in range ]-0.5..0.5[. These always round to +/-zero.
7905     if (sign) return isolate->heap()->minus_zero_value();
7906     return Smi::FromInt(0);
7907   }
7908 
7909   // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7910   // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7911   // argument holds for 32-bit smis).
7912   if (!sign && exponent < kSmiValueSize - 2) {
7913     return Smi::FromInt(static_cast<int>(value + 0.5));
7914   }
7915 
7916   // If the magnitude is big enough, there's no place for fraction part. If we
7917   // try to add 0.5 to this number, 1.0 will be added instead.
7918   if (exponent >= 52) {
7919     return *number;
7920   }
7921 
7922   if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7923 
7924   // Do not call NumberFromDouble() to avoid extra checks.
7925   return *isolate->factory()->NewNumber(std::floor(value + 0.5));
7926 }
7927 
7928 
RUNTIME_FUNCTION(Runtime_MathSqrtRT)7929 RUNTIME_FUNCTION(Runtime_MathSqrtRT) {
7930   HandleScope scope(isolate);
7931   ASSERT(args.length() == 1);
7932   isolate->counters()->math_sqrt()->Increment();
7933 
7934   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7935   return *isolate->factory()->NewNumber(fast_sqrt(x));
7936 }
7937 
7938 
RUNTIME_FUNCTION(Runtime_MathFround)7939 RUNTIME_FUNCTION(Runtime_MathFround) {
7940   HandleScope scope(isolate);
7941   ASSERT(args.length() == 1);
7942 
7943   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7944   float xf = static_cast<float>(x);
7945   return *isolate->factory()->NewNumber(xf);
7946 }
7947 
7948 
RUNTIME_FUNCTION(Runtime_DateMakeDay)7949 RUNTIME_FUNCTION(Runtime_DateMakeDay) {
7950   SealHandleScope shs(isolate);
7951   ASSERT(args.length() == 2);
7952 
7953   CONVERT_SMI_ARG_CHECKED(year, 0);
7954   CONVERT_SMI_ARG_CHECKED(month, 1);
7955 
7956   int days = isolate->date_cache()->DaysFromYearMonth(year, month);
7957   RUNTIME_ASSERT(Smi::IsValid(days));
7958   return Smi::FromInt(days);
7959 }
7960 
7961 
RUNTIME_FUNCTION(Runtime_DateSetValue)7962 RUNTIME_FUNCTION(Runtime_DateSetValue) {
7963   HandleScope scope(isolate);
7964   ASSERT(args.length() == 3);
7965 
7966   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7967   CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7968   CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7969 
7970   DateCache* date_cache = isolate->date_cache();
7971 
7972   Handle<Object> value;;
7973   bool is_value_nan = false;
7974   if (std::isnan(time)) {
7975     value = isolate->factory()->nan_value();
7976     is_value_nan = true;
7977   } else if (!is_utc &&
7978              (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7979               time > DateCache::kMaxTimeBeforeUTCInMs)) {
7980     value = isolate->factory()->nan_value();
7981     is_value_nan = true;
7982   } else {
7983     time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7984     if (time < -DateCache::kMaxTimeInMs ||
7985         time > DateCache::kMaxTimeInMs) {
7986       value = isolate->factory()->nan_value();
7987       is_value_nan = true;
7988     } else  {
7989       value = isolate->factory()->NewNumber(DoubleToInteger(time));
7990     }
7991   }
7992   date->SetValue(*value, is_value_nan);
7993   return *value;
7994 }
7995 
7996 
RUNTIME_FUNCTION(RuntimeHidden_NewSloppyArguments)7997 RUNTIME_FUNCTION(RuntimeHidden_NewSloppyArguments) {
7998   HandleScope scope(isolate);
7999   ASSERT(args.length() == 3);
8000 
8001   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
8002   Object** parameters = reinterpret_cast<Object**>(args[1]);
8003   CONVERT_SMI_ARG_CHECKED(argument_count, 2);
8004 
8005   Handle<JSObject> result =
8006       isolate->factory()->NewArgumentsObject(callee, argument_count);
8007   // Allocate the elements if needed.
8008   int parameter_count = callee->shared()->formal_parameter_count();
8009   if (argument_count > 0) {
8010     if (parameter_count > 0) {
8011       int mapped_count = Min(argument_count, parameter_count);
8012       Handle<FixedArray> parameter_map =
8013           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
8014       parameter_map->set_map(
8015           isolate->heap()->sloppy_arguments_elements_map());
8016 
8017       Handle<Map> map = Map::Copy(handle(result->map()));
8018       map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
8019 
8020       result->set_map(*map);
8021       result->set_elements(*parameter_map);
8022 
8023       // Store the context and the arguments array at the beginning of the
8024       // parameter map.
8025       Handle<Context> context(isolate->context());
8026       Handle<FixedArray> arguments =
8027           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8028       parameter_map->set(0, *context);
8029       parameter_map->set(1, *arguments);
8030 
8031       // Loop over the actual parameters backwards.
8032       int index = argument_count - 1;
8033       while (index >= mapped_count) {
8034         // These go directly in the arguments array and have no
8035         // corresponding slot in the parameter map.
8036         arguments->set(index, *(parameters - index - 1));
8037         --index;
8038       }
8039 
8040       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
8041       while (index >= 0) {
8042         // Detect duplicate names to the right in the parameter list.
8043         Handle<String> name(scope_info->ParameterName(index));
8044         int context_local_count = scope_info->ContextLocalCount();
8045         bool duplicate = false;
8046         for (int j = index + 1; j < parameter_count; ++j) {
8047           if (scope_info->ParameterName(j) == *name) {
8048             duplicate = true;
8049             break;
8050           }
8051         }
8052 
8053         if (duplicate) {
8054           // This goes directly in the arguments array with a hole in the
8055           // parameter map.
8056           arguments->set(index, *(parameters - index - 1));
8057           parameter_map->set_the_hole(index + 2);
8058         } else {
8059           // The context index goes in the parameter map with a hole in the
8060           // arguments array.
8061           int context_index = -1;
8062           for (int j = 0; j < context_local_count; ++j) {
8063             if (scope_info->ContextLocalName(j) == *name) {
8064               context_index = j;
8065               break;
8066             }
8067           }
8068           ASSERT(context_index >= 0);
8069           arguments->set_the_hole(index);
8070           parameter_map->set(index + 2, Smi::FromInt(
8071               Context::MIN_CONTEXT_SLOTS + context_index));
8072         }
8073 
8074         --index;
8075       }
8076     } else {
8077       // If there is no aliasing, the arguments object elements are not
8078       // special in any way.
8079       Handle<FixedArray> elements =
8080           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8081       result->set_elements(*elements);
8082       for (int i = 0; i < argument_count; ++i) {
8083         elements->set(i, *(parameters - i - 1));
8084       }
8085     }
8086   }
8087   return *result;
8088 }
8089 
8090 
RUNTIME_FUNCTION(RuntimeHidden_NewStrictArguments)8091 RUNTIME_FUNCTION(RuntimeHidden_NewStrictArguments) {
8092   HandleScope scope(isolate);
8093   ASSERT(args.length() == 3);
8094   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
8095   Object** parameters = reinterpret_cast<Object**>(args[1]);
8096   CONVERT_SMI_ARG_CHECKED(length, 2);
8097 
8098   Handle<JSObject> result =
8099         isolate->factory()->NewArgumentsObject(callee, length);
8100 
8101   if (length > 0) {
8102     Handle<FixedArray> array =
8103         isolate->factory()->NewUninitializedFixedArray(length);
8104     DisallowHeapAllocation no_gc;
8105     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
8106     for (int i = 0; i < length; i++) {
8107       array->set(i, *--parameters, mode);
8108     }
8109     result->set_elements(*array);
8110   }
8111   return *result;
8112 }
8113 
8114 
RUNTIME_FUNCTION(RuntimeHidden_NewClosureFromStubFailure)8115 RUNTIME_FUNCTION(RuntimeHidden_NewClosureFromStubFailure) {
8116   HandleScope scope(isolate);
8117   ASSERT(args.length() == 1);
8118   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
8119   Handle<Context> context(isolate->context());
8120   PretenureFlag pretenure_flag = NOT_TENURED;
8121   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
8122       shared,  context, pretenure_flag);
8123 }
8124 
8125 
RUNTIME_FUNCTION(RuntimeHidden_NewClosure)8126 RUNTIME_FUNCTION(RuntimeHidden_NewClosure) {
8127   HandleScope scope(isolate);
8128   ASSERT(args.length() == 3);
8129   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8130   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
8131   CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
8132 
8133   // The caller ensures that we pretenure closures that are assigned
8134   // directly to properties.
8135   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
8136   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
8137       shared, context, pretenure_flag);
8138 }
8139 
8140 
8141 // Find the arguments of the JavaScript function invocation that called
8142 // into C++ code. Collect these in a newly allocated array of handles (possibly
8143 // prefixed by a number of empty handles).
GetCallerArguments(Isolate * isolate,int prefix_argc,int * total_argc)8144 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
8145     Isolate* isolate,
8146     int prefix_argc,
8147     int* total_argc) {
8148   // Find frame containing arguments passed to the caller.
8149   JavaScriptFrameIterator it(isolate);
8150   JavaScriptFrame* frame = it.frame();
8151   List<JSFunction*> functions(2);
8152   frame->GetFunctions(&functions);
8153   if (functions.length() > 1) {
8154     int inlined_jsframe_index = functions.length() - 1;
8155     JSFunction* inlined_function = functions[inlined_jsframe_index];
8156     SlotRefValueBuilder slot_refs(
8157         frame,
8158         inlined_jsframe_index,
8159         inlined_function->shared()->formal_parameter_count());
8160 
8161     int args_count = slot_refs.args_length();
8162 
8163     *total_argc = prefix_argc + args_count;
8164     SmartArrayPointer<Handle<Object> > param_data(
8165         NewArray<Handle<Object> >(*total_argc));
8166     slot_refs.Prepare(isolate);
8167     for (int i = 0; i < args_count; i++) {
8168       Handle<Object> val = slot_refs.GetNext(isolate, 0);
8169       param_data[prefix_argc + i] = val;
8170     }
8171     slot_refs.Finish(isolate);
8172 
8173     return param_data;
8174   } else {
8175     it.AdvanceToArgumentsFrame();
8176     frame = it.frame();
8177     int args_count = frame->ComputeParametersCount();
8178 
8179     *total_argc = prefix_argc + args_count;
8180     SmartArrayPointer<Handle<Object> > param_data(
8181         NewArray<Handle<Object> >(*total_argc));
8182     for (int i = 0; i < args_count; i++) {
8183       Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
8184       param_data[prefix_argc + i] = val;
8185     }
8186     return param_data;
8187   }
8188 }
8189 
8190 
RUNTIME_FUNCTION(Runtime_FunctionBindArguments)8191 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) {
8192   HandleScope scope(isolate);
8193   ASSERT(args.length() == 4);
8194   CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
8195   CONVERT_ARG_HANDLE_CHECKED(Object, bindee, 1);
8196   CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2);
8197   CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3);
8198 
8199   // TODO(lrn): Create bound function in C++ code from premade shared info.
8200   bound_function->shared()->set_bound(true);
8201   // Get all arguments of calling function (Function.prototype.bind).
8202   int argc = 0;
8203   SmartArrayPointer<Handle<Object> > arguments =
8204       GetCallerArguments(isolate, 0, &argc);
8205   // Don't count the this-arg.
8206   if (argc > 0) {
8207     RUNTIME_ASSERT(arguments[0].is_identical_to(this_object));
8208     argc--;
8209   } else {
8210     RUNTIME_ASSERT(this_object->IsUndefined());
8211   }
8212   // Initialize array of bindings (function, this, and any existing arguments
8213   // if the function was already bound).
8214   Handle<FixedArray> new_bindings;
8215   int i;
8216   if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8217     Handle<FixedArray> old_bindings(
8218         JSFunction::cast(*bindee)->function_bindings());
8219     RUNTIME_ASSERT(old_bindings->length() > JSFunction::kBoundFunctionIndex);
8220     new_bindings =
8221         isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8222     bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8223                             isolate);
8224     i = 0;
8225     for (int n = old_bindings->length(); i < n; i++) {
8226       new_bindings->set(i, old_bindings->get(i));
8227     }
8228   } else {
8229     int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8230     new_bindings = isolate->factory()->NewFixedArray(array_size);
8231     new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8232     new_bindings->set(JSFunction::kBoundThisIndex, *this_object);
8233     i = 2;
8234   }
8235   // Copy arguments, skipping the first which is "this_arg".
8236   for (int j = 0; j < argc; j++, i++) {
8237     new_bindings->set(i, *arguments[j + 1]);
8238   }
8239   new_bindings->set_map_no_write_barrier(
8240       isolate->heap()->fixed_cow_array_map());
8241   bound_function->set_function_bindings(*new_bindings);
8242 
8243   // Update length. Have to remove the prototype first so that map migration
8244   // is happy about the number of fields.
8245   RUNTIME_ASSERT(bound_function->RemovePrototype());
8246   Handle<Map> bound_function_map(
8247       isolate->native_context()->bound_function_map());
8248   JSObject::MigrateToMap(bound_function, bound_function_map);
8249   Handle<String> length_string = isolate->factory()->length_string();
8250   PropertyAttributes attr =
8251       static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8252   RETURN_FAILURE_ON_EXCEPTION(
8253       isolate,
8254       JSObject::SetOwnPropertyIgnoreAttributes(bound_function, length_string,
8255                                                new_length, attr));
8256   return *bound_function;
8257 }
8258 
8259 
RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings)8260 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) {
8261   HandleScope handles(isolate);
8262   ASSERT(args.length() == 1);
8263   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8264   if (callable->IsJSFunction()) {
8265     Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8266     if (function->shared()->bound()) {
8267       Handle<FixedArray> bindings(function->function_bindings());
8268       RUNTIME_ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8269       return *isolate->factory()->NewJSArrayWithElements(bindings);
8270     }
8271   }
8272   return isolate->heap()->undefined_value();
8273 }
8274 
8275 
RUNTIME_FUNCTION(Runtime_NewObjectFromBound)8276 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) {
8277   HandleScope scope(isolate);
8278   ASSERT(args.length() == 1);
8279   // First argument is a function to use as a constructor.
8280   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8281   RUNTIME_ASSERT(function->shared()->bound());
8282 
8283   // The argument is a bound function. Extract its bound arguments
8284   // and callable.
8285   Handle<FixedArray> bound_args =
8286       Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8287   int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8288   Handle<Object> bound_function(
8289       JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
8290       isolate);
8291   ASSERT(!bound_function->IsJSFunction() ||
8292          !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8293 
8294   int total_argc = 0;
8295   SmartArrayPointer<Handle<Object> > param_data =
8296       GetCallerArguments(isolate, bound_argc, &total_argc);
8297   for (int i = 0; i < bound_argc; i++) {
8298     param_data[i] = Handle<Object>(bound_args->get(
8299         JSFunction::kBoundArgumentsStartIndex + i), isolate);
8300   }
8301 
8302   if (!bound_function->IsJSFunction()) {
8303     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8304         isolate, bound_function,
8305         Execution::TryGetConstructorDelegate(isolate, bound_function));
8306   }
8307   ASSERT(bound_function->IsJSFunction());
8308 
8309   Handle<Object> result;
8310   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8311       isolate, result,
8312       Execution::New(Handle<JSFunction>::cast(bound_function),
8313                      total_argc, param_data.get()));
8314   return *result;
8315 }
8316 
8317 
Runtime_NewObjectHelper(Isolate * isolate,Handle<Object> constructor,Handle<AllocationSite> site)8318 static Object* Runtime_NewObjectHelper(Isolate* isolate,
8319                                             Handle<Object> constructor,
8320                                             Handle<AllocationSite> site) {
8321   // If the constructor isn't a proper function we throw a type error.
8322   if (!constructor->IsJSFunction()) {
8323     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8324     Handle<Object> type_error =
8325         isolate->factory()->NewTypeError("not_constructor", arguments);
8326     return isolate->Throw(*type_error);
8327   }
8328 
8329   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8330 
8331   // If function should not have prototype, construction is not allowed. In this
8332   // case generated code bailouts here, since function has no initial_map.
8333   if (!function->should_have_prototype() && !function->shared()->bound()) {
8334     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8335     Handle<Object> type_error =
8336         isolate->factory()->NewTypeError("not_constructor", arguments);
8337     return isolate->Throw(*type_error);
8338   }
8339 
8340   Debug* debug = isolate->debug();
8341   // Handle stepping into constructors if step into is active.
8342   if (debug->StepInActive()) {
8343     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8344   }
8345 
8346   if (function->has_initial_map()) {
8347     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8348       // The 'Function' function ignores the receiver object when
8349       // called using 'new' and creates a new JSFunction object that
8350       // is returned.  The receiver object is only used for error
8351       // reporting if an error occurs when constructing the new
8352       // JSFunction. Factory::NewJSObject() should not be used to
8353       // allocate JSFunctions since it does not properly initialize
8354       // the shared part of the function. Since the receiver is
8355       // ignored anyway, we use the global object as the receiver
8356       // instead of a new JSFunction object. This way, errors are
8357       // reported the same way whether or not 'Function' is called
8358       // using 'new'.
8359       return isolate->context()->global_object();
8360     }
8361   }
8362 
8363   // The function should be compiled for the optimization hints to be
8364   // available.
8365   Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
8366 
8367   Handle<JSObject> result;
8368   if (site.is_null()) {
8369     result = isolate->factory()->NewJSObject(function);
8370   } else {
8371     result = isolate->factory()->NewJSObjectWithMemento(function, site);
8372   }
8373 
8374   isolate->counters()->constructed_objects()->Increment();
8375   isolate->counters()->constructed_objects_runtime()->Increment();
8376 
8377   return *result;
8378 }
8379 
8380 
RUNTIME_FUNCTION(RuntimeHidden_NewObject)8381 RUNTIME_FUNCTION(RuntimeHidden_NewObject) {
8382   HandleScope scope(isolate);
8383   ASSERT(args.length() == 1);
8384   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
8385   return Runtime_NewObjectHelper(isolate,
8386                                  constructor,
8387                                  Handle<AllocationSite>::null());
8388 }
8389 
8390 
RUNTIME_FUNCTION(RuntimeHidden_NewObjectWithAllocationSite)8391 RUNTIME_FUNCTION(RuntimeHidden_NewObjectWithAllocationSite) {
8392   HandleScope scope(isolate);
8393   ASSERT(args.length() == 2);
8394   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 1);
8395   CONVERT_ARG_HANDLE_CHECKED(Object, feedback, 0);
8396   Handle<AllocationSite> site;
8397   if (feedback->IsAllocationSite()) {
8398     // The feedback can be an AllocationSite or undefined.
8399     site = Handle<AllocationSite>::cast(feedback);
8400   }
8401   return Runtime_NewObjectHelper(isolate, constructor, site);
8402 }
8403 
8404 
RUNTIME_FUNCTION(RuntimeHidden_FinalizeInstanceSize)8405 RUNTIME_FUNCTION(RuntimeHidden_FinalizeInstanceSize) {
8406   HandleScope scope(isolate);
8407   ASSERT(args.length() == 1);
8408 
8409   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8410   function->CompleteInobjectSlackTracking();
8411 
8412   return isolate->heap()->undefined_value();
8413 }
8414 
8415 
RUNTIME_FUNCTION(RuntimeHidden_CompileUnoptimized)8416 RUNTIME_FUNCTION(RuntimeHidden_CompileUnoptimized) {
8417   HandleScope scope(isolate);
8418   ASSERT(args.length() == 1);
8419   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8420 #ifdef DEBUG
8421   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8422     PrintF("[unoptimized: ");
8423     function->PrintName();
8424     PrintF("]\n");
8425   }
8426 #endif
8427 
8428   // Compile the target function.
8429   ASSERT(function->shared()->allows_lazy_compilation());
8430 
8431   Handle<Code> code;
8432   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code,
8433                                      Compiler::GetUnoptimizedCode(function));
8434   function->ReplaceCode(*code);
8435 
8436   // All done. Return the compiled code.
8437   ASSERT(function->is_compiled());
8438   ASSERT(function->code()->kind() == Code::FUNCTION ||
8439          (FLAG_always_opt &&
8440           function->code()->kind() == Code::OPTIMIZED_FUNCTION));
8441   return *code;
8442 }
8443 
8444 
RUNTIME_FUNCTION(RuntimeHidden_CompileOptimized)8445 RUNTIME_FUNCTION(RuntimeHidden_CompileOptimized) {
8446   HandleScope scope(isolate);
8447   ASSERT(args.length() == 2);
8448   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8449   CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
8450 
8451   Handle<Code> unoptimized(function->shared()->code());
8452   if (!function->shared()->is_compiled()) {
8453     // If the function is not compiled, do not optimize.
8454     // This can happen if the debugger is activated and
8455     // the function is returned to the not compiled state.
8456     // TODO(yangguo): reconsider this.
8457     function->ReplaceCode(function->shared()->code());
8458   } else if (!isolate->use_crankshaft() ||
8459              function->shared()->optimization_disabled() ||
8460              isolate->DebuggerHasBreakPoints()) {
8461     // If the function is not optimizable or debugger is active continue
8462     // using the code from the full compiler.
8463     if (FLAG_trace_opt) {
8464       PrintF("[failed to optimize ");
8465       function->PrintName();
8466       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8467           function->shared()->optimization_disabled() ? "F" : "T",
8468           isolate->DebuggerHasBreakPoints() ? "T" : "F");
8469     }
8470     function->ReplaceCode(*unoptimized);
8471   } else {
8472     Compiler::ConcurrencyMode mode = concurrent ? Compiler::CONCURRENT
8473                                                 : Compiler::NOT_CONCURRENT;
8474     Handle<Code> code;
8475     if (Compiler::GetOptimizedCode(
8476             function, unoptimized, mode).ToHandle(&code)) {
8477       function->ReplaceCode(*code);
8478     } else {
8479       function->ReplaceCode(*unoptimized);
8480     }
8481   }
8482 
8483   ASSERT(function->code()->kind() == Code::FUNCTION ||
8484          function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
8485          function->IsInOptimizationQueue());
8486   return function->code();
8487 }
8488 
8489 
8490 class ActivationsFinder : public ThreadVisitor {
8491  public:
8492   Code* code_;
8493   bool has_code_activations_;
8494 
ActivationsFinder(Code * code)8495   explicit ActivationsFinder(Code* code)
8496     : code_(code),
8497       has_code_activations_(false) { }
8498 
VisitThread(Isolate * isolate,ThreadLocalTop * top)8499   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8500     JavaScriptFrameIterator it(isolate, top);
8501     VisitFrames(&it);
8502   }
8503 
VisitFrames(JavaScriptFrameIterator * it)8504   void VisitFrames(JavaScriptFrameIterator* it) {
8505     for (; !it->done(); it->Advance()) {
8506       JavaScriptFrame* frame = it->frame();
8507       if (code_->contains(frame->pc())) has_code_activations_ = true;
8508     }
8509   }
8510 };
8511 
8512 
RUNTIME_FUNCTION(RuntimeHidden_NotifyStubFailure)8513 RUNTIME_FUNCTION(RuntimeHidden_NotifyStubFailure) {
8514   HandleScope scope(isolate);
8515   ASSERT(args.length() == 0);
8516   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8517   ASSERT(AllowHeapAllocation::IsAllowed());
8518   delete deoptimizer;
8519   return isolate->heap()->undefined_value();
8520 }
8521 
8522 
RUNTIME_FUNCTION(RuntimeHidden_NotifyDeoptimized)8523 RUNTIME_FUNCTION(RuntimeHidden_NotifyDeoptimized) {
8524   HandleScope scope(isolate);
8525   ASSERT(args.length() == 1);
8526   CONVERT_SMI_ARG_CHECKED(type_arg, 0);
8527   Deoptimizer::BailoutType type =
8528       static_cast<Deoptimizer::BailoutType>(type_arg);
8529   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8530   ASSERT(AllowHeapAllocation::IsAllowed());
8531 
8532   Handle<JSFunction> function = deoptimizer->function();
8533   Handle<Code> optimized_code = deoptimizer->compiled_code();
8534 
8535   ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
8536   ASSERT(type == deoptimizer->bailout_type());
8537 
8538   // Make sure to materialize objects before causing any allocation.
8539   JavaScriptFrameIterator it(isolate);
8540   deoptimizer->MaterializeHeapObjects(&it);
8541   delete deoptimizer;
8542 
8543   JavaScriptFrame* frame = it.frame();
8544   RUNTIME_ASSERT(frame->function()->IsJSFunction());
8545   ASSERT(frame->function() == *function);
8546 
8547   // Avoid doing too much work when running with --always-opt and keep
8548   // the optimized code around.
8549   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8550     return isolate->heap()->undefined_value();
8551   }
8552 
8553   // Search for other activations of the same function and code.
8554   ActivationsFinder activations_finder(*optimized_code);
8555   activations_finder.VisitFrames(&it);
8556   isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8557 
8558   if (!activations_finder.has_code_activations_) {
8559     if (function->code() == *optimized_code) {
8560       if (FLAG_trace_deopt) {
8561         PrintF("[removing optimized code for: ");
8562         function->PrintName();
8563         PrintF("]\n");
8564       }
8565       function->ReplaceCode(function->shared()->code());
8566       // Evict optimized code for this function from the cache so that it
8567       // doesn't get used for new closures.
8568       function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8569                                                     "notify deoptimized");
8570     }
8571   } else {
8572     // TODO(titzer): we should probably do DeoptimizeCodeList(code)
8573     // unconditionally if the code is not already marked for deoptimization.
8574     // If there is an index by shared function info, all the better.
8575     Deoptimizer::DeoptimizeFunction(*function);
8576   }
8577 
8578   return isolate->heap()->undefined_value();
8579 }
8580 
8581 
RUNTIME_FUNCTION(Runtime_DeoptimizeFunction)8582 RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
8583   HandleScope scope(isolate);
8584   ASSERT(args.length() == 1);
8585   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8586   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8587 
8588   Deoptimizer::DeoptimizeFunction(*function);
8589 
8590   return isolate->heap()->undefined_value();
8591 }
8592 
8593 
RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback)8594 RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
8595   HandleScope scope(isolate);
8596   ASSERT(args.length() == 1);
8597   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8598   function->shared()->ClearTypeFeedbackInfo();
8599   Code* unoptimized = function->shared()->code();
8600   if (unoptimized->kind() == Code::FUNCTION) {
8601     unoptimized->ClearInlineCaches();
8602   }
8603   return isolate->heap()->undefined_value();
8604 }
8605 
8606 
RUNTIME_FUNCTION(Runtime_RunningInSimulator)8607 RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
8608   SealHandleScope shs(isolate);
8609   ASSERT(args.length() == 0);
8610 #if defined(USE_SIMULATOR)
8611   return isolate->heap()->true_value();
8612 #else
8613   return isolate->heap()->false_value();
8614 #endif
8615 }
8616 
8617 
RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported)8618 RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
8619   SealHandleScope shs(isolate);
8620   ASSERT(args.length() == 0);
8621   return isolate->heap()->ToBoolean(
8622       isolate->concurrent_recompilation_enabled());
8623 }
8624 
8625 
RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall)8626 RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
8627   HandleScope scope(isolate);
8628   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8629   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8630 
8631   if (!function->IsOptimizable() &&
8632       !function->IsMarkedForConcurrentOptimization() &&
8633       !function->IsInOptimizationQueue()) {
8634     return isolate->heap()->undefined_value();
8635   }
8636 
8637   function->MarkForOptimization();
8638 
8639   Code* unoptimized = function->shared()->code();
8640   if (args.length() == 2 &&
8641       unoptimized->kind() == Code::FUNCTION) {
8642     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8643     if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
8644       // Start patching from the currently patched loop nesting level.
8645       int current_level = unoptimized->allow_osr_at_loop_nesting_level();
8646       ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
8647       if (FLAG_use_osr) {
8648         for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
8649           unoptimized->set_allow_osr_at_loop_nesting_level(i);
8650           isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8651         }
8652       }
8653     } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent")) &&
8654                isolate->concurrent_recompilation_enabled()) {
8655       function->MarkForConcurrentOptimization();
8656     }
8657   }
8658 
8659   return isolate->heap()->undefined_value();
8660 }
8661 
8662 
RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction)8663 RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
8664   HandleScope scope(isolate);
8665   ASSERT(args.length() == 1);
8666   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8667   function->shared()->set_optimization_disabled(true);
8668   return isolate->heap()->undefined_value();
8669 }
8670 
8671 
RUNTIME_FUNCTION(Runtime_GetOptimizationStatus)8672 RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
8673   HandleScope scope(isolate);
8674   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8675   if (!isolate->use_crankshaft()) {
8676     return Smi::FromInt(4);  // 4 == "never".
8677   }
8678   bool sync_with_compiler_thread = true;
8679   if (args.length() == 2) {
8680     CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
8681     if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
8682       sync_with_compiler_thread = false;
8683     }
8684   }
8685   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8686   if (isolate->concurrent_recompilation_enabled() &&
8687       sync_with_compiler_thread) {
8688     while (function->IsInOptimizationQueue()) {
8689       isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8690       OS::Sleep(50);
8691     }
8692   }
8693   if (FLAG_always_opt) {
8694     // We may have always opt, but that is more best-effort than a real
8695     // promise, so we still say "no" if it is not optimized.
8696     return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8697                                    : Smi::FromInt(2);  // 2 == "no".
8698   }
8699   if (FLAG_deopt_every_n_times) {
8700     return Smi::FromInt(6);  // 6 == "maybe deopted".
8701   }
8702   return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8703                                  : Smi::FromInt(2);  // 2 == "no".
8704 }
8705 
8706 
RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation)8707 RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
8708   ASSERT(args.length() == 0);
8709   RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
8710   RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
8711   isolate->optimizing_compiler_thread()->Unblock();
8712   return isolate->heap()->undefined_value();
8713 }
8714 
8715 
RUNTIME_FUNCTION(Runtime_GetOptimizationCount)8716 RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
8717   HandleScope scope(isolate);
8718   ASSERT(args.length() == 1);
8719   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8720   return Smi::FromInt(function->shared()->opt_count());
8721 }
8722 
8723 
IsSuitableForOnStackReplacement(Isolate * isolate,Handle<JSFunction> function,Handle<Code> current_code)8724 static bool IsSuitableForOnStackReplacement(Isolate* isolate,
8725                                             Handle<JSFunction> function,
8726                                             Handle<Code> current_code) {
8727   // Keep track of whether we've succeeded in optimizing.
8728   if (!isolate->use_crankshaft() || !current_code->optimizable()) return false;
8729   // If we are trying to do OSR when there are already optimized
8730   // activations of the function, it means (a) the function is directly or
8731   // indirectly recursive and (b) an optimized invocation has been
8732   // deoptimized so that we are currently in an unoptimized activation.
8733   // Check for optimized activations of this function.
8734   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
8735     JavaScriptFrame* frame = it.frame();
8736     if (frame->is_optimized() && frame->function() == *function) return false;
8737   }
8738 
8739   return true;
8740 }
8741 
8742 
RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement)8743 RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
8744   HandleScope scope(isolate);
8745   ASSERT(args.length() == 1);
8746   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8747   Handle<Code> caller_code(function->shared()->code());
8748 
8749   // We're not prepared to handle a function with arguments object.
8750   ASSERT(!function->shared()->uses_arguments());
8751 
8752   RUNTIME_ASSERT(FLAG_use_osr);
8753 
8754   // Passing the PC in the javascript frame from the caller directly is
8755   // not GC safe, so we walk the stack to get it.
8756   JavaScriptFrameIterator it(isolate);
8757   JavaScriptFrame* frame = it.frame();
8758   if (!caller_code->contains(frame->pc())) {
8759     // Code on the stack may not be the code object referenced by the shared
8760     // function info.  It may have been replaced to include deoptimization data.
8761     caller_code = Handle<Code>(frame->LookupCode());
8762   }
8763 
8764   uint32_t pc_offset = static_cast<uint32_t>(
8765       frame->pc() - caller_code->instruction_start());
8766 
8767 #ifdef DEBUG
8768   ASSERT_EQ(frame->function(), *function);
8769   ASSERT_EQ(frame->LookupCode(), *caller_code);
8770   ASSERT(caller_code->contains(frame->pc()));
8771 #endif  // DEBUG
8772 
8773 
8774   BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
8775   ASSERT(!ast_id.IsNone());
8776 
8777   Compiler::ConcurrencyMode mode =
8778       isolate->concurrent_osr_enabled() &&
8779       (function->shared()->ast_node_count() > 512) ? Compiler::CONCURRENT
8780                                                    : Compiler::NOT_CONCURRENT;
8781   Handle<Code> result = Handle<Code>::null();
8782 
8783   OptimizedCompileJob* job = NULL;
8784   if (mode == Compiler::CONCURRENT) {
8785     // Gate the OSR entry with a stack check.
8786     BackEdgeTable::AddStackCheck(caller_code, pc_offset);
8787     // Poll already queued compilation jobs.
8788     OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
8789     if (thread->IsQueuedForOSR(function, ast_id)) {
8790       if (FLAG_trace_osr) {
8791         PrintF("[OSR - Still waiting for queued: ");
8792         function->PrintName();
8793         PrintF(" at AST id %d]\n", ast_id.ToInt());
8794       }
8795       return NULL;
8796     }
8797 
8798     job = thread->FindReadyOSRCandidate(function, ast_id);
8799   }
8800 
8801   if (job != NULL) {
8802     if (FLAG_trace_osr) {
8803       PrintF("[OSR - Found ready: ");
8804       function->PrintName();
8805       PrintF(" at AST id %d]\n", ast_id.ToInt());
8806     }
8807     result = Compiler::GetConcurrentlyOptimizedCode(job);
8808   } else if (IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
8809     if (FLAG_trace_osr) {
8810       PrintF("[OSR - Compiling: ");
8811       function->PrintName();
8812       PrintF(" at AST id %d]\n", ast_id.ToInt());
8813     }
8814     MaybeHandle<Code> maybe_result = Compiler::GetOptimizedCode(
8815         function, caller_code, mode, ast_id);
8816     if (maybe_result.ToHandle(&result) &&
8817         result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
8818       // Optimization is queued.  Return to check later.
8819       return NULL;
8820     }
8821   }
8822 
8823   // Revert the patched back edge table, regardless of whether OSR succeeds.
8824   BackEdgeTable::Revert(isolate, *caller_code);
8825 
8826   // Check whether we ended up with usable optimized code.
8827   if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
8828     DeoptimizationInputData* data =
8829         DeoptimizationInputData::cast(result->deoptimization_data());
8830 
8831     if (data->OsrPcOffset()->value() >= 0) {
8832       ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8833       if (FLAG_trace_osr) {
8834         PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
8835                ast_id.ToInt(), data->OsrPcOffset()->value());
8836       }
8837       // TODO(titzer): this is a massive hack to make the deopt counts
8838       // match. Fix heuristics for reenabling optimizations!
8839       function->shared()->increment_deopt_count();
8840 
8841       // TODO(titzer): Do not install code into the function.
8842       function->ReplaceCode(*result);
8843       return *result;
8844     }
8845   }
8846 
8847   // Failed.
8848   if (FLAG_trace_osr) {
8849     PrintF("[OSR - Failed: ");
8850     function->PrintName();
8851     PrintF(" at AST id %d]\n", ast_id.ToInt());
8852   }
8853 
8854   if (!function->IsOptimized()) {
8855     function->ReplaceCode(function->shared()->code());
8856   }
8857   return NULL;
8858 }
8859 
8860 
RUNTIME_FUNCTION(Runtime_SetAllocationTimeout)8861 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
8862   SealHandleScope shs(isolate);
8863   ASSERT(args.length() == 2 || args.length() == 3);
8864 #ifdef DEBUG
8865   CONVERT_SMI_ARG_CHECKED(interval, 0);
8866   CONVERT_SMI_ARG_CHECKED(timeout, 1);
8867   isolate->heap()->set_allocation_timeout(timeout);
8868   FLAG_gc_interval = interval;
8869   if (args.length() == 3) {
8870     // Enable/disable inline allocation if requested.
8871     CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
8872     if (inline_allocation) {
8873       isolate->heap()->EnableInlineAllocation();
8874     } else {
8875       isolate->heap()->DisableInlineAllocation();
8876     }
8877   }
8878 #endif
8879   return isolate->heap()->undefined_value();
8880 }
8881 
8882 
RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping)8883 RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
8884   SealHandleScope shs(isolate);
8885   ASSERT(args.length() == 0);
8886   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8887   return isolate->heap()->undefined_value();
8888 }
8889 
8890 
RUNTIME_FUNCTION(Runtime_GetRootNaN)8891 RUNTIME_FUNCTION(Runtime_GetRootNaN) {
8892   SealHandleScope shs(isolate);
8893   ASSERT(args.length() == 0);
8894   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8895   return isolate->heap()->nan_value();
8896 }
8897 
8898 
RUNTIME_FUNCTION(Runtime_Call)8899 RUNTIME_FUNCTION(Runtime_Call) {
8900   HandleScope scope(isolate);
8901   ASSERT(args.length() >= 2);
8902   int argc = args.length() - 2;
8903   CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8904   Object* receiver = args[0];
8905 
8906   // If there are too many arguments, allocate argv via malloc.
8907   const int argv_small_size = 10;
8908   Handle<Object> argv_small_buffer[argv_small_size];
8909   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8910   Handle<Object>* argv = argv_small_buffer;
8911   if (argc > argv_small_size) {
8912     argv = new Handle<Object>[argc];
8913     if (argv == NULL) return isolate->StackOverflow();
8914     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8915   }
8916 
8917   for (int i = 0; i < argc; ++i) {
8918      argv[i] = Handle<Object>(args[1 + i], isolate);
8919   }
8920 
8921   Handle<JSReceiver> hfun(fun);
8922   Handle<Object> hreceiver(receiver, isolate);
8923   Handle<Object> result;
8924   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8925       isolate, result,
8926       Execution::Call(isolate, hfun, hreceiver, argc, argv, true));
8927   return *result;
8928 }
8929 
8930 
RUNTIME_FUNCTION(Runtime_Apply)8931 RUNTIME_FUNCTION(Runtime_Apply) {
8932   HandleScope scope(isolate);
8933   ASSERT(args.length() == 5);
8934   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8935   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
8936   CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8937   CONVERT_SMI_ARG_CHECKED(offset, 3);
8938   CONVERT_SMI_ARG_CHECKED(argc, 4);
8939   RUNTIME_ASSERT(offset >= 0);
8940   // Loose upper bound to allow fuzzing. We'll most likely run out of
8941   // stack space before hitting this limit.
8942   static int kMaxArgc = 1000000;
8943   RUNTIME_ASSERT(argc >= 0 && argc <= kMaxArgc);
8944 
8945   // If there are too many arguments, allocate argv via malloc.
8946   const int argv_small_size = 10;
8947   Handle<Object> argv_small_buffer[argv_small_size];
8948   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8949   Handle<Object>* argv = argv_small_buffer;
8950   if (argc > argv_small_size) {
8951     argv = new Handle<Object>[argc];
8952     if (argv == NULL) return isolate->StackOverflow();
8953     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8954   }
8955 
8956   for (int i = 0; i < argc; ++i) {
8957     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8958         isolate, argv[i],
8959         Object::GetElement(isolate, arguments, offset + i));
8960   }
8961 
8962   Handle<Object> result;
8963   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
8964       isolate, result,
8965       Execution::Call(isolate, fun, receiver, argc, argv, true));
8966   return *result;
8967 }
8968 
8969 
RUNTIME_FUNCTION(Runtime_GetFunctionDelegate)8970 RUNTIME_FUNCTION(Runtime_GetFunctionDelegate) {
8971   HandleScope scope(isolate);
8972   ASSERT(args.length() == 1);
8973   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
8974   RUNTIME_ASSERT(!object->IsJSFunction());
8975   return *Execution::GetFunctionDelegate(isolate, object);
8976 }
8977 
8978 
RUNTIME_FUNCTION(Runtime_GetConstructorDelegate)8979 RUNTIME_FUNCTION(Runtime_GetConstructorDelegate) {
8980   HandleScope scope(isolate);
8981   ASSERT(args.length() == 1);
8982   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
8983   RUNTIME_ASSERT(!object->IsJSFunction());
8984   return *Execution::GetConstructorDelegate(isolate, object);
8985 }
8986 
8987 
RUNTIME_FUNCTION(RuntimeHidden_NewGlobalContext)8988 RUNTIME_FUNCTION(RuntimeHidden_NewGlobalContext) {
8989   HandleScope scope(isolate);
8990   ASSERT(args.length() == 2);
8991 
8992   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8993   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
8994   Handle<Context> result =
8995       isolate->factory()->NewGlobalContext(function, scope_info);
8996 
8997   ASSERT(function->context() == isolate->context());
8998   ASSERT(function->context()->global_object() == result->global_object());
8999   result->global_object()->set_global_context(*result);
9000   return *result;
9001 }
9002 
9003 
RUNTIME_FUNCTION(RuntimeHidden_NewFunctionContext)9004 RUNTIME_FUNCTION(RuntimeHidden_NewFunctionContext) {
9005   HandleScope scope(isolate);
9006   ASSERT(args.length() == 1);
9007 
9008   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9009   int length = function->shared()->scope_info()->ContextLength();
9010   return *isolate->factory()->NewFunctionContext(length, function);
9011 }
9012 
9013 
RUNTIME_FUNCTION(RuntimeHidden_PushWithContext)9014 RUNTIME_FUNCTION(RuntimeHidden_PushWithContext) {
9015   HandleScope scope(isolate);
9016   ASSERT(args.length() == 2);
9017   Handle<JSReceiver> extension_object;
9018   if (args[0]->IsJSReceiver()) {
9019     extension_object = args.at<JSReceiver>(0);
9020   } else {
9021     // Try to convert the object to a proper JavaScript object.
9022     MaybeHandle<JSReceiver> maybe_object =
9023         Object::ToObject(isolate, args.at<Object>(0));
9024     if (!maybe_object.ToHandle(&extension_object)) {
9025       Handle<Object> handle = args.at<Object>(0);
9026       Handle<Object> result =
9027           isolate->factory()->NewTypeError("with_expression",
9028                                            HandleVector(&handle, 1));
9029       return isolate->Throw(*result);
9030     }
9031   }
9032 
9033   Handle<JSFunction> function;
9034   if (args[1]->IsSmi()) {
9035     // A smi sentinel indicates a context nested inside global code rather
9036     // than some function.  There is a canonical empty function that can be
9037     // gotten from the native context.
9038     function = handle(isolate->context()->native_context()->closure());
9039   } else {
9040     function = args.at<JSFunction>(1);
9041   }
9042 
9043   Handle<Context> current(isolate->context());
9044   Handle<Context> context = isolate->factory()->NewWithContext(
9045       function, current, extension_object);
9046   isolate->set_context(*context);
9047   return *context;
9048 }
9049 
9050 
RUNTIME_FUNCTION(RuntimeHidden_PushCatchContext)9051 RUNTIME_FUNCTION(RuntimeHidden_PushCatchContext) {
9052   HandleScope scope(isolate);
9053   ASSERT(args.length() == 3);
9054   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
9055   CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
9056   Handle<JSFunction> function;
9057   if (args[2]->IsSmi()) {
9058     // A smi sentinel indicates a context nested inside global code rather
9059     // than some function.  There is a canonical empty function that can be
9060     // gotten from the native context.
9061     function = handle(isolate->context()->native_context()->closure());
9062   } else {
9063     function = args.at<JSFunction>(2);
9064   }
9065   Handle<Context> current(isolate->context());
9066   Handle<Context> context = isolate->factory()->NewCatchContext(
9067       function, current, name, thrown_object);
9068   isolate->set_context(*context);
9069   return *context;
9070 }
9071 
9072 
RUNTIME_FUNCTION(RuntimeHidden_PushBlockContext)9073 RUNTIME_FUNCTION(RuntimeHidden_PushBlockContext) {
9074   HandleScope scope(isolate);
9075   ASSERT(args.length() == 2);
9076   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
9077   Handle<JSFunction> function;
9078   if (args[1]->IsSmi()) {
9079     // A smi sentinel indicates a context nested inside global code rather
9080     // than some function.  There is a canonical empty function that can be
9081     // gotten from the native context.
9082     function = handle(isolate->context()->native_context()->closure());
9083   } else {
9084     function = args.at<JSFunction>(1);
9085   }
9086   Handle<Context> current(isolate->context());
9087   Handle<Context> context = isolate->factory()->NewBlockContext(
9088       function, current, scope_info);
9089   isolate->set_context(*context);
9090   return *context;
9091 }
9092 
9093 
RUNTIME_FUNCTION(Runtime_IsJSModule)9094 RUNTIME_FUNCTION(Runtime_IsJSModule) {
9095   SealHandleScope shs(isolate);
9096   ASSERT(args.length() == 1);
9097   CONVERT_ARG_CHECKED(Object, obj, 0);
9098   return isolate->heap()->ToBoolean(obj->IsJSModule());
9099 }
9100 
9101 
RUNTIME_FUNCTION(RuntimeHidden_PushModuleContext)9102 RUNTIME_FUNCTION(RuntimeHidden_PushModuleContext) {
9103   SealHandleScope shs(isolate);
9104   ASSERT(args.length() == 2);
9105   CONVERT_SMI_ARG_CHECKED(index, 0);
9106 
9107   if (!args[1]->IsScopeInfo()) {
9108     // Module already initialized. Find hosting context and retrieve context.
9109     Context* host = Context::cast(isolate->context())->global_context();
9110     Context* context = Context::cast(host->get(index));
9111     ASSERT(context->previous() == isolate->context());
9112     isolate->set_context(context);
9113     return context;
9114   }
9115 
9116   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
9117 
9118   // Allocate module context.
9119   HandleScope scope(isolate);
9120   Factory* factory = isolate->factory();
9121   Handle<Context> context = factory->NewModuleContext(scope_info);
9122   Handle<JSModule> module = factory->NewJSModule(context, scope_info);
9123   context->set_module(*module);
9124   Context* previous = isolate->context();
9125   context->set_previous(previous);
9126   context->set_closure(previous->closure());
9127   context->set_global_object(previous->global_object());
9128   isolate->set_context(*context);
9129 
9130   // Find hosting scope and initialize internal variable holding module there.
9131   previous->global_context()->set(index, *context);
9132 
9133   return *context;
9134 }
9135 
9136 
RUNTIME_FUNCTION(RuntimeHidden_DeclareModules)9137 RUNTIME_FUNCTION(RuntimeHidden_DeclareModules) {
9138   HandleScope scope(isolate);
9139   ASSERT(args.length() == 1);
9140   CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
9141   Context* host_context = isolate->context();
9142 
9143   for (int i = 0; i < descriptions->length(); ++i) {
9144     Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
9145     int host_index = description->host_index();
9146     Handle<Context> context(Context::cast(host_context->get(host_index)));
9147     Handle<JSModule> module(context->module());
9148 
9149     for (int j = 0; j < description->length(); ++j) {
9150       Handle<String> name(description->name(j));
9151       VariableMode mode = description->mode(j);
9152       int index = description->index(j);
9153       switch (mode) {
9154         case VAR:
9155         case LET:
9156         case CONST:
9157         case CONST_LEGACY: {
9158           PropertyAttributes attr =
9159               IsImmutableVariableMode(mode) ? FROZEN : SEALED;
9160           Handle<AccessorInfo> info =
9161               Accessors::MakeModuleExport(name, index, attr);
9162           Handle<Object> result =
9163               JSObject::SetAccessor(module, info).ToHandleChecked();
9164           ASSERT(!result->IsUndefined());
9165           USE(result);
9166           break;
9167         }
9168         case MODULE: {
9169           Object* referenced_context = Context::cast(host_context)->get(index);
9170           Handle<JSModule> value(Context::cast(referenced_context)->module());
9171           JSReceiver::SetProperty(module, name, value, FROZEN, STRICT).Assert();
9172           break;
9173         }
9174         case INTERNAL:
9175         case TEMPORARY:
9176         case DYNAMIC:
9177         case DYNAMIC_GLOBAL:
9178         case DYNAMIC_LOCAL:
9179           UNREACHABLE();
9180       }
9181     }
9182 
9183     JSObject::PreventExtensions(module).Assert();
9184   }
9185 
9186   ASSERT(!isolate->has_pending_exception());
9187   return isolate->heap()->undefined_value();
9188 }
9189 
9190 
RUNTIME_FUNCTION(RuntimeHidden_DeleteContextSlot)9191 RUNTIME_FUNCTION(RuntimeHidden_DeleteContextSlot) {
9192   HandleScope scope(isolate);
9193   ASSERT(args.length() == 2);
9194 
9195   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
9196   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
9197 
9198   int index;
9199   PropertyAttributes attributes;
9200   ContextLookupFlags flags = FOLLOW_CHAINS;
9201   BindingFlags binding_flags;
9202   Handle<Object> holder = context->Lookup(name,
9203                                           flags,
9204                                           &index,
9205                                           &attributes,
9206                                           &binding_flags);
9207 
9208   // If the slot was not found the result is true.
9209   if (holder.is_null()) {
9210     return isolate->heap()->true_value();
9211   }
9212 
9213   // If the slot was found in a context, it should be DONT_DELETE.
9214   if (holder->IsContext()) {
9215     return isolate->heap()->false_value();
9216   }
9217 
9218   // The slot was found in a JSObject, either a context extension object,
9219   // the global object, or the subject of a with.  Try to delete it
9220   // (respecting DONT_DELETE).
9221   Handle<JSObject> object = Handle<JSObject>::cast(holder);
9222   Handle<Object> result;
9223   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9224       isolate, result,
9225       JSReceiver::DeleteProperty(object, name));
9226   return *result;
9227 }
9228 
9229 
9230 // A mechanism to return a pair of Object pointers in registers (if possible).
9231 // How this is achieved is calling convention-dependent.
9232 // All currently supported x86 compiles uses calling conventions that are cdecl
9233 // variants where a 64-bit value is returned in two 32-bit registers
9234 // (edx:eax on ia32, r1:r0 on ARM).
9235 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9236 // In Win64 calling convention, a struct of two pointers is returned in memory,
9237 // allocated by the caller, and passed as a pointer in a hidden first parameter.
9238 #ifdef V8_HOST_ARCH_64_BIT
9239 struct ObjectPair {
9240   Object* x;
9241   Object* y;
9242 };
9243 
9244 
MakePair(Object * x,Object * y)9245 static inline ObjectPair MakePair(Object* x, Object* y) {
9246   ObjectPair result = {x, y};
9247   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9248   // In Win64 they are assigned to a hidden first argument.
9249   return result;
9250 }
9251 #else
9252 typedef uint64_t ObjectPair;
MakePair(Object * x,Object * y)9253 static inline ObjectPair MakePair(Object* x, Object* y) {
9254 #if defined(V8_TARGET_LITTLE_ENDIAN)
9255   return reinterpret_cast<uint32_t>(x) |
9256       (reinterpret_cast<ObjectPair>(y) << 32);
9257 #elif defined(V8_TARGET_BIG_ENDIAN)
9258     return reinterpret_cast<uint32_t>(y) |
9259         (reinterpret_cast<ObjectPair>(x) << 32);
9260 #else
9261 #error Unknown endianness
9262 #endif
9263 }
9264 #endif
9265 
9266 
ComputeReceiverForNonGlobal(Isolate * isolate,JSObject * holder)9267 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9268                                            JSObject* holder) {
9269   ASSERT(!holder->IsGlobalObject());
9270   Context* top = isolate->context();
9271   // Get the context extension function.
9272   JSFunction* context_extension_function =
9273       top->native_context()->context_extension_function();
9274   // If the holder isn't a context extension object, we just return it
9275   // as the receiver. This allows arguments objects to be used as
9276   // receivers, but only if they are put in the context scope chain
9277   // explicitly via a with-statement.
9278   Object* constructor = holder->map()->constructor();
9279   if (constructor != context_extension_function) return holder;
9280   // Fall back to using the global object as the implicit receiver if
9281   // the property turns out to be a local variable allocated in a
9282   // context extension object - introduced via eval.
9283   return isolate->heap()->undefined_value();
9284 }
9285 
9286 
LoadContextSlotHelper(Arguments args,Isolate * isolate,bool throw_error)9287 static ObjectPair LoadContextSlotHelper(Arguments args,
9288                                         Isolate* isolate,
9289                                         bool throw_error) {
9290   HandleScope scope(isolate);
9291   ASSERT_EQ(2, args.length());
9292 
9293   if (!args[0]->IsContext() || !args[1]->IsString()) {
9294     return MakePair(isolate->ThrowIllegalOperation(), NULL);
9295   }
9296   Handle<Context> context = args.at<Context>(0);
9297   Handle<String> name = args.at<String>(1);
9298 
9299   int index;
9300   PropertyAttributes attributes;
9301   ContextLookupFlags flags = FOLLOW_CHAINS;
9302   BindingFlags binding_flags;
9303   Handle<Object> holder = context->Lookup(name,
9304                                           flags,
9305                                           &index,
9306                                           &attributes,
9307                                           &binding_flags);
9308   if (isolate->has_pending_exception()) {
9309     return MakePair(isolate->heap()->exception(), NULL);
9310   }
9311 
9312   // If the index is non-negative, the slot has been found in a context.
9313   if (index >= 0) {
9314     ASSERT(holder->IsContext());
9315     // If the "property" we were looking for is a local variable, the
9316     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9317     Handle<Object> receiver = isolate->factory()->undefined_value();
9318     Object* value = Context::cast(*holder)->get(index);
9319     // Check for uninitialized bindings.
9320     switch (binding_flags) {
9321       case MUTABLE_CHECK_INITIALIZED:
9322       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
9323         if (value->IsTheHole()) {
9324           Handle<Object> reference_error =
9325               isolate->factory()->NewReferenceError("not_defined",
9326                                                     HandleVector(&name, 1));
9327           return MakePair(isolate->Throw(*reference_error), NULL);
9328         }
9329         // FALLTHROUGH
9330       case MUTABLE_IS_INITIALIZED:
9331       case IMMUTABLE_IS_INITIALIZED:
9332       case IMMUTABLE_IS_INITIALIZED_HARMONY:
9333         ASSERT(!value->IsTheHole());
9334         return MakePair(value, *receiver);
9335       case IMMUTABLE_CHECK_INITIALIZED:
9336         if (value->IsTheHole()) {
9337           ASSERT((attributes & READ_ONLY) != 0);
9338           value = isolate->heap()->undefined_value();
9339         }
9340         return MakePair(value, *receiver);
9341       case MISSING_BINDING:
9342         UNREACHABLE();
9343         return MakePair(NULL, NULL);
9344     }
9345   }
9346 
9347   // Otherwise, if the slot was found the holder is a context extension
9348   // object, subject of a with, or a global object.  We read the named
9349   // property from it.
9350   if (!holder.is_null()) {
9351     Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9352     ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name));
9353     // GetProperty below can cause GC.
9354     Handle<Object> receiver_handle(
9355         object->IsGlobalObject()
9356             ? Object::cast(isolate->heap()->undefined_value())
9357             : object->IsJSProxy() ? static_cast<Object*>(*object)
9358                 : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9359         isolate);
9360 
9361     // No need to unhole the value here.  This is taken care of by the
9362     // GetProperty function.
9363     Handle<Object> value;
9364     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9365         isolate, value,
9366         Object::GetProperty(object, name),
9367         MakePair(isolate->heap()->exception(), NULL));
9368     return MakePair(*value, *receiver_handle);
9369   }
9370 
9371   if (throw_error) {
9372     // The property doesn't exist - throw exception.
9373     Handle<Object> reference_error =
9374         isolate->factory()->NewReferenceError("not_defined",
9375                                               HandleVector(&name, 1));
9376     return MakePair(isolate->Throw(*reference_error), NULL);
9377   } else {
9378     // The property doesn't exist - return undefined.
9379     return MakePair(isolate->heap()->undefined_value(),
9380                     isolate->heap()->undefined_value());
9381   }
9382 }
9383 
9384 
RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlot)9385 RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlot) {
9386   return LoadContextSlotHelper(args, isolate, true);
9387 }
9388 
9389 
RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlotNoReferenceError)9390 RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_LoadContextSlotNoReferenceError) {
9391   return LoadContextSlotHelper(args, isolate, false);
9392 }
9393 
9394 
RUNTIME_FUNCTION(RuntimeHidden_StoreContextSlot)9395 RUNTIME_FUNCTION(RuntimeHidden_StoreContextSlot) {
9396   HandleScope scope(isolate);
9397   ASSERT(args.length() == 4);
9398 
9399   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
9400   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9401   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9402   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
9403 
9404   int index;
9405   PropertyAttributes attributes;
9406   ContextLookupFlags flags = FOLLOW_CHAINS;
9407   BindingFlags binding_flags;
9408   Handle<Object> holder = context->Lookup(name,
9409                                           flags,
9410                                           &index,
9411                                           &attributes,
9412                                           &binding_flags);
9413   if (isolate->has_pending_exception()) return isolate->heap()->exception();
9414 
9415   if (index >= 0) {
9416     // The property was found in a context slot.
9417     Handle<Context> context = Handle<Context>::cast(holder);
9418     if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9419         context->get(index)->IsTheHole()) {
9420       Handle<Object> error =
9421           isolate->factory()->NewReferenceError("not_defined",
9422                                                 HandleVector(&name, 1));
9423       return isolate->Throw(*error);
9424     }
9425     // Ignore if read_only variable.
9426     if ((attributes & READ_ONLY) == 0) {
9427       // Context is a fixed array and set cannot fail.
9428       context->set(index, *value);
9429     } else if (strict_mode == STRICT) {
9430       // Setting read only property in strict mode.
9431       Handle<Object> error =
9432           isolate->factory()->NewTypeError("strict_cannot_assign",
9433                                            HandleVector(&name, 1));
9434       return isolate->Throw(*error);
9435     }
9436     return *value;
9437   }
9438 
9439   // Slow case: The property is not in a context slot.  It is either in a
9440   // context extension object, a property of the subject of a with, or a
9441   // property of the global object.
9442   Handle<JSReceiver> object;
9443 
9444   if (!holder.is_null()) {
9445     // The property exists on the holder.
9446     object = Handle<JSReceiver>::cast(holder);
9447   } else {
9448     // The property was not found.
9449     ASSERT(attributes == ABSENT);
9450 
9451     if (strict_mode == STRICT) {
9452       // Throw in strict mode (assignment to undefined variable).
9453       Handle<Object> error =
9454           isolate->factory()->NewReferenceError(
9455               "not_defined", HandleVector(&name, 1));
9456       return isolate->Throw(*error);
9457     }
9458     // In sloppy mode, the property is added to the global object.
9459     attributes = NONE;
9460     object = Handle<JSReceiver>(isolate->context()->global_object());
9461   }
9462 
9463   // Set the property if it's not read only or doesn't yet exist.
9464   if ((attributes & READ_ONLY) == 0 ||
9465       (JSReceiver::GetOwnPropertyAttributes(object, name) == ABSENT)) {
9466     RETURN_FAILURE_ON_EXCEPTION(
9467         isolate,
9468         JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9469   } else if (strict_mode == STRICT && (attributes & READ_ONLY) != 0) {
9470     // Setting read only property in strict mode.
9471     Handle<Object> error =
9472       isolate->factory()->NewTypeError(
9473           "strict_cannot_assign", HandleVector(&name, 1));
9474     return isolate->Throw(*error);
9475   }
9476   return *value;
9477 }
9478 
9479 
RUNTIME_FUNCTION(RuntimeHidden_Throw)9480 RUNTIME_FUNCTION(RuntimeHidden_Throw) {
9481   HandleScope scope(isolate);
9482   ASSERT(args.length() == 1);
9483 
9484   return isolate->Throw(args[0]);
9485 }
9486 
9487 
RUNTIME_FUNCTION(RuntimeHidden_ReThrow)9488 RUNTIME_FUNCTION(RuntimeHidden_ReThrow) {
9489   HandleScope scope(isolate);
9490   ASSERT(args.length() == 1);
9491 
9492   return isolate->ReThrow(args[0]);
9493 }
9494 
9495 
RUNTIME_FUNCTION(RuntimeHidden_PromoteScheduledException)9496 RUNTIME_FUNCTION(RuntimeHidden_PromoteScheduledException) {
9497   SealHandleScope shs(isolate);
9498   ASSERT(args.length() == 0);
9499   return isolate->PromoteScheduledException();
9500 }
9501 
9502 
RUNTIME_FUNCTION(RuntimeHidden_ThrowReferenceError)9503 RUNTIME_FUNCTION(RuntimeHidden_ThrowReferenceError) {
9504   HandleScope scope(isolate);
9505   ASSERT(args.length() == 1);
9506   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
9507   Handle<Object> reference_error =
9508     isolate->factory()->NewReferenceError("not_defined",
9509                                           HandleVector(&name, 1));
9510   return isolate->Throw(*reference_error);
9511 }
9512 
9513 
RUNTIME_FUNCTION(RuntimeHidden_ThrowNotDateError)9514 RUNTIME_FUNCTION(RuntimeHidden_ThrowNotDateError) {
9515   HandleScope scope(isolate);
9516   ASSERT(args.length() == 0);
9517   return isolate->Throw(*isolate->factory()->NewTypeError(
9518       "not_date_object", HandleVector<Object>(NULL, 0)));
9519 }
9520 
9521 
RUNTIME_FUNCTION(RuntimeHidden_StackGuard)9522 RUNTIME_FUNCTION(RuntimeHidden_StackGuard) {
9523   SealHandleScope shs(isolate);
9524   ASSERT(args.length() == 0);
9525 
9526   // First check if this is a real stack overflow.
9527   StackLimitCheck check(isolate);
9528   if (check.JsHasOverflowed()) {
9529     return isolate->StackOverflow();
9530   }
9531 
9532   return isolate->stack_guard()->HandleInterrupts();
9533 }
9534 
9535 
RUNTIME_FUNCTION(RuntimeHidden_TryInstallOptimizedCode)9536 RUNTIME_FUNCTION(RuntimeHidden_TryInstallOptimizedCode) {
9537   HandleScope scope(isolate);
9538   ASSERT(args.length() == 1);
9539   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9540 
9541   // First check if this is a real stack overflow.
9542   StackLimitCheck check(isolate);
9543   if (check.JsHasOverflowed()) {
9544     SealHandleScope shs(isolate);
9545     return isolate->StackOverflow();
9546   }
9547 
9548   isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
9549   return (function->IsOptimized()) ? function->code()
9550                                    : function->shared()->code();
9551 }
9552 
9553 
RUNTIME_FUNCTION(RuntimeHidden_Interrupt)9554 RUNTIME_FUNCTION(RuntimeHidden_Interrupt) {
9555   SealHandleScope shs(isolate);
9556   ASSERT(args.length() == 0);
9557   return isolate->stack_guard()->HandleInterrupts();
9558 }
9559 
9560 
StackSize(Isolate * isolate)9561 static int StackSize(Isolate* isolate) {
9562   int n = 0;
9563   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9564   return n;
9565 }
9566 
9567 
PrintTransition(Isolate * isolate,Object * result)9568 static void PrintTransition(Isolate* isolate, Object* result) {
9569   // indentation
9570   { const int nmax = 80;
9571     int n = StackSize(isolate);
9572     if (n <= nmax)
9573       PrintF("%4d:%*s", n, n, "");
9574     else
9575       PrintF("%4d:%*s", n, nmax, "...");
9576   }
9577 
9578   if (result == NULL) {
9579     JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9580     PrintF(" {\n");
9581   } else {
9582     // function result
9583     PrintF("} -> ");
9584     result->ShortPrint();
9585     PrintF("\n");
9586   }
9587 }
9588 
9589 
RUNTIME_FUNCTION(Runtime_TraceEnter)9590 RUNTIME_FUNCTION(Runtime_TraceEnter) {
9591   SealHandleScope shs(isolate);
9592   ASSERT(args.length() == 0);
9593   PrintTransition(isolate, NULL);
9594   return isolate->heap()->undefined_value();
9595 }
9596 
9597 
RUNTIME_FUNCTION(Runtime_TraceExit)9598 RUNTIME_FUNCTION(Runtime_TraceExit) {
9599   SealHandleScope shs(isolate);
9600   ASSERT(args.length() == 1);
9601   CONVERT_ARG_CHECKED(Object, obj, 0);
9602   PrintTransition(isolate, obj);
9603   return obj;  // return TOS
9604 }
9605 
9606 
RUNTIME_FUNCTION(Runtime_DebugPrint)9607 RUNTIME_FUNCTION(Runtime_DebugPrint) {
9608   SealHandleScope shs(isolate);
9609   ASSERT(args.length() == 1);
9610 
9611 #ifdef DEBUG
9612   if (args[0]->IsString()) {
9613     // If we have a string, assume it's a code "marker"
9614     // and print some interesting cpu debugging info.
9615     JavaScriptFrameIterator it(isolate);
9616     JavaScriptFrame* frame = it.frame();
9617     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9618            frame->fp(), frame->sp(), frame->caller_sp());
9619   } else {
9620     PrintF("DebugPrint: ");
9621   }
9622   args[0]->Print();
9623   if (args[0]->IsHeapObject()) {
9624     PrintF("\n");
9625     HeapObject::cast(args[0])->map()->Print();
9626   }
9627 #else
9628   // ShortPrint is available in release mode. Print is not.
9629   args[0]->ShortPrint();
9630 #endif
9631   PrintF("\n");
9632   Flush();
9633 
9634   return args[0];  // return TOS
9635 }
9636 
9637 
RUNTIME_FUNCTION(Runtime_DebugTrace)9638 RUNTIME_FUNCTION(Runtime_DebugTrace) {
9639   SealHandleScope shs(isolate);
9640   ASSERT(args.length() == 0);
9641   isolate->PrintStack(stdout);
9642   return isolate->heap()->undefined_value();
9643 }
9644 
9645 
RUNTIME_FUNCTION(Runtime_DateCurrentTime)9646 RUNTIME_FUNCTION(Runtime_DateCurrentTime) {
9647   HandleScope scope(isolate);
9648   ASSERT(args.length() == 0);
9649   if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent());
9650 
9651   // According to ECMA-262, section 15.9.1, page 117, the precision of
9652   // the number in a Date object representing a particular instant in
9653   // time is milliseconds. Therefore, we floor the result of getting
9654   // the OS time.
9655   double millis = std::floor(OS::TimeCurrentMillis());
9656   return *isolate->factory()->NewNumber(millis);
9657 }
9658 
9659 
RUNTIME_FUNCTION(Runtime_DateParseString)9660 RUNTIME_FUNCTION(Runtime_DateParseString) {
9661   HandleScope scope(isolate);
9662   ASSERT(args.length() == 2);
9663   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9664   CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9665 
9666   RUNTIME_ASSERT(output->HasFastElements());
9667   JSObject::EnsureCanContainHeapObjectElements(output);
9668   RUNTIME_ASSERT(output->HasFastObjectElements());
9669   Handle<FixedArray> output_array(FixedArray::cast(output->elements()));
9670   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9671 
9672   str = String::Flatten(str);
9673   DisallowHeapAllocation no_gc;
9674 
9675   bool result;
9676   String::FlatContent str_content = str->GetFlatContent();
9677   if (str_content.IsAscii()) {
9678     result = DateParser::Parse(str_content.ToOneByteVector(),
9679                                *output_array,
9680                                isolate->unicode_cache());
9681   } else {
9682     ASSERT(str_content.IsTwoByte());
9683     result = DateParser::Parse(str_content.ToUC16Vector(),
9684                                *output_array,
9685                                isolate->unicode_cache());
9686   }
9687 
9688   if (result) {
9689     return *output;
9690   } else {
9691     return isolate->heap()->null_value();
9692   }
9693 }
9694 
9695 
RUNTIME_FUNCTION(Runtime_DateLocalTimezone)9696 RUNTIME_FUNCTION(Runtime_DateLocalTimezone) {
9697   HandleScope scope(isolate);
9698   ASSERT(args.length() == 1);
9699 
9700   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9701   RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
9702                  x <= DateCache::kMaxTimeBeforeUTCInMs);
9703   const char* zone =
9704       isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
9705   Handle<String> result = isolate->factory()->NewStringFromUtf8(
9706       CStrVector(zone)).ToHandleChecked();
9707   return *result;
9708 }
9709 
9710 
RUNTIME_FUNCTION(Runtime_DateToUTC)9711 RUNTIME_FUNCTION(Runtime_DateToUTC) {
9712   HandleScope scope(isolate);
9713   ASSERT(args.length() == 1);
9714 
9715   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9716   RUNTIME_ASSERT(x >= -DateCache::kMaxTimeBeforeUTCInMs &&
9717                  x <= DateCache::kMaxTimeBeforeUTCInMs);
9718   int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9719 
9720   return *isolate->factory()->NewNumber(static_cast<double>(time));
9721 }
9722 
9723 
RUNTIME_FUNCTION(Runtime_DateCacheVersion)9724 RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
9725   HandleScope hs(isolate);
9726   ASSERT(args.length() == 0);
9727   if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
9728     Handle<FixedArray> date_cache_version =
9729         isolate->factory()->NewFixedArray(1, TENURED);
9730     date_cache_version->set(0, Smi::FromInt(0));
9731     isolate->eternal_handles()->CreateSingleton(
9732         isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
9733   }
9734   Handle<FixedArray> date_cache_version =
9735       Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
9736           EternalHandles::DATE_CACHE_VERSION));
9737   // Return result as a JS array.
9738   Handle<JSObject> result =
9739       isolate->factory()->NewJSObject(isolate->array_function());
9740   JSArray::SetContent(Handle<JSArray>::cast(result), date_cache_version);
9741   return *result;
9742 }
9743 
9744 
RUNTIME_FUNCTION(Runtime_GlobalReceiver)9745 RUNTIME_FUNCTION(Runtime_GlobalReceiver) {
9746   SealHandleScope shs(isolate);
9747   ASSERT(args.length() == 1);
9748   CONVERT_ARG_CHECKED(Object, global, 0);
9749   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9750   return JSGlobalObject::cast(global)->global_receiver();
9751 }
9752 
9753 
RUNTIME_FUNCTION(Runtime_IsAttachedGlobal)9754 RUNTIME_FUNCTION(Runtime_IsAttachedGlobal) {
9755   SealHandleScope shs(isolate);
9756   ASSERT(args.length() == 1);
9757   CONVERT_ARG_CHECKED(Object, global, 0);
9758   if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
9759   return isolate->heap()->ToBoolean(
9760       !JSGlobalObject::cast(global)->IsDetached());
9761 }
9762 
9763 
RUNTIME_FUNCTION(Runtime_ParseJson)9764 RUNTIME_FUNCTION(Runtime_ParseJson) {
9765   HandleScope scope(isolate);
9766   ASSERT(args.length() == 1);
9767   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9768 
9769   source = String::Flatten(source);
9770   // Optimized fast case where we only have ASCII characters.
9771   Handle<Object> result;
9772   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9773       isolate, result,
9774       source->IsSeqOneByteString() ? JsonParser<true>::Parse(source)
9775                                    : JsonParser<false>::Parse(source));
9776   return *result;
9777 }
9778 
9779 
CodeGenerationFromStringsAllowed(Isolate * isolate,Handle<Context> context)9780 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9781                                       Handle<Context> context) {
9782   ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9783   // Check with callback if set.
9784   AllowCodeGenerationFromStringsCallback callback =
9785       isolate->allow_code_gen_callback();
9786   if (callback == NULL) {
9787     // No callback set and code generation disallowed.
9788     return false;
9789   } else {
9790     // Callback set. Let it decide if code generation is allowed.
9791     VMState<EXTERNAL> state(isolate);
9792     return callback(v8::Utils::ToLocal(context));
9793   }
9794 }
9795 
9796 
9797 // Walk up the stack expecting:
9798 //  - Runtime_CompileString
9799 //  - JSFunction callee (eval, Function constructor, etc)
9800 //  - call() (maybe)
9801 //  - apply() (maybe)
9802 //  - bind() (maybe)
9803 // - JSFunction caller (maybe)
9804 //
9805 // return true if the caller has the same security token as the callee
9806 // or if an exit frame was hit, in which case allow it through, as it could
9807 // have come through the api.
TokensMatchForCompileString(Isolate * isolate)9808 static bool TokensMatchForCompileString(Isolate* isolate) {
9809   MaybeHandle<JSFunction> callee;
9810   bool exit_handled = true;
9811   bool tokens_match = true;
9812   bool done = false;
9813   for (StackFrameIterator it(isolate); !it.done() && !done; it.Advance()) {
9814     StackFrame* raw_frame = it.frame();
9815     if (!raw_frame->is_java_script()) {
9816       if (raw_frame->is_exit()) exit_handled = false;
9817       continue;
9818     }
9819     JavaScriptFrame* outer_frame = JavaScriptFrame::cast(raw_frame);
9820     List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
9821     outer_frame->Summarize(&frames);
9822     for (int i = frames.length() - 1; i >= 0 && !done; --i) {
9823       FrameSummary& frame = frames[i];
9824       Handle<JSFunction> fun = frame.function();
9825       // Capture the callee function.
9826       if (callee.is_null()) {
9827         callee = fun;
9828         exit_handled = true;
9829         continue;
9830       }
9831       // Exit condition.
9832       Handle<Context> context(callee.ToHandleChecked()->context());
9833       if (!fun->context()->HasSameSecurityTokenAs(*context)) {
9834         tokens_match = false;
9835         done = true;
9836         continue;
9837       }
9838       // Skip bound functions in correct origin.
9839       if (fun->shared()->bound()) {
9840         exit_handled = true;
9841         continue;
9842       }
9843       done = true;
9844     }
9845   }
9846   return !exit_handled || tokens_match;
9847 }
9848 
9849 
RUNTIME_FUNCTION(Runtime_CompileString)9850 RUNTIME_FUNCTION(Runtime_CompileString) {
9851   HandleScope scope(isolate);
9852   ASSERT(args.length() == 2);
9853   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9854   CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9855 
9856   // Extract native context.
9857   Handle<Context> context(isolate->context()->native_context());
9858 
9859   // Filter cross security context calls.
9860   if (!TokensMatchForCompileString(isolate)) {
9861     return isolate->heap()->undefined_value();
9862   }
9863 
9864   // Check if native context allows code generation from
9865   // strings. Throw an exception if it doesn't.
9866   if (context->allow_code_gen_from_strings()->IsFalse() &&
9867       !CodeGenerationFromStringsAllowed(isolate, context)) {
9868     Handle<Object> error_message =
9869         context->ErrorMessageForCodeGenerationFromStrings();
9870     return isolate->Throw(*isolate->factory()->NewEvalError(
9871         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9872   }
9873 
9874   // Compile source string in the native context.
9875   ParseRestriction restriction = function_literal_only
9876       ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
9877   Handle<JSFunction> fun;
9878   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
9879       isolate, fun,
9880       Compiler::GetFunctionFromEval(
9881           source, context, SLOPPY, restriction, RelocInfo::kNoPosition));
9882   return *fun;
9883 }
9884 
9885 
CompileGlobalEval(Isolate * isolate,Handle<String> source,Handle<Object> receiver,StrictMode strict_mode,int scope_position)9886 static ObjectPair CompileGlobalEval(Isolate* isolate,
9887                                     Handle<String> source,
9888                                     Handle<Object> receiver,
9889                                     StrictMode strict_mode,
9890                                     int scope_position) {
9891   Handle<Context> context = Handle<Context>(isolate->context());
9892   Handle<Context> native_context = Handle<Context>(context->native_context());
9893 
9894   // Check if native context allows code generation from
9895   // strings. Throw an exception if it doesn't.
9896   if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9897       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9898     Handle<Object> error_message =
9899         native_context->ErrorMessageForCodeGenerationFromStrings();
9900     isolate->Throw(*isolate->factory()->NewEvalError(
9901         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9902     return MakePair(isolate->heap()->exception(), NULL);
9903   }
9904 
9905   // Deal with a normal eval call with a string argument. Compile it
9906   // and return the compiled function bound in the local context.
9907   static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
9908   Handle<JSFunction> compiled;
9909   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
9910       isolate, compiled,
9911       Compiler::GetFunctionFromEval(
9912           source, context, strict_mode, restriction, scope_position),
9913       MakePair(isolate->heap()->exception(), NULL));
9914   return MakePair(*compiled, *receiver);
9915 }
9916 
9917 
RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_ResolvePossiblyDirectEval)9918 RUNTIME_FUNCTION_RETURN_PAIR(RuntimeHidden_ResolvePossiblyDirectEval) {
9919   HandleScope scope(isolate);
9920   ASSERT(args.length() == 5);
9921 
9922   Handle<Object> callee = args.at<Object>(0);
9923 
9924   // If "eval" didn't refer to the original GlobalEval, it's not a
9925   // direct call to eval.
9926   // (And even if it is, but the first argument isn't a string, just let
9927   // execution default to an indirect call to eval, which will also return
9928   // the first argument without doing anything).
9929   if (*callee != isolate->native_context()->global_eval_fun() ||
9930       !args[1]->IsString()) {
9931     return MakePair(*callee, isolate->heap()->undefined_value());
9932   }
9933 
9934   ASSERT(args[3]->IsSmi());
9935   ASSERT(args.smi_at(3) == SLOPPY || args.smi_at(3) == STRICT);
9936   StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(3));
9937   ASSERT(args[4]->IsSmi());
9938   return CompileGlobalEval(isolate,
9939                            args.at<String>(1),
9940                            args.at<Object>(2),
9941                            strict_mode,
9942                            args.smi_at(4));
9943 }
9944 
9945 
RUNTIME_FUNCTION(RuntimeHidden_AllocateInNewSpace)9946 RUNTIME_FUNCTION(RuntimeHidden_AllocateInNewSpace) {
9947   HandleScope scope(isolate);
9948   ASSERT(args.length() == 1);
9949   CONVERT_SMI_ARG_CHECKED(size, 0);
9950   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9951   RUNTIME_ASSERT(size > 0);
9952   RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
9953   return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE);
9954 }
9955 
9956 
RUNTIME_FUNCTION(RuntimeHidden_AllocateInTargetSpace)9957 RUNTIME_FUNCTION(RuntimeHidden_AllocateInTargetSpace) {
9958   HandleScope scope(isolate);
9959   ASSERT(args.length() == 2);
9960   CONVERT_SMI_ARG_CHECKED(size, 0);
9961   CONVERT_SMI_ARG_CHECKED(flags, 1);
9962   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9963   RUNTIME_ASSERT(size > 0);
9964   RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
9965   bool double_align = AllocateDoubleAlignFlag::decode(flags);
9966   AllocationSpace space = AllocateTargetSpace::decode(flags);
9967   return *isolate->factory()->NewFillerObject(size, double_align, space);
9968 }
9969 
9970 
9971 // Push an object unto an array of objects if it is not already in the
9972 // array.  Returns true if the element was pushed on the stack and
9973 // false otherwise.
RUNTIME_FUNCTION(Runtime_PushIfAbsent)9974 RUNTIME_FUNCTION(Runtime_PushIfAbsent) {
9975   HandleScope scope(isolate);
9976   ASSERT(args.length() == 2);
9977   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
9978   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, element, 1);
9979   RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9980   int length = Smi::cast(array->length())->value();
9981   FixedArray* elements = FixedArray::cast(array->elements());
9982   for (int i = 0; i < length; i++) {
9983     if (elements->get(i) == *element) return isolate->heap()->false_value();
9984   }
9985 
9986   // Strict not needed. Used for cycle detection in Array join implementation.
9987   RETURN_FAILURE_ON_EXCEPTION(
9988       isolate,
9989       JSObject::SetFastElement(array, length, element, SLOPPY, true));
9990   return isolate->heap()->true_value();
9991 }
9992 
9993 
9994 /**
9995  * A simple visitor visits every element of Array's.
9996  * The backend storage can be a fixed array for fast elements case,
9997  * or a dictionary for sparse array. Since Dictionary is a subtype
9998  * of FixedArray, the class can be used by both fast and slow cases.
9999  * The second parameter of the constructor, fast_elements, specifies
10000  * whether the storage is a FixedArray or Dictionary.
10001  *
10002  * An index limit is used to deal with the situation that a result array
10003  * length overflows 32-bit non-negative integer.
10004  */
10005 class ArrayConcatVisitor {
10006  public:
ArrayConcatVisitor(Isolate * isolate,Handle<FixedArray> storage,bool fast_elements)10007   ArrayConcatVisitor(Isolate* isolate,
10008                      Handle<FixedArray> storage,
10009                      bool fast_elements) :
10010       isolate_(isolate),
10011       storage_(Handle<FixedArray>::cast(
10012           isolate->global_handles()->Create(*storage))),
10013       index_offset_(0u),
10014       fast_elements_(fast_elements),
10015       exceeds_array_limit_(false) { }
10016 
~ArrayConcatVisitor()10017   ~ArrayConcatVisitor() {
10018     clear_storage();
10019   }
10020 
visit(uint32_t i,Handle<Object> elm)10021   void visit(uint32_t i, Handle<Object> elm) {
10022     if (i > JSObject::kMaxElementCount - index_offset_) {
10023       exceeds_array_limit_ = true;
10024       return;
10025     }
10026     uint32_t index = index_offset_ + i;
10027 
10028     if (fast_elements_) {
10029       if (index < static_cast<uint32_t>(storage_->length())) {
10030         storage_->set(index, *elm);
10031         return;
10032       }
10033       // Our initial estimate of length was foiled, possibly by
10034       // getters on the arrays increasing the length of later arrays
10035       // during iteration.
10036       // This shouldn't happen in anything but pathological cases.
10037       SetDictionaryMode();
10038       // Fall-through to dictionary mode.
10039     }
10040     ASSERT(!fast_elements_);
10041     Handle<SeededNumberDictionary> dict(
10042         SeededNumberDictionary::cast(*storage_));
10043     Handle<SeededNumberDictionary> result =
10044         SeededNumberDictionary::AtNumberPut(dict, index, elm);
10045     if (!result.is_identical_to(dict)) {
10046       // Dictionary needed to grow.
10047       clear_storage();
10048       set_storage(*result);
10049     }
10050   }
10051 
increase_index_offset(uint32_t delta)10052   void increase_index_offset(uint32_t delta) {
10053     if (JSObject::kMaxElementCount - index_offset_ < delta) {
10054       index_offset_ = JSObject::kMaxElementCount;
10055     } else {
10056       index_offset_ += delta;
10057     }
10058     // If the initial length estimate was off (see special case in visit()),
10059     // but the array blowing the limit didn't contain elements beyond the
10060     // provided-for index range, go to dictionary mode now.
10061     if (fast_elements_ &&
10062         index_offset_ >
10063             static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
10064       SetDictionaryMode();
10065     }
10066   }
10067 
exceeds_array_limit()10068   bool exceeds_array_limit() {
10069     return exceeds_array_limit_;
10070   }
10071 
ToArray()10072   Handle<JSArray> ToArray() {
10073     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
10074     Handle<Object> length =
10075         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
10076     Handle<Map> map = JSObject::GetElementsTransitionMap(
10077         array,
10078         fast_elements_ ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
10079     array->set_map(*map);
10080     array->set_length(*length);
10081     array->set_elements(*storage_);
10082     return array;
10083   }
10084 
10085  private:
10086   // Convert storage to dictionary mode.
SetDictionaryMode()10087   void SetDictionaryMode() {
10088     ASSERT(fast_elements_);
10089     Handle<FixedArray> current_storage(*storage_);
10090     Handle<SeededNumberDictionary> slow_storage(
10091         SeededNumberDictionary::New(isolate_, current_storage->length()));
10092     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
10093     for (uint32_t i = 0; i < current_length; i++) {
10094       HandleScope loop_scope(isolate_);
10095       Handle<Object> element(current_storage->get(i), isolate_);
10096       if (!element->IsTheHole()) {
10097         Handle<SeededNumberDictionary> new_storage =
10098             SeededNumberDictionary::AtNumberPut(slow_storage, i, element);
10099         if (!new_storage.is_identical_to(slow_storage)) {
10100           slow_storage = loop_scope.CloseAndEscape(new_storage);
10101         }
10102       }
10103     }
10104     clear_storage();
10105     set_storage(*slow_storage);
10106     fast_elements_ = false;
10107   }
10108 
clear_storage()10109   inline void clear_storage() {
10110     GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
10111   }
10112 
set_storage(FixedArray * storage)10113   inline void set_storage(FixedArray* storage) {
10114     storage_ = Handle<FixedArray>::cast(
10115         isolate_->global_handles()->Create(storage));
10116   }
10117 
10118   Isolate* isolate_;
10119   Handle<FixedArray> storage_;  // Always a global handle.
10120   // Index after last seen index. Always less than or equal to
10121   // JSObject::kMaxElementCount.
10122   uint32_t index_offset_;
10123   bool fast_elements_ : 1;
10124   bool exceeds_array_limit_ : 1;
10125 };
10126 
10127 
EstimateElementCount(Handle<JSArray> array)10128 static uint32_t EstimateElementCount(Handle<JSArray> array) {
10129   uint32_t length = static_cast<uint32_t>(array->length()->Number());
10130   int element_count = 0;
10131   switch (array->GetElementsKind()) {
10132     case FAST_SMI_ELEMENTS:
10133     case FAST_HOLEY_SMI_ELEMENTS:
10134     case FAST_ELEMENTS:
10135     case FAST_HOLEY_ELEMENTS: {
10136       // Fast elements can't have lengths that are not representable by
10137       // a 32-bit signed integer.
10138       ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
10139       int fast_length = static_cast<int>(length);
10140       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
10141       for (int i = 0; i < fast_length; i++) {
10142         if (!elements->get(i)->IsTheHole()) element_count++;
10143       }
10144       break;
10145     }
10146     case FAST_DOUBLE_ELEMENTS:
10147     case FAST_HOLEY_DOUBLE_ELEMENTS: {
10148       // Fast elements can't have lengths that are not representable by
10149       // a 32-bit signed integer.
10150       ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
10151       int fast_length = static_cast<int>(length);
10152       if (array->elements()->IsFixedArray()) {
10153         ASSERT(FixedArray::cast(array->elements())->length() == 0);
10154         break;
10155       }
10156       Handle<FixedDoubleArray> elements(
10157           FixedDoubleArray::cast(array->elements()));
10158       for (int i = 0; i < fast_length; i++) {
10159         if (!elements->is_the_hole(i)) element_count++;
10160       }
10161       break;
10162     }
10163     case DICTIONARY_ELEMENTS: {
10164       Handle<SeededNumberDictionary> dictionary(
10165           SeededNumberDictionary::cast(array->elements()));
10166       int capacity = dictionary->Capacity();
10167       for (int i = 0; i < capacity; i++) {
10168         Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
10169         if (dictionary->IsKey(*key)) {
10170           element_count++;
10171         }
10172       }
10173       break;
10174     }
10175     case SLOPPY_ARGUMENTS_ELEMENTS:
10176 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
10177     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
10178     case TYPE##_ELEMENTS:                                                    \
10179 
10180     TYPED_ARRAYS(TYPED_ARRAY_CASE)
10181 #undef TYPED_ARRAY_CASE
10182       // External arrays are always dense.
10183       return length;
10184   }
10185   // As an estimate, we assume that the prototype doesn't contain any
10186   // inherited elements.
10187   return element_count;
10188 }
10189 
10190 
10191 
10192 template<class ExternalArrayClass, class ElementType>
IterateExternalArrayElements(Isolate * isolate,Handle<JSObject> receiver,bool elements_are_ints,bool elements_are_guaranteed_smis,ArrayConcatVisitor * visitor)10193 static void IterateExternalArrayElements(Isolate* isolate,
10194                                          Handle<JSObject> receiver,
10195                                          bool elements_are_ints,
10196                                          bool elements_are_guaranteed_smis,
10197                                          ArrayConcatVisitor* visitor) {
10198   Handle<ExternalArrayClass> array(
10199       ExternalArrayClass::cast(receiver->elements()));
10200   uint32_t len = static_cast<uint32_t>(array->length());
10201 
10202   ASSERT(visitor != NULL);
10203   if (elements_are_ints) {
10204     if (elements_are_guaranteed_smis) {
10205       for (uint32_t j = 0; j < len; j++) {
10206         HandleScope loop_scope(isolate);
10207         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
10208                       isolate);
10209         visitor->visit(j, e);
10210       }
10211     } else {
10212       for (uint32_t j = 0; j < len; j++) {
10213         HandleScope loop_scope(isolate);
10214         int64_t val = static_cast<int64_t>(array->get_scalar(j));
10215         if (Smi::IsValid(static_cast<intptr_t>(val))) {
10216           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
10217           visitor->visit(j, e);
10218         } else {
10219           Handle<Object> e =
10220               isolate->factory()->NewNumber(static_cast<ElementType>(val));
10221           visitor->visit(j, e);
10222         }
10223       }
10224     }
10225   } else {
10226     for (uint32_t j = 0; j < len; j++) {
10227       HandleScope loop_scope(isolate);
10228       Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
10229       visitor->visit(j, e);
10230     }
10231   }
10232 }
10233 
10234 
10235 // Used for sorting indices in a List<uint32_t>.
compareUInt32(const uint32_t * ap,const uint32_t * bp)10236 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
10237   uint32_t a = *ap;
10238   uint32_t b = *bp;
10239   return (a == b) ? 0 : (a < b) ? -1 : 1;
10240 }
10241 
10242 
CollectElementIndices(Handle<JSObject> object,uint32_t range,List<uint32_t> * indices)10243 static void CollectElementIndices(Handle<JSObject> object,
10244                                   uint32_t range,
10245                                   List<uint32_t>* indices) {
10246   Isolate* isolate = object->GetIsolate();
10247   ElementsKind kind = object->GetElementsKind();
10248   switch (kind) {
10249     case FAST_SMI_ELEMENTS:
10250     case FAST_ELEMENTS:
10251     case FAST_HOLEY_SMI_ELEMENTS:
10252     case FAST_HOLEY_ELEMENTS: {
10253       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
10254       uint32_t length = static_cast<uint32_t>(elements->length());
10255       if (range < length) length = range;
10256       for (uint32_t i = 0; i < length; i++) {
10257         if (!elements->get(i)->IsTheHole()) {
10258           indices->Add(i);
10259         }
10260       }
10261       break;
10262     }
10263     case FAST_HOLEY_DOUBLE_ELEMENTS:
10264     case FAST_DOUBLE_ELEMENTS: {
10265       // TODO(1810): Decide if it's worthwhile to implement this.
10266       UNREACHABLE();
10267       break;
10268     }
10269     case DICTIONARY_ELEMENTS: {
10270       Handle<SeededNumberDictionary> dict(
10271           SeededNumberDictionary::cast(object->elements()));
10272       uint32_t capacity = dict->Capacity();
10273       for (uint32_t j = 0; j < capacity; j++) {
10274         HandleScope loop_scope(isolate);
10275         Handle<Object> k(dict->KeyAt(j), isolate);
10276         if (dict->IsKey(*k)) {
10277           ASSERT(k->IsNumber());
10278           uint32_t index = static_cast<uint32_t>(k->Number());
10279           if (index < range) {
10280             indices->Add(index);
10281           }
10282         }
10283       }
10284       break;
10285     }
10286     default: {
10287       int dense_elements_length;
10288       switch (kind) {
10289 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
10290         case EXTERNAL_##TYPE##_ELEMENTS: {                                     \
10291           dense_elements_length =                                              \
10292               External##Type##Array::cast(object->elements())->length();       \
10293           break;                                                               \
10294         }
10295 
10296         TYPED_ARRAYS(TYPED_ARRAY_CASE)
10297 #undef TYPED_ARRAY_CASE
10298 
10299         default:
10300           UNREACHABLE();
10301           dense_elements_length = 0;
10302           break;
10303       }
10304       uint32_t length = static_cast<uint32_t>(dense_elements_length);
10305       if (range <= length) {
10306         length = range;
10307         // We will add all indices, so we might as well clear it first
10308         // and avoid duplicates.
10309         indices->Clear();
10310       }
10311       for (uint32_t i = 0; i < length; i++) {
10312         indices->Add(i);
10313       }
10314       if (length == range) return;  // All indices accounted for already.
10315       break;
10316     }
10317   }
10318 
10319   Handle<Object> prototype(object->GetPrototype(), isolate);
10320   if (prototype->IsJSObject()) {
10321     // The prototype will usually have no inherited element indices,
10322     // but we have to check.
10323     CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
10324   }
10325 }
10326 
10327 
10328 /**
10329  * A helper function that visits elements of a JSArray in numerical
10330  * order.
10331  *
10332  * The visitor argument called for each existing element in the array
10333  * with the element index and the element's value.
10334  * Afterwards it increments the base-index of the visitor by the array
10335  * length.
10336  * Returns false if any access threw an exception, otherwise true.
10337  */
IterateElements(Isolate * isolate,Handle<JSArray> receiver,ArrayConcatVisitor * visitor)10338 static bool IterateElements(Isolate* isolate,
10339                             Handle<JSArray> receiver,
10340                             ArrayConcatVisitor* visitor) {
10341   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10342   switch (receiver->GetElementsKind()) {
10343     case FAST_SMI_ELEMENTS:
10344     case FAST_ELEMENTS:
10345     case FAST_HOLEY_SMI_ELEMENTS:
10346     case FAST_HOLEY_ELEMENTS: {
10347       // Run through the elements FixedArray and use HasElement and GetElement
10348       // to check the prototype for missing elements.
10349       Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10350       int fast_length = static_cast<int>(length);
10351       ASSERT(fast_length <= elements->length());
10352       for (int j = 0; j < fast_length; j++) {
10353         HandleScope loop_scope(isolate);
10354         Handle<Object> element_value(elements->get(j), isolate);
10355         if (!element_value->IsTheHole()) {
10356           visitor->visit(j, element_value);
10357         } else if (JSReceiver::HasElement(receiver, j)) {
10358           // Call GetElement on receiver, not its prototype, or getters won't
10359           // have the correct receiver.
10360           ASSIGN_RETURN_ON_EXCEPTION_VALUE(
10361               isolate, element_value,
10362               Object::GetElement(isolate, receiver, j),
10363               false);
10364           visitor->visit(j, element_value);
10365         }
10366       }
10367       break;
10368     }
10369     case FAST_HOLEY_DOUBLE_ELEMENTS:
10370     case FAST_DOUBLE_ELEMENTS: {
10371       // Empty array is FixedArray but not FixedDoubleArray.
10372       if (length == 0) break;
10373       // Run through the elements FixedArray and use HasElement and GetElement
10374       // to check the prototype for missing elements.
10375       if (receiver->elements()->IsFixedArray()) {
10376         ASSERT(receiver->elements()->length() == 0);
10377         break;
10378       }
10379       Handle<FixedDoubleArray> elements(
10380           FixedDoubleArray::cast(receiver->elements()));
10381       int fast_length = static_cast<int>(length);
10382       ASSERT(fast_length <= elements->length());
10383       for (int j = 0; j < fast_length; j++) {
10384         HandleScope loop_scope(isolate);
10385         if (!elements->is_the_hole(j)) {
10386           double double_value = elements->get_scalar(j);
10387           Handle<Object> element_value =
10388               isolate->factory()->NewNumber(double_value);
10389           visitor->visit(j, element_value);
10390         } else if (JSReceiver::HasElement(receiver, j)) {
10391           // Call GetElement on receiver, not its prototype, or getters won't
10392           // have the correct receiver.
10393           Handle<Object> element_value;
10394           ASSIGN_RETURN_ON_EXCEPTION_VALUE(
10395               isolate, element_value,
10396               Object::GetElement(isolate, receiver, j),
10397               false);
10398           visitor->visit(j, element_value);
10399         }
10400       }
10401       break;
10402     }
10403     case DICTIONARY_ELEMENTS: {
10404       Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10405       List<uint32_t> indices(dict->Capacity() / 2);
10406       // Collect all indices in the object and the prototypes less
10407       // than length. This might introduce duplicates in the indices list.
10408       CollectElementIndices(receiver, length, &indices);
10409       indices.Sort(&compareUInt32);
10410       int j = 0;
10411       int n = indices.length();
10412       while (j < n) {
10413         HandleScope loop_scope(isolate);
10414         uint32_t index = indices[j];
10415         Handle<Object> element;
10416         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
10417             isolate, element,
10418             Object::GetElement(isolate, receiver, index),
10419             false);
10420         visitor->visit(index, element);
10421         // Skip to next different index (i.e., omit duplicates).
10422         do {
10423           j++;
10424         } while (j < n && indices[j] == index);
10425       }
10426       break;
10427     }
10428     case EXTERNAL_UINT8_CLAMPED_ELEMENTS: {
10429       Handle<ExternalUint8ClampedArray> pixels(ExternalUint8ClampedArray::cast(
10430           receiver->elements()));
10431       for (uint32_t j = 0; j < length; j++) {
10432         Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10433         visitor->visit(j, e);
10434       }
10435       break;
10436     }
10437     case EXTERNAL_INT8_ELEMENTS: {
10438       IterateExternalArrayElements<ExternalInt8Array, int8_t>(
10439           isolate, receiver, true, true, visitor);
10440       break;
10441     }
10442     case EXTERNAL_UINT8_ELEMENTS: {
10443       IterateExternalArrayElements<ExternalUint8Array, uint8_t>(
10444           isolate, receiver, true, true, visitor);
10445       break;
10446     }
10447     case EXTERNAL_INT16_ELEMENTS: {
10448       IterateExternalArrayElements<ExternalInt16Array, int16_t>(
10449           isolate, receiver, true, true, visitor);
10450       break;
10451     }
10452     case EXTERNAL_UINT16_ELEMENTS: {
10453       IterateExternalArrayElements<ExternalUint16Array, uint16_t>(
10454           isolate, receiver, true, true, visitor);
10455       break;
10456     }
10457     case EXTERNAL_INT32_ELEMENTS: {
10458       IterateExternalArrayElements<ExternalInt32Array, int32_t>(
10459           isolate, receiver, true, false, visitor);
10460       break;
10461     }
10462     case EXTERNAL_UINT32_ELEMENTS: {
10463       IterateExternalArrayElements<ExternalUint32Array, uint32_t>(
10464           isolate, receiver, true, false, visitor);
10465       break;
10466     }
10467     case EXTERNAL_FLOAT32_ELEMENTS: {
10468       IterateExternalArrayElements<ExternalFloat32Array, float>(
10469           isolate, receiver, false, false, visitor);
10470       break;
10471     }
10472     case EXTERNAL_FLOAT64_ELEMENTS: {
10473       IterateExternalArrayElements<ExternalFloat64Array, double>(
10474           isolate, receiver, false, false, visitor);
10475       break;
10476     }
10477     default:
10478       UNREACHABLE();
10479       break;
10480   }
10481   visitor->increase_index_offset(length);
10482   return true;
10483 }
10484 
10485 
10486 /**
10487  * Array::concat implementation.
10488  * See ECMAScript 262, 15.4.4.4.
10489  * TODO(581): Fix non-compliance for very large concatenations and update to
10490  * following the ECMAScript 5 specification.
10491  */
RUNTIME_FUNCTION(Runtime_ArrayConcat)10492 RUNTIME_FUNCTION(Runtime_ArrayConcat) {
10493   HandleScope handle_scope(isolate);
10494   ASSERT(args.length() == 1);
10495 
10496   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10497   int argument_count = static_cast<int>(arguments->length()->Number());
10498   RUNTIME_ASSERT(arguments->HasFastObjectElements());
10499   Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10500 
10501   // Pass 1: estimate the length and number of elements of the result.
10502   // The actual length can be larger if any of the arguments have getters
10503   // that mutate other arguments (but will otherwise be precise).
10504   // The number of elements is precise if there are no inherited elements.
10505 
10506   ElementsKind kind = FAST_SMI_ELEMENTS;
10507 
10508   uint32_t estimate_result_length = 0;
10509   uint32_t estimate_nof_elements = 0;
10510   for (int i = 0; i < argument_count; i++) {
10511     HandleScope loop_scope(isolate);
10512     Handle<Object> obj(elements->get(i), isolate);
10513     uint32_t length_estimate;
10514     uint32_t element_estimate;
10515     if (obj->IsJSArray()) {
10516       Handle<JSArray> array(Handle<JSArray>::cast(obj));
10517       length_estimate = static_cast<uint32_t>(array->length()->Number());
10518       if (length_estimate != 0) {
10519         ElementsKind array_kind =
10520             GetPackedElementsKind(array->map()->elements_kind());
10521         if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10522           kind = array_kind;
10523         }
10524       }
10525       element_estimate = EstimateElementCount(array);
10526     } else {
10527       if (obj->IsHeapObject()) {
10528         if (obj->IsNumber()) {
10529           if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
10530             kind = FAST_DOUBLE_ELEMENTS;
10531           }
10532         } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
10533           kind = FAST_ELEMENTS;
10534         }
10535       }
10536       length_estimate = 1;
10537       element_estimate = 1;
10538     }
10539     // Avoid overflows by capping at kMaxElementCount.
10540     if (JSObject::kMaxElementCount - estimate_result_length <
10541         length_estimate) {
10542       estimate_result_length = JSObject::kMaxElementCount;
10543     } else {
10544       estimate_result_length += length_estimate;
10545     }
10546     if (JSObject::kMaxElementCount - estimate_nof_elements <
10547         element_estimate) {
10548       estimate_nof_elements = JSObject::kMaxElementCount;
10549     } else {
10550       estimate_nof_elements += element_estimate;
10551     }
10552   }
10553 
10554   // If estimated number of elements is more than half of length, a
10555   // fixed array (fast case) is more time and space-efficient than a
10556   // dictionary.
10557   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10558 
10559   if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
10560     Handle<FixedArrayBase> storage =
10561         isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10562     int j = 0;
10563     if (estimate_result_length > 0) {
10564       Handle<FixedDoubleArray> double_storage =
10565           Handle<FixedDoubleArray>::cast(storage);
10566       bool failure = false;
10567       for (int i = 0; i < argument_count; i++) {
10568         Handle<Object> obj(elements->get(i), isolate);
10569         if (obj->IsSmi()) {
10570           double_storage->set(j, Smi::cast(*obj)->value());
10571           j++;
10572         } else if (obj->IsNumber()) {
10573           double_storage->set(j, obj->Number());
10574           j++;
10575         } else {
10576           JSArray* array = JSArray::cast(*obj);
10577           uint32_t length = static_cast<uint32_t>(array->length()->Number());
10578           switch (array->map()->elements_kind()) {
10579             case FAST_HOLEY_DOUBLE_ELEMENTS:
10580             case FAST_DOUBLE_ELEMENTS: {
10581               // Empty array is FixedArray but not FixedDoubleArray.
10582               if (length == 0) break;
10583               FixedDoubleArray* elements =
10584                   FixedDoubleArray::cast(array->elements());
10585               for (uint32_t i = 0; i < length; i++) {
10586                 if (elements->is_the_hole(i)) {
10587                   failure = true;
10588                   break;
10589                 }
10590                 double double_value = elements->get_scalar(i);
10591                 double_storage->set(j, double_value);
10592                 j++;
10593               }
10594               break;
10595             }
10596             case FAST_HOLEY_SMI_ELEMENTS:
10597             case FAST_SMI_ELEMENTS: {
10598               FixedArray* elements(
10599                   FixedArray::cast(array->elements()));
10600               for (uint32_t i = 0; i < length; i++) {
10601                 Object* element = elements->get(i);
10602                 if (element->IsTheHole()) {
10603                   failure = true;
10604                   break;
10605                 }
10606                 int32_t int_value = Smi::cast(element)->value();
10607                 double_storage->set(j, int_value);
10608                 j++;
10609               }
10610               break;
10611             }
10612             case FAST_HOLEY_ELEMENTS:
10613               ASSERT_EQ(0, length);
10614               break;
10615             default:
10616               UNREACHABLE();
10617           }
10618         }
10619         if (failure) break;
10620       }
10621     }
10622     Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10623     Smi* length = Smi::FromInt(j);
10624     Handle<Map> map;
10625     map = JSObject::GetElementsTransitionMap(array, kind);
10626     array->set_map(*map);
10627     array->set_length(length);
10628     array->set_elements(*storage);
10629     return *array;
10630   }
10631 
10632   Handle<FixedArray> storage;
10633   if (fast_case) {
10634     // The backing storage array must have non-existing elements to preserve
10635     // holes across concat operations.
10636     storage = isolate->factory()->NewFixedArrayWithHoles(
10637         estimate_result_length);
10638   } else {
10639     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10640     uint32_t at_least_space_for = estimate_nof_elements +
10641                                   (estimate_nof_elements >> 2);
10642     storage = Handle<FixedArray>::cast(
10643         SeededNumberDictionary::New(isolate, at_least_space_for));
10644   }
10645 
10646   ArrayConcatVisitor visitor(isolate, storage, fast_case);
10647 
10648   for (int i = 0; i < argument_count; i++) {
10649     Handle<Object> obj(elements->get(i), isolate);
10650     if (obj->IsJSArray()) {
10651       Handle<JSArray> array = Handle<JSArray>::cast(obj);
10652       if (!IterateElements(isolate, array, &visitor)) {
10653         return isolate->heap()->exception();
10654       }
10655     } else {
10656       visitor.visit(0, obj);
10657       visitor.increase_index_offset(1);
10658     }
10659   }
10660 
10661   if (visitor.exceeds_array_limit()) {
10662     return isolate->Throw(
10663         *isolate->factory()->NewRangeError("invalid_array_length",
10664                                            HandleVector<Object>(NULL, 0)));
10665   }
10666   return *visitor.ToArray();
10667 }
10668 
10669 
10670 // This will not allocate (flatten the string), but it may run
10671 // very slowly for very deeply nested ConsStrings.  For debugging use only.
RUNTIME_FUNCTION(Runtime_GlobalPrint)10672 RUNTIME_FUNCTION(Runtime_GlobalPrint) {
10673   SealHandleScope shs(isolate);
10674   ASSERT(args.length() == 1);
10675 
10676   CONVERT_ARG_CHECKED(String, string, 0);
10677   ConsStringIteratorOp op;
10678   StringCharacterStream stream(string, &op);
10679   while (stream.HasMore()) {
10680     uint16_t character = stream.GetNext();
10681     PrintF("%c", character);
10682   }
10683   return string;
10684 }
10685 
10686 
10687 // Moves all own elements of an object, that are below a limit, to positions
10688 // starting at zero. All undefined values are placed after non-undefined values,
10689 // and are followed by non-existing element. Does not change the length
10690 // property.
10691 // Returns the number of non-undefined elements collected.
10692 // Returns -1 if hole removal is not supported by this method.
RUNTIME_FUNCTION(Runtime_RemoveArrayHoles)10693 RUNTIME_FUNCTION(Runtime_RemoveArrayHoles) {
10694   HandleScope scope(isolate);
10695   ASSERT(args.length() == 2);
10696   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
10697   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10698   return *JSObject::PrepareElementsForSort(object, limit);
10699 }
10700 
10701 
10702 // Move contents of argument 0 (an array) to argument 1 (an array)
RUNTIME_FUNCTION(Runtime_MoveArrayContents)10703 RUNTIME_FUNCTION(Runtime_MoveArrayContents) {
10704   HandleScope scope(isolate);
10705   ASSERT(args.length() == 2);
10706   CONVERT_ARG_HANDLE_CHECKED(JSArray, from, 0);
10707   CONVERT_ARG_HANDLE_CHECKED(JSArray, to, 1);
10708   JSObject::ValidateElements(from);
10709   JSObject::ValidateElements(to);
10710 
10711   Handle<FixedArrayBase> new_elements(from->elements());
10712   ElementsKind from_kind = from->GetElementsKind();
10713   Handle<Map> new_map = JSObject::GetElementsTransitionMap(to, from_kind);
10714   JSObject::SetMapAndElements(to, new_map, new_elements);
10715   to->set_length(from->length());
10716 
10717   JSObject::ResetElements(from);
10718   from->set_length(Smi::FromInt(0));
10719 
10720   JSObject::ValidateElements(to);
10721   return *to;
10722 }
10723 
10724 
10725 // How many elements does this object/array have?
RUNTIME_FUNCTION(Runtime_EstimateNumberOfElements)10726 RUNTIME_FUNCTION(Runtime_EstimateNumberOfElements) {
10727   SealHandleScope shs(isolate);
10728   ASSERT(args.length() == 1);
10729   CONVERT_ARG_CHECKED(JSArray, object, 0);
10730   HeapObject* elements = object->elements();
10731   if (elements->IsDictionary()) {
10732     int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10733     return Smi::FromInt(result);
10734   } else {
10735     return object->length();
10736   }
10737 }
10738 
10739 
10740 // Returns an array that tells you where in the [0, length) interval an array
10741 // might have elements.  Can either return an array of keys (positive integers
10742 // or undefined) or a number representing the positive length of an interval
10743 // starting at index 0.
10744 // Intervals can span over some keys that are not in the object.
RUNTIME_FUNCTION(Runtime_GetArrayKeys)10745 RUNTIME_FUNCTION(Runtime_GetArrayKeys) {
10746   HandleScope scope(isolate);
10747   ASSERT(args.length() == 2);
10748   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10749   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10750   if (array->elements()->IsDictionary()) {
10751     Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10752     for (Handle<Object> p = array;
10753          !p->IsNull();
10754          p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
10755       if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
10756         // Bail out if we find a proxy or interceptor, likely not worth
10757         // collecting keys in that case.
10758         return *isolate->factory()->NewNumberFromUint(length);
10759       }
10760       Handle<JSObject> current = Handle<JSObject>::cast(p);
10761       Handle<FixedArray> current_keys =
10762           isolate->factory()->NewFixedArray(current->NumberOfOwnElements(NONE));
10763       current->GetOwnElementKeys(*current_keys, NONE);
10764       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
10765           isolate, keys, FixedArray::UnionOfKeys(keys, current_keys));
10766     }
10767     // Erase any keys >= length.
10768     // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10769     // is changed to let this happen on the JS side.
10770     for (int i = 0; i < keys->length(); i++) {
10771       if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10772     }
10773     return *isolate->factory()->NewJSArrayWithElements(keys);
10774   } else {
10775     RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() ||
10776                    array->HasFastDoubleElements());
10777     uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10778     return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10779   }
10780 }
10781 
10782 
RUNTIME_FUNCTION(Runtime_LookupAccessor)10783 RUNTIME_FUNCTION(Runtime_LookupAccessor) {
10784   HandleScope scope(isolate);
10785   ASSERT(args.length() == 3);
10786   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
10787   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10788   CONVERT_SMI_ARG_CHECKED(flag, 2);
10789   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10790   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10791   Handle<Object> result;
10792   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
10793       isolate, result,
10794       JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
10795   return *result;
10796 }
10797 
10798 
RUNTIME_FUNCTION(Runtime_DebugBreak)10799 RUNTIME_FUNCTION(Runtime_DebugBreak) {
10800   SealHandleScope shs(isolate);
10801   ASSERT(args.length() == 0);
10802   isolate->debug()->HandleDebugBreak();
10803   return isolate->heap()->undefined_value();
10804 }
10805 
10806 
10807 // Helper functions for wrapping and unwrapping stack frame ids.
WrapFrameId(StackFrame::Id id)10808 static Smi* WrapFrameId(StackFrame::Id id) {
10809   ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10810   return Smi::FromInt(id >> 2);
10811 }
10812 
10813 
UnwrapFrameId(int wrapped)10814 static StackFrame::Id UnwrapFrameId(int wrapped) {
10815   return static_cast<StackFrame::Id>(wrapped << 2);
10816 }
10817 
10818 
10819 // Adds a JavaScript function as a debug event listener.
10820 // args[0]: debug event listener function to set or null or undefined for
10821 //          clearing the event listener function
10822 // args[1]: object supplied during callback
RUNTIME_FUNCTION(Runtime_SetDebugEventListener)10823 RUNTIME_FUNCTION(Runtime_SetDebugEventListener) {
10824   SealHandleScope shs(isolate);
10825   ASSERT(args.length() == 2);
10826   RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10827                  args[0]->IsUndefined() ||
10828                  args[0]->IsNull());
10829   CONVERT_ARG_HANDLE_CHECKED(Object, callback, 0);
10830   CONVERT_ARG_HANDLE_CHECKED(Object, data, 1);
10831   isolate->debug()->SetEventListener(callback, data);
10832 
10833   return isolate->heap()->undefined_value();
10834 }
10835 
10836 
RUNTIME_FUNCTION(Runtime_Break)10837 RUNTIME_FUNCTION(Runtime_Break) {
10838   SealHandleScope shs(isolate);
10839   ASSERT(args.length() == 0);
10840   isolate->stack_guard()->RequestDebugBreak();
10841   return isolate->heap()->undefined_value();
10842 }
10843 
10844 
DebugLookupResultValue(Isolate * isolate,Handle<Object> receiver,Handle<Name> name,LookupResult * result,bool * has_caught=NULL)10845 static Handle<Object> DebugLookupResultValue(Isolate* isolate,
10846                                              Handle<Object> receiver,
10847                                              Handle<Name> name,
10848                                              LookupResult* result,
10849                                              bool* has_caught = NULL) {
10850   Handle<Object> value = isolate->factory()->undefined_value();
10851   if  (!result->IsFound()) return value;
10852   switch (result->type()) {
10853     case NORMAL:
10854       value = JSObject::GetNormalizedProperty(
10855           handle(result->holder(), isolate), result);
10856       break;
10857     case FIELD:
10858       value = JSObject::FastPropertyAt(handle(result->holder(), isolate),
10859                                        result->representation(),
10860                                        result->GetFieldIndex());
10861       break;
10862     case CONSTANT:
10863       return handle(result->GetConstant(), isolate);
10864     case CALLBACKS: {
10865       Handle<Object> structure(result->GetCallbackObject(), isolate);
10866       ASSERT(!structure->IsForeign());
10867       if (structure->IsAccessorInfo()) {
10868         MaybeHandle<Object> obj = JSObject::GetPropertyWithAccessor(
10869             receiver, name, handle(result->holder(), isolate), structure);
10870         if (!obj.ToHandle(&value)) {
10871           value = handle(isolate->pending_exception(), isolate);
10872           isolate->clear_pending_exception();
10873           if (has_caught != NULL) *has_caught = true;
10874           return value;
10875         }
10876       }
10877       break;
10878     }
10879     case INTERCEPTOR:
10880     case HANDLER:
10881       break;
10882     case NONEXISTENT:
10883       UNREACHABLE();
10884       break;
10885   }
10886   ASSERT(!value->IsTheHole() || result->IsReadOnly());
10887   return value->IsTheHole()
10888       ? Handle<Object>::cast(isolate->factory()->undefined_value()) : value;
10889 }
10890 
10891 
10892 // Get debugger related details for an object property.
10893 // args[0]: object holding property
10894 // args[1]: name of the property
10895 //
10896 // The array returned contains the following information:
10897 // 0: Property value
10898 // 1: Property details
10899 // 2: Property value is exception
10900 // 3: Getter function if defined
10901 // 4: Setter function if defined
10902 // Items 2-4 are only filled if the property has either a getter or a setter
10903 // defined through __defineGetter__ and/or __defineSetter__.
RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails)10904 RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
10905   HandleScope scope(isolate);
10906 
10907   ASSERT(args.length() == 2);
10908 
10909   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10910   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10911 
10912   // Make sure to set the current context to the context before the debugger was
10913   // entered (if the debugger is entered). The reason for switching context here
10914   // is that for some property lookups (accessors and interceptors) callbacks
10915   // into the embedding application can occour, and the embedding application
10916   // could have the assumption that its own native context is the current
10917   // context and not some internal debugger context.
10918   SaveContext save(isolate);
10919   if (isolate->debug()->in_debug_scope()) {
10920     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10921   }
10922 
10923   // Skip the global proxy as it has no properties and always delegates to the
10924   // real global object.
10925   if (obj->IsJSGlobalProxy()) {
10926     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10927   }
10928 
10929 
10930   // Check if the name is trivially convertible to an index and get the element
10931   // if so.
10932   uint32_t index;
10933   if (name->AsArrayIndex(&index)) {
10934     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10935     Handle<Object> element_or_char;
10936     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
10937         isolate, element_or_char,
10938         Runtime::GetElementOrCharAt(isolate, obj, index));
10939     details->set(0, *element_or_char);
10940     details->set(
10941         1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
10942     return *isolate->factory()->NewJSArrayWithElements(details);
10943   }
10944 
10945   // Find the number of objects making up this.
10946   int length = OwnPrototypeChainLength(*obj);
10947 
10948   // Try own lookup on each of the objects.
10949   Handle<JSObject> jsproto = obj;
10950   for (int i = 0; i < length; i++) {
10951     LookupResult result(isolate);
10952     jsproto->LookupOwn(name, &result);
10953     if (result.IsFound()) {
10954       // LookupResult is not GC safe as it holds raw object pointers.
10955       // GC can happen later in this code so put the required fields into
10956       // local variables using handles when required for later use.
10957       Handle<Object> result_callback_obj;
10958       if (result.IsPropertyCallbacks()) {
10959         result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10960                                              isolate);
10961       }
10962 
10963 
10964       bool has_caught = false;
10965       Handle<Object> value = DebugLookupResultValue(
10966           isolate, obj, name, &result, &has_caught);
10967 
10968       // If the callback object is a fixed array then it contains JavaScript
10969       // getter and/or setter.
10970       bool has_js_accessors = result.IsPropertyCallbacks() &&
10971                               result_callback_obj->IsAccessorPair();
10972       Handle<FixedArray> details =
10973           isolate->factory()->NewFixedArray(has_js_accessors ? 5 : 2);
10974       details->set(0, *value);
10975       details->set(1, result.GetPropertyDetails().AsSmi());
10976       if (has_js_accessors) {
10977         AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10978         details->set(2, isolate->heap()->ToBoolean(has_caught));
10979         details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10980         details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10981       }
10982 
10983       return *isolate->factory()->NewJSArrayWithElements(details);
10984     }
10985     if (i < length - 1) {
10986       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10987     }
10988   }
10989 
10990   return isolate->heap()->undefined_value();
10991 }
10992 
10993 
RUNTIME_FUNCTION(Runtime_DebugGetProperty)10994 RUNTIME_FUNCTION(Runtime_DebugGetProperty) {
10995   HandleScope scope(isolate);
10996 
10997   ASSERT(args.length() == 2);
10998 
10999   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11000   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
11001 
11002   LookupResult result(isolate);
11003   obj->Lookup(name, &result);
11004   return *DebugLookupResultValue(isolate, obj, name, &result);
11005 }
11006 
11007 
11008 // Return the property type calculated from the property details.
11009 // args[0]: smi with property details.
RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails)11010 RUNTIME_FUNCTION(Runtime_DebugPropertyTypeFromDetails) {
11011   SealHandleScope shs(isolate);
11012   ASSERT(args.length() == 1);
11013   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11014   return Smi::FromInt(static_cast<int>(details.type()));
11015 }
11016 
11017 
11018 // Return the property attribute calculated from the property details.
11019 // args[0]: smi with property details.
RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails)11020 RUNTIME_FUNCTION(Runtime_DebugPropertyAttributesFromDetails) {
11021   SealHandleScope shs(isolate);
11022   ASSERT(args.length() == 1);
11023   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11024   return Smi::FromInt(static_cast<int>(details.attributes()));
11025 }
11026 
11027 
11028 // Return the property insertion index calculated from the property details.
11029 // args[0]: smi with property details.
RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails)11030 RUNTIME_FUNCTION(Runtime_DebugPropertyIndexFromDetails) {
11031   SealHandleScope shs(isolate);
11032   ASSERT(args.length() == 1);
11033   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11034   // TODO(verwaest): Depends on the type of details.
11035   return Smi::FromInt(details.dictionary_index());
11036 }
11037 
11038 
11039 // Return property value from named interceptor.
11040 // args[0]: object
11041 // args[1]: property name
RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue)11042 RUNTIME_FUNCTION(Runtime_DebugNamedInterceptorPropertyValue) {
11043   HandleScope scope(isolate);
11044   ASSERT(args.length() == 2);
11045   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11046   RUNTIME_ASSERT(obj->HasNamedInterceptor());
11047   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
11048 
11049   Handle<Object> result;
11050   LookupIterator it(obj, name, obj);
11051   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
11052       isolate, result, JSObject::GetProperty(&it));
11053   return *result;
11054 }
11055 
11056 
11057 // Return element value from indexed interceptor.
11058 // args[0]: object
11059 // args[1]: index
RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue)11060 RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) {
11061   HandleScope scope(isolate);
11062   ASSERT(args.length() == 2);
11063   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11064   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
11065   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
11066   Handle<Object> result;
11067   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
11068       isolate, result, JSObject::GetElementWithInterceptor(obj, obj, index));
11069   return *result;
11070 }
11071 
11072 
CheckExecutionState(Isolate * isolate,int break_id)11073 static bool CheckExecutionState(Isolate* isolate, int break_id) {
11074   return !isolate->debug()->debug_context().is_null() &&
11075          isolate->debug()->break_id() != 0 &&
11076          isolate->debug()->break_id() == break_id;
11077 }
11078 
11079 
RUNTIME_FUNCTION(Runtime_CheckExecutionState)11080 RUNTIME_FUNCTION(Runtime_CheckExecutionState) {
11081   SealHandleScope shs(isolate);
11082   ASSERT(args.length() == 1);
11083   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11084   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
11085   return isolate->heap()->true_value();
11086 }
11087 
11088 
RUNTIME_FUNCTION(Runtime_GetFrameCount)11089 RUNTIME_FUNCTION(Runtime_GetFrameCount) {
11090   HandleScope scope(isolate);
11091   ASSERT(args.length() == 1);
11092   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11093   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
11094 
11095   // Count all frames which are relevant to debugging stack trace.
11096   int n = 0;
11097   StackFrame::Id id = isolate->debug()->break_frame_id();
11098   if (id == StackFrame::NO_ID) {
11099     // If there is no JavaScript stack frame count is 0.
11100     return Smi::FromInt(0);
11101   }
11102 
11103   for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
11104     n += it.frame()->GetInlineCount();
11105   }
11106   return Smi::FromInt(n);
11107 }
11108 
11109 
11110 class FrameInspector {
11111  public:
FrameInspector(JavaScriptFrame * frame,int inlined_jsframe_index,Isolate * isolate)11112   FrameInspector(JavaScriptFrame* frame,
11113                  int inlined_jsframe_index,
11114                  Isolate* isolate)
11115       : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
11116     // Calculate the deoptimized frame.
11117     if (frame->is_optimized()) {
11118       deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
11119           frame, inlined_jsframe_index, isolate);
11120     }
11121     has_adapted_arguments_ = frame_->has_adapted_arguments();
11122     is_bottommost_ = inlined_jsframe_index == 0;
11123     is_optimized_ = frame_->is_optimized();
11124   }
11125 
~FrameInspector()11126   ~FrameInspector() {
11127     // Get rid of the calculated deoptimized frame if any.
11128     if (deoptimized_frame_ != NULL) {
11129       Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
11130                                                   isolate_);
11131     }
11132   }
11133 
GetParametersCount()11134   int GetParametersCount() {
11135     return is_optimized_
11136         ? deoptimized_frame_->parameters_count()
11137         : frame_->ComputeParametersCount();
11138   }
expression_count()11139   int expression_count() { return deoptimized_frame_->expression_count(); }
GetFunction()11140   Object* GetFunction() {
11141     return is_optimized_
11142         ? deoptimized_frame_->GetFunction()
11143         : frame_->function();
11144   }
GetParameter(int index)11145   Object* GetParameter(int index) {
11146     return is_optimized_
11147         ? deoptimized_frame_->GetParameter(index)
11148         : frame_->GetParameter(index);
11149   }
GetExpression(int index)11150   Object* GetExpression(int index) {
11151     return is_optimized_
11152         ? deoptimized_frame_->GetExpression(index)
11153         : frame_->GetExpression(index);
11154   }
GetSourcePosition()11155   int GetSourcePosition() {
11156     return is_optimized_
11157         ? deoptimized_frame_->GetSourcePosition()
11158         : frame_->LookupCode()->SourcePosition(frame_->pc());
11159   }
IsConstructor()11160   bool IsConstructor() {
11161     return is_optimized_ && !is_bottommost_
11162         ? deoptimized_frame_->HasConstructStub()
11163         : frame_->IsConstructor();
11164   }
11165 
11166   // To inspect all the provided arguments the frame might need to be
11167   // replaced with the arguments frame.
SetArgumentsFrame(JavaScriptFrame * frame)11168   void SetArgumentsFrame(JavaScriptFrame* frame) {
11169     ASSERT(has_adapted_arguments_);
11170     frame_ = frame;
11171     is_optimized_ = frame_->is_optimized();
11172     ASSERT(!is_optimized_);
11173   }
11174 
11175  private:
11176   JavaScriptFrame* frame_;
11177   DeoptimizedFrameInfo* deoptimized_frame_;
11178   Isolate* isolate_;
11179   bool is_optimized_;
11180   bool is_bottommost_;
11181   bool has_adapted_arguments_;
11182 
11183   DISALLOW_COPY_AND_ASSIGN(FrameInspector);
11184 };
11185 
11186 
11187 static const int kFrameDetailsFrameIdIndex = 0;
11188 static const int kFrameDetailsReceiverIndex = 1;
11189 static const int kFrameDetailsFunctionIndex = 2;
11190 static const int kFrameDetailsArgumentCountIndex = 3;
11191 static const int kFrameDetailsLocalCountIndex = 4;
11192 static const int kFrameDetailsSourcePositionIndex = 5;
11193 static const int kFrameDetailsConstructCallIndex = 6;
11194 static const int kFrameDetailsAtReturnIndex = 7;
11195 static const int kFrameDetailsFlagsIndex = 8;
11196 static const int kFrameDetailsFirstDynamicIndex = 9;
11197 
11198 
FindSavedContextForFrame(Isolate * isolate,JavaScriptFrame * frame)11199 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
11200                                              JavaScriptFrame* frame) {
11201   SaveContext* save = isolate->save_context();
11202   while (save != NULL && !save->IsBelowFrame(frame)) {
11203     save = save->prev();
11204   }
11205   ASSERT(save != NULL);
11206   return save;
11207 }
11208 
11209 
11210 // Return an array with frame details
11211 // args[0]: number: break id
11212 // args[1]: number: frame index
11213 //
11214 // The array returned contains the following information:
11215 // 0: Frame id
11216 // 1: Receiver
11217 // 2: Function
11218 // 3: Argument count
11219 // 4: Local count
11220 // 5: Source position
11221 // 6: Constructor call
11222 // 7: Is at return
11223 // 8: Flags
11224 // Arguments name, value
11225 // Locals name, value
11226 // Return value if any
RUNTIME_FUNCTION(Runtime_GetFrameDetails)11227 RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
11228   HandleScope scope(isolate);
11229   ASSERT(args.length() == 2);
11230   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11231   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
11232 
11233   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11234   Heap* heap = isolate->heap();
11235 
11236   // Find the relevant frame with the requested index.
11237   StackFrame::Id id = isolate->debug()->break_frame_id();
11238   if (id == StackFrame::NO_ID) {
11239     // If there are no JavaScript stack frames return undefined.
11240     return heap->undefined_value();
11241   }
11242 
11243   int count = 0;
11244   JavaScriptFrameIterator it(isolate, id);
11245   for (; !it.done(); it.Advance()) {
11246     if (index < count + it.frame()->GetInlineCount()) break;
11247     count += it.frame()->GetInlineCount();
11248   }
11249   if (it.done()) return heap->undefined_value();
11250 
11251   bool is_optimized = it.frame()->is_optimized();
11252 
11253   int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
11254   if (is_optimized) {
11255     inlined_jsframe_index =
11256         it.frame()->GetInlineCount() - (index - count) - 1;
11257   }
11258   FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11259 
11260   // Traverse the saved contexts chain to find the active context for the
11261   // selected frame.
11262   SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11263 
11264   // Get the frame id.
11265   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11266 
11267   // Find source position in unoptimized code.
11268   int position = frame_inspector.GetSourcePosition();
11269 
11270   // Check for constructor frame.
11271   bool constructor = frame_inspector.IsConstructor();
11272 
11273   // Get scope info and read from it for local variable information.
11274   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11275   Handle<SharedFunctionInfo> shared(function->shared());
11276   Handle<ScopeInfo> scope_info(shared->scope_info());
11277   ASSERT(*scope_info != ScopeInfo::Empty(isolate));
11278 
11279   // Get the locals names and values into a temporary array.
11280   int local_count = scope_info->LocalCount();
11281   for (int slot = 0; slot < scope_info->LocalCount(); ++slot) {
11282     // Hide compiler-introduced temporary variables, whether on the stack or on
11283     // the context.
11284     if (scope_info->LocalIsSynthetic(slot))
11285       local_count--;
11286   }
11287 
11288   Handle<FixedArray> locals =
11289       isolate->factory()->NewFixedArray(local_count * 2);
11290 
11291   // Fill in the values of the locals.
11292   int local = 0;
11293   int i = 0;
11294   for (; i < scope_info->StackLocalCount(); ++i) {
11295     // Use the value from the stack.
11296     if (scope_info->LocalIsSynthetic(i))
11297       continue;
11298     locals->set(local * 2, scope_info->LocalName(i));
11299     locals->set(local * 2 + 1, frame_inspector.GetExpression(i));
11300     local++;
11301   }
11302   if (local < local_count) {
11303     // Get the context containing declarations.
11304     Handle<Context> context(
11305         Context::cast(it.frame()->context())->declaration_context());
11306     for (; i < scope_info->LocalCount(); ++i) {
11307       if (scope_info->LocalIsSynthetic(i))
11308         continue;
11309       Handle<String> name(scope_info->LocalName(i));
11310       VariableMode mode;
11311       InitializationFlag init_flag;
11312       locals->set(local * 2, *name);
11313       int context_slot_index =
11314           ScopeInfo::ContextSlotIndex(scope_info, name, &mode, &init_flag);
11315       Object* value = context->get(context_slot_index);
11316       locals->set(local * 2 + 1, value);
11317       local++;
11318     }
11319   }
11320 
11321   // Check whether this frame is positioned at return. If not top
11322   // frame or if the frame is optimized it cannot be at a return.
11323   bool at_return = false;
11324   if (!is_optimized && index == 0) {
11325     at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11326   }
11327 
11328   // If positioned just before return find the value to be returned and add it
11329   // to the frame information.
11330   Handle<Object> return_value = isolate->factory()->undefined_value();
11331   if (at_return) {
11332     StackFrameIterator it2(isolate);
11333     Address internal_frame_sp = NULL;
11334     while (!it2.done()) {
11335       if (it2.frame()->is_internal()) {
11336         internal_frame_sp = it2.frame()->sp();
11337       } else {
11338         if (it2.frame()->is_java_script()) {
11339           if (it2.frame()->id() == it.frame()->id()) {
11340             // The internal frame just before the JavaScript frame contains the
11341             // value to return on top. A debug break at return will create an
11342             // internal frame to store the return value (eax/rax/r0) before
11343             // entering the debug break exit frame.
11344             if (internal_frame_sp != NULL) {
11345               return_value =
11346                   Handle<Object>(Memory::Object_at(internal_frame_sp),
11347                                  isolate);
11348               break;
11349             }
11350           }
11351         }
11352 
11353         // Indicate that the previous frame was not an internal frame.
11354         internal_frame_sp = NULL;
11355       }
11356       it2.Advance();
11357     }
11358   }
11359 
11360   // Now advance to the arguments adapter frame (if any). It contains all
11361   // the provided parameters whereas the function frame always have the number
11362   // of arguments matching the functions parameters. The rest of the
11363   // information (except for what is collected above) is the same.
11364   if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11365     it.AdvanceToArgumentsFrame();
11366     frame_inspector.SetArgumentsFrame(it.frame());
11367   }
11368 
11369   // Find the number of arguments to fill. At least fill the number of
11370   // parameters for the function and fill more if more parameters are provided.
11371   int argument_count = scope_info->ParameterCount();
11372   if (argument_count < frame_inspector.GetParametersCount()) {
11373     argument_count = frame_inspector.GetParametersCount();
11374   }
11375 
11376   // Calculate the size of the result.
11377   int details_size = kFrameDetailsFirstDynamicIndex +
11378                      2 * (argument_count + local_count) +
11379                      (at_return ? 1 : 0);
11380   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11381 
11382   // Add the frame id.
11383   details->set(kFrameDetailsFrameIdIndex, *frame_id);
11384 
11385   // Add the function (same as in function frame).
11386   details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11387 
11388   // Add the arguments count.
11389   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11390 
11391   // Add the locals count
11392   details->set(kFrameDetailsLocalCountIndex,
11393                Smi::FromInt(local_count));
11394 
11395   // Add the source position.
11396   if (position != RelocInfo::kNoPosition) {
11397     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11398   } else {
11399     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11400   }
11401 
11402   // Add the constructor information.
11403   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11404 
11405   // Add the at return information.
11406   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11407 
11408   // Add flags to indicate information on whether this frame is
11409   //   bit 0: invoked in the debugger context.
11410   //   bit 1: optimized frame.
11411   //   bit 2: inlined in optimized frame
11412   int flags = 0;
11413   if (*save->context() == *isolate->debug()->debug_context()) {
11414     flags |= 1 << 0;
11415   }
11416   if (is_optimized) {
11417     flags |= 1 << 1;
11418     flags |= inlined_jsframe_index << 2;
11419   }
11420   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11421 
11422   // Fill the dynamic part.
11423   int details_index = kFrameDetailsFirstDynamicIndex;
11424 
11425   // Add arguments name and value.
11426   for (int i = 0; i < argument_count; i++) {
11427     // Name of the argument.
11428     if (i < scope_info->ParameterCount()) {
11429       details->set(details_index++, scope_info->ParameterName(i));
11430     } else {
11431       details->set(details_index++, heap->undefined_value());
11432     }
11433 
11434     // Parameter value.
11435     if (i < frame_inspector.GetParametersCount()) {
11436       // Get the value from the stack.
11437       details->set(details_index++, frame_inspector.GetParameter(i));
11438     } else {
11439       details->set(details_index++, heap->undefined_value());
11440     }
11441   }
11442 
11443   // Add locals name and value from the temporary copy from the function frame.
11444   for (int i = 0; i < local_count * 2; i++) {
11445     details->set(details_index++, locals->get(i));
11446   }
11447 
11448   // Add the value being returned.
11449   if (at_return) {
11450     details->set(details_index++, *return_value);
11451   }
11452 
11453   // Add the receiver (same as in function frame).
11454   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11455   // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11456   Handle<Object> receiver(it.frame()->receiver(), isolate);
11457   if (!receiver->IsJSObject() &&
11458       shared->strict_mode() == SLOPPY &&
11459       !function->IsBuiltin()) {
11460     // If the receiver is not a JSObject and the function is not a
11461     // builtin or strict-mode we have hit an optimization where a
11462     // value object is not converted into a wrapped JS objects. To
11463     // hide this optimization from the debugger, we wrap the receiver
11464     // by creating correct wrapper object based on the calling frame's
11465     // native context.
11466     it.Advance();
11467     if (receiver->IsUndefined()) {
11468       Context* context = function->context();
11469       receiver = handle(context->global_object()->global_receiver());
11470     } else {
11471       ASSERT(!receiver->IsNull());
11472       Context* context = Context::cast(it.frame()->context());
11473       Handle<Context> native_context(Context::cast(context->native_context()));
11474       receiver = Object::ToObject(
11475           isolate, receiver, native_context).ToHandleChecked();
11476     }
11477   }
11478   details->set(kFrameDetailsReceiverIndex, *receiver);
11479 
11480   ASSERT_EQ(details_size, details_index);
11481   return *isolate->factory()->NewJSArrayWithElements(details);
11482 }
11483 
11484 
ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,Handle<String> parameter_name)11485 static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
11486                                               Handle<String> parameter_name) {
11487   VariableMode mode;
11488   InitializationFlag flag;
11489   return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &flag) != -1;
11490 }
11491 
11492 
11493 // Create a plain JSObject which materializes the local scope for the specified
11494 // frame.
11495 MUST_USE_RESULT
MaterializeStackLocalsWithFrameInspector(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function,FrameInspector * frame_inspector)11496 static MaybeHandle<JSObject> MaterializeStackLocalsWithFrameInspector(
11497     Isolate* isolate,
11498     Handle<JSObject> target,
11499     Handle<JSFunction> function,
11500     FrameInspector* frame_inspector) {
11501   Handle<SharedFunctionInfo> shared(function->shared());
11502   Handle<ScopeInfo> scope_info(shared->scope_info());
11503 
11504   // First fill all parameters.
11505   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11506     // Do not materialize the parameter if it is shadowed by a context local.
11507     Handle<String> name(scope_info->ParameterName(i));
11508     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
11509 
11510     HandleScope scope(isolate);
11511     Handle<Object> value(i < frame_inspector->GetParametersCount()
11512                              ? frame_inspector->GetParameter(i)
11513                              : isolate->heap()->undefined_value(),
11514                          isolate);
11515     ASSERT(!value->IsTheHole());
11516 
11517     RETURN_ON_EXCEPTION(
11518         isolate,
11519         Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
11520         JSObject);
11521   }
11522 
11523   // Second fill all stack locals.
11524   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11525     if (scope_info->LocalIsSynthetic(i)) continue;
11526     Handle<String> name(scope_info->StackLocalName(i));
11527     Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11528     if (value->IsTheHole()) continue;
11529 
11530     RETURN_ON_EXCEPTION(
11531         isolate,
11532         Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
11533         JSObject);
11534   }
11535 
11536   return target;
11537 }
11538 
11539 
UpdateStackLocalsFromMaterializedObject(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function,JavaScriptFrame * frame,int inlined_jsframe_index)11540 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11541                                                     Handle<JSObject> target,
11542                                                     Handle<JSFunction> function,
11543                                                     JavaScriptFrame* frame,
11544                                                     int inlined_jsframe_index) {
11545   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11546     // Optimized frames are not supported.
11547     // TODO(yangguo): make sure all code deoptimized when debugger is active
11548     //                and assert that this cannot happen.
11549     return;
11550   }
11551 
11552   Handle<SharedFunctionInfo> shared(function->shared());
11553   Handle<ScopeInfo> scope_info(shared->scope_info());
11554 
11555   // Parameters.
11556   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11557     // Shadowed parameters were not materialized.
11558     Handle<String> name(scope_info->ParameterName(i));
11559     if (ParameterIsShadowedByContextLocal(scope_info, name)) continue;
11560 
11561     ASSERT(!frame->GetParameter(i)->IsTheHole());
11562     HandleScope scope(isolate);
11563     Handle<Object> value =
11564         Object::GetPropertyOrElement(target, name).ToHandleChecked();
11565     frame->SetParameterValue(i, *value);
11566   }
11567 
11568   // Stack locals.
11569   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11570     if (scope_info->LocalIsSynthetic(i)) continue;
11571     if (frame->GetExpression(i)->IsTheHole()) continue;
11572     HandleScope scope(isolate);
11573     Handle<Object> value = Object::GetPropertyOrElement(
11574         target,
11575         handle(scope_info->StackLocalName(i), isolate)).ToHandleChecked();
11576     frame->SetExpression(i, *value);
11577   }
11578 }
11579 
11580 
MaterializeLocalContext(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function,JavaScriptFrame * frame)11581 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalContext(
11582     Isolate* isolate,
11583     Handle<JSObject> target,
11584     Handle<JSFunction> function,
11585     JavaScriptFrame* frame) {
11586   HandleScope scope(isolate);
11587   Handle<SharedFunctionInfo> shared(function->shared());
11588   Handle<ScopeInfo> scope_info(shared->scope_info());
11589 
11590   if (!scope_info->HasContext()) return target;
11591 
11592   // Third fill all context locals.
11593   Handle<Context> frame_context(Context::cast(frame->context()));
11594   Handle<Context> function_context(frame_context->declaration_context());
11595   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11596           scope_info, function_context, target)) {
11597     return MaybeHandle<JSObject>();
11598   }
11599 
11600   // Finally copy any properties from the function context extension.
11601   // These will be variables introduced by eval.
11602   if (function_context->closure() == *function) {
11603     if (function_context->has_extension() &&
11604         !function_context->IsNativeContext()) {
11605       Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11606       Handle<FixedArray> keys;
11607       ASSIGN_RETURN_ON_EXCEPTION(
11608           isolate, keys,
11609           JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS),
11610           JSObject);
11611 
11612       for (int i = 0; i < keys->length(); i++) {
11613         // Names of variables introduced by eval are strings.
11614         ASSERT(keys->get(i)->IsString());
11615         Handle<String> key(String::cast(keys->get(i)));
11616         Handle<Object> value;
11617         ASSIGN_RETURN_ON_EXCEPTION(
11618             isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
11619         RETURN_ON_EXCEPTION(
11620             isolate,
11621             Runtime::SetObjectProperty(
11622                 isolate, target, key, value, NONE, SLOPPY),
11623             JSObject);
11624       }
11625     }
11626   }
11627 
11628   return target;
11629 }
11630 
11631 
MaterializeLocalScope(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index)11632 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeLocalScope(
11633     Isolate* isolate,
11634     JavaScriptFrame* frame,
11635     int inlined_jsframe_index) {
11636   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11637   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11638 
11639   Handle<JSObject> local_scope =
11640       isolate->factory()->NewJSObject(isolate->object_function());
11641   ASSIGN_RETURN_ON_EXCEPTION(
11642       isolate, local_scope,
11643       MaterializeStackLocalsWithFrameInspector(
11644           isolate, local_scope, function, &frame_inspector),
11645       JSObject);
11646 
11647   return MaterializeLocalContext(isolate, local_scope, function, frame);
11648 }
11649 
11650 
11651 // Set the context local variable value.
SetContextLocalValue(Isolate * isolate,Handle<ScopeInfo> scope_info,Handle<Context> context,Handle<String> variable_name,Handle<Object> new_value)11652 static bool SetContextLocalValue(Isolate* isolate,
11653                                  Handle<ScopeInfo> scope_info,
11654                                  Handle<Context> context,
11655                                  Handle<String> variable_name,
11656                                  Handle<Object> new_value) {
11657   for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11658     Handle<String> next_name(scope_info->ContextLocalName(i));
11659     if (String::Equals(variable_name, next_name)) {
11660       VariableMode mode;
11661       InitializationFlag init_flag;
11662       int context_index =
11663           ScopeInfo::ContextSlotIndex(scope_info, next_name, &mode, &init_flag);
11664       context->set(context_index, *new_value);
11665       return true;
11666     }
11667   }
11668 
11669   return false;
11670 }
11671 
11672 
SetLocalVariableValue(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index,Handle<String> variable_name,Handle<Object> new_value)11673 static bool SetLocalVariableValue(Isolate* isolate,
11674                                   JavaScriptFrame* frame,
11675                                   int inlined_jsframe_index,
11676                                   Handle<String> variable_name,
11677                                   Handle<Object> new_value) {
11678   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11679     // Optimized frames are not supported.
11680     return false;
11681   }
11682 
11683   Handle<JSFunction> function(frame->function());
11684   Handle<SharedFunctionInfo> shared(function->shared());
11685   Handle<ScopeInfo> scope_info(shared->scope_info());
11686 
11687   bool default_result = false;
11688 
11689   // Parameters.
11690   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11691     HandleScope scope(isolate);
11692     if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
11693       frame->SetParameterValue(i, *new_value);
11694       // Argument might be shadowed in heap context, don't stop here.
11695       default_result = true;
11696     }
11697   }
11698 
11699   // Stack locals.
11700   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11701     HandleScope scope(isolate);
11702     if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
11703       frame->SetExpression(i, *new_value);
11704       return true;
11705     }
11706   }
11707 
11708   if (scope_info->HasContext()) {
11709     // Context locals.
11710     Handle<Context> frame_context(Context::cast(frame->context()));
11711     Handle<Context> function_context(frame_context->declaration_context());
11712     if (SetContextLocalValue(
11713         isolate, scope_info, function_context, variable_name, new_value)) {
11714       return true;
11715     }
11716 
11717     // Function context extension. These are variables introduced by eval.
11718     if (function_context->closure() == *function) {
11719       if (function_context->has_extension() &&
11720           !function_context->IsNativeContext()) {
11721         Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11722 
11723         if (JSReceiver::HasProperty(ext, variable_name)) {
11724           // We don't expect this to do anything except replacing
11725           // property value.
11726           Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11727                                      NONE, SLOPPY).Assert();
11728           return true;
11729         }
11730       }
11731     }
11732   }
11733 
11734   return default_result;
11735 }
11736 
11737 
11738 // Create a plain JSObject which materializes the closure content for the
11739 // context.
MaterializeClosure(Isolate * isolate,Handle<Context> context)11740 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeClosure(
11741     Isolate* isolate,
11742     Handle<Context> context) {
11743   ASSERT(context->IsFunctionContext());
11744 
11745   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11746   Handle<ScopeInfo> scope_info(shared->scope_info());
11747 
11748   // Allocate and initialize a JSObject with all the content of this function
11749   // closure.
11750   Handle<JSObject> closure_scope =
11751       isolate->factory()->NewJSObject(isolate->object_function());
11752 
11753   // Fill all context locals to the context extension.
11754   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11755           scope_info, context, closure_scope)) {
11756     return MaybeHandle<JSObject>();
11757   }
11758 
11759   // Finally copy any properties from the function context extension. This will
11760   // be variables introduced by eval.
11761   if (context->has_extension()) {
11762     Handle<JSObject> ext(JSObject::cast(context->extension()));
11763     Handle<FixedArray> keys;
11764     ASSIGN_RETURN_ON_EXCEPTION(
11765         isolate, keys,
11766         JSReceiver::GetKeys(ext, JSReceiver::INCLUDE_PROTOS), JSObject);
11767 
11768     for (int i = 0; i < keys->length(); i++) {
11769       HandleScope scope(isolate);
11770       // Names of variables introduced by eval are strings.
11771       ASSERT(keys->get(i)->IsString());
11772       Handle<String> key(String::cast(keys->get(i)));
11773       Handle<Object> value;
11774       ASSIGN_RETURN_ON_EXCEPTION(
11775           isolate, value, Object::GetPropertyOrElement(ext, key), JSObject);
11776       RETURN_ON_EXCEPTION(
11777           isolate,
11778           Runtime::SetObjectProperty(
11779               isolate, closure_scope, key, value, NONE, SLOPPY),
11780           JSObject);
11781     }
11782   }
11783 
11784   return closure_scope;
11785 }
11786 
11787 
11788 // This method copies structure of MaterializeClosure method above.
SetClosureVariableValue(Isolate * isolate,Handle<Context> context,Handle<String> variable_name,Handle<Object> new_value)11789 static bool SetClosureVariableValue(Isolate* isolate,
11790                                     Handle<Context> context,
11791                                     Handle<String> variable_name,
11792                                     Handle<Object> new_value) {
11793   ASSERT(context->IsFunctionContext());
11794 
11795   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11796   Handle<ScopeInfo> scope_info(shared->scope_info());
11797 
11798   // Context locals to the context extension.
11799   if (SetContextLocalValue(
11800           isolate, scope_info, context, variable_name, new_value)) {
11801     return true;
11802   }
11803 
11804   // Properties from the function context extension. This will
11805   // be variables introduced by eval.
11806   if (context->has_extension()) {
11807     Handle<JSObject> ext(JSObject::cast(context->extension()));
11808     if (JSReceiver::HasProperty(ext, variable_name)) {
11809       // We don't expect this to do anything except replacing property value.
11810       Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11811                                  NONE, SLOPPY).Assert();
11812       return true;
11813     }
11814   }
11815 
11816   return false;
11817 }
11818 
11819 
11820 // Create a plain JSObject which materializes the scope for the specified
11821 // catch context.
MaterializeCatchScope(Isolate * isolate,Handle<Context> context)11822 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeCatchScope(
11823     Isolate* isolate,
11824     Handle<Context> context) {
11825   ASSERT(context->IsCatchContext());
11826   Handle<String> name(String::cast(context->extension()));
11827   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11828                                isolate);
11829   Handle<JSObject> catch_scope =
11830       isolate->factory()->NewJSObject(isolate->object_function());
11831   RETURN_ON_EXCEPTION(
11832       isolate,
11833       Runtime::SetObjectProperty(isolate, catch_scope, name, thrown_object,
11834                                  NONE, SLOPPY),
11835       JSObject);
11836   return catch_scope;
11837 }
11838 
11839 
SetCatchVariableValue(Isolate * isolate,Handle<Context> context,Handle<String> variable_name,Handle<Object> new_value)11840 static bool SetCatchVariableValue(Isolate* isolate,
11841                                   Handle<Context> context,
11842                                   Handle<String> variable_name,
11843                                   Handle<Object> new_value) {
11844   ASSERT(context->IsCatchContext());
11845   Handle<String> name(String::cast(context->extension()));
11846   if (!String::Equals(name, variable_name)) {
11847     return false;
11848   }
11849   context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11850   return true;
11851 }
11852 
11853 
11854 // Create a plain JSObject which materializes the block scope for the specified
11855 // block context.
MaterializeBlockScope(Isolate * isolate,Handle<Context> context)11856 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeBlockScope(
11857     Isolate* isolate,
11858     Handle<Context> context) {
11859   ASSERT(context->IsBlockContext());
11860   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11861 
11862   // Allocate and initialize a JSObject with all the arguments, stack locals
11863   // heap locals and extension properties of the debugged function.
11864   Handle<JSObject> block_scope =
11865       isolate->factory()->NewJSObject(isolate->object_function());
11866 
11867   // Fill all context locals.
11868   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11869           scope_info, context, block_scope)) {
11870     return MaybeHandle<JSObject>();
11871   }
11872 
11873   return block_scope;
11874 }
11875 
11876 
11877 // Create a plain JSObject which materializes the module scope for the specified
11878 // module context.
MaterializeModuleScope(Isolate * isolate,Handle<Context> context)11879 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeModuleScope(
11880     Isolate* isolate,
11881     Handle<Context> context) {
11882   ASSERT(context->IsModuleContext());
11883   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11884 
11885   // Allocate and initialize a JSObject with all the members of the debugged
11886   // module.
11887   Handle<JSObject> module_scope =
11888       isolate->factory()->NewJSObject(isolate->object_function());
11889 
11890   // Fill all context locals.
11891   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11892           scope_info, context, module_scope)) {
11893     return MaybeHandle<JSObject>();
11894   }
11895 
11896   return module_scope;
11897 }
11898 
11899 
11900 // Iterate over the actual scopes visible from a stack frame or from a closure.
11901 // The iteration proceeds from the innermost visible nested scope outwards.
11902 // All scopes are backed by an actual context except the local scope,
11903 // which is inserted "artificially" in the context chain.
11904 class ScopeIterator {
11905  public:
11906   enum ScopeType {
11907     ScopeTypeGlobal = 0,
11908     ScopeTypeLocal,
11909     ScopeTypeWith,
11910     ScopeTypeClosure,
11911     ScopeTypeCatch,
11912     ScopeTypeBlock,
11913     ScopeTypeModule
11914   };
11915 
ScopeIterator(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index,bool ignore_nested_scopes=false)11916   ScopeIterator(Isolate* isolate,
11917                 JavaScriptFrame* frame,
11918                 int inlined_jsframe_index,
11919                 bool ignore_nested_scopes = false)
11920     : isolate_(isolate),
11921       frame_(frame),
11922       inlined_jsframe_index_(inlined_jsframe_index),
11923       function_(frame->function()),
11924       context_(Context::cast(frame->context())),
11925       nested_scope_chain_(4),
11926       failed_(false) {
11927 
11928     // Catch the case when the debugger stops in an internal function.
11929     Handle<SharedFunctionInfo> shared_info(function_->shared());
11930     Handle<ScopeInfo> scope_info(shared_info->scope_info());
11931     if (shared_info->script() == isolate->heap()->undefined_value()) {
11932       while (context_->closure() == *function_) {
11933         context_ = Handle<Context>(context_->previous(), isolate_);
11934       }
11935       return;
11936     }
11937 
11938     // Get the debug info (create it if it does not exist).
11939     if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
11940       // Return if ensuring debug info failed.
11941       return;
11942     }
11943 
11944     // Currently it takes too much time to find nested scopes due to script
11945     // parsing. Sometimes we want to run the ScopeIterator as fast as possible
11946     // (for example, while collecting async call stacks on every
11947     // addEventListener call), even if we drop some nested scopes.
11948     // Later we may optimize getting the nested scopes (cache the result?)
11949     // and include nested scopes into the "fast" iteration case as well.
11950     if (!ignore_nested_scopes) {
11951       Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11952 
11953       // Find the break point where execution has stopped.
11954       BreakLocationIterator break_location_iterator(debug_info,
11955                                                     ALL_BREAK_LOCATIONS);
11956       // pc points to the instruction after the current one, possibly a break
11957       // location as well. So the "- 1" to exclude it from the search.
11958       break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
11959 
11960       // Within the return sequence at the moment it is not possible to
11961       // get a source position which is consistent with the current scope chain.
11962       // Thus all nested with, catch and block contexts are skipped and we only
11963       // provide the function scope.
11964       ignore_nested_scopes = break_location_iterator.IsExit();
11965     }
11966 
11967     if (ignore_nested_scopes) {
11968       if (scope_info->HasContext()) {
11969         context_ = Handle<Context>(context_->declaration_context(), isolate_);
11970       } else {
11971         while (context_->closure() == *function_) {
11972           context_ = Handle<Context>(context_->previous(), isolate_);
11973         }
11974       }
11975       if (scope_info->scope_type() == FUNCTION_SCOPE) {
11976         nested_scope_chain_.Add(scope_info);
11977       }
11978     } else {
11979       // Reparse the code and analyze the scopes.
11980       Handle<Script> script(Script::cast(shared_info->script()));
11981       Scope* scope = NULL;
11982 
11983       // Check whether we are in global, eval or function code.
11984       Handle<ScopeInfo> scope_info(shared_info->scope_info());
11985       if (scope_info->scope_type() != FUNCTION_SCOPE) {
11986         // Global or eval code.
11987         CompilationInfoWithZone info(script);
11988         if (scope_info->scope_type() == GLOBAL_SCOPE) {
11989           info.MarkAsGlobal();
11990         } else {
11991           ASSERT(scope_info->scope_type() == EVAL_SCOPE);
11992           info.MarkAsEval();
11993           info.SetContext(Handle<Context>(function_->context()));
11994         }
11995         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11996           scope = info.function()->scope();
11997         }
11998         RetrieveScopeChain(scope, shared_info);
11999       } else {
12000         // Function code
12001         CompilationInfoWithZone info(shared_info);
12002         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
12003           scope = info.function()->scope();
12004         }
12005         RetrieveScopeChain(scope, shared_info);
12006       }
12007     }
12008   }
12009 
ScopeIterator(Isolate * isolate,Handle<JSFunction> function)12010   ScopeIterator(Isolate* isolate,
12011                 Handle<JSFunction> function)
12012     : isolate_(isolate),
12013       frame_(NULL),
12014       inlined_jsframe_index_(0),
12015       function_(function),
12016       context_(function->context()),
12017       failed_(false) {
12018     if (function->IsBuiltin()) {
12019       context_ = Handle<Context>();
12020     }
12021   }
12022 
12023   // More scopes?
Done()12024   bool Done() {
12025     ASSERT(!failed_);
12026     return context_.is_null();
12027   }
12028 
Failed()12029   bool Failed() { return failed_; }
12030 
12031   // Move to the next scope.
Next()12032   void Next() {
12033     ASSERT(!failed_);
12034     ScopeType scope_type = Type();
12035     if (scope_type == ScopeTypeGlobal) {
12036       // The global scope is always the last in the chain.
12037       ASSERT(context_->IsNativeContext());
12038       context_ = Handle<Context>();
12039       return;
12040     }
12041     if (nested_scope_chain_.is_empty()) {
12042       context_ = Handle<Context>(context_->previous(), isolate_);
12043     } else {
12044       if (nested_scope_chain_.last()->HasContext()) {
12045         ASSERT(context_->previous() != NULL);
12046         context_ = Handle<Context>(context_->previous(), isolate_);
12047       }
12048       nested_scope_chain_.RemoveLast();
12049     }
12050   }
12051 
12052   // Return the type of the current scope.
Type()12053   ScopeType Type() {
12054     ASSERT(!failed_);
12055     if (!nested_scope_chain_.is_empty()) {
12056       Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
12057       switch (scope_info->scope_type()) {
12058         case FUNCTION_SCOPE:
12059           ASSERT(context_->IsFunctionContext() ||
12060                  !scope_info->HasContext());
12061           return ScopeTypeLocal;
12062         case MODULE_SCOPE:
12063           ASSERT(context_->IsModuleContext());
12064           return ScopeTypeModule;
12065         case GLOBAL_SCOPE:
12066           ASSERT(context_->IsNativeContext());
12067           return ScopeTypeGlobal;
12068         case WITH_SCOPE:
12069           ASSERT(context_->IsWithContext());
12070           return ScopeTypeWith;
12071         case CATCH_SCOPE:
12072           ASSERT(context_->IsCatchContext());
12073           return ScopeTypeCatch;
12074         case BLOCK_SCOPE:
12075           ASSERT(!scope_info->HasContext() ||
12076                  context_->IsBlockContext());
12077           return ScopeTypeBlock;
12078         case EVAL_SCOPE:
12079           UNREACHABLE();
12080       }
12081     }
12082     if (context_->IsNativeContext()) {
12083       ASSERT(context_->global_object()->IsGlobalObject());
12084       return ScopeTypeGlobal;
12085     }
12086     if (context_->IsFunctionContext()) {
12087       return ScopeTypeClosure;
12088     }
12089     if (context_->IsCatchContext()) {
12090       return ScopeTypeCatch;
12091     }
12092     if (context_->IsBlockContext()) {
12093       return ScopeTypeBlock;
12094     }
12095     if (context_->IsModuleContext()) {
12096       return ScopeTypeModule;
12097     }
12098     ASSERT(context_->IsWithContext());
12099     return ScopeTypeWith;
12100   }
12101 
12102   // Return the JavaScript object with the content of the current scope.
ScopeObject()12103   MaybeHandle<JSObject> ScopeObject() {
12104     ASSERT(!failed_);
12105     switch (Type()) {
12106       case ScopeIterator::ScopeTypeGlobal:
12107         return Handle<JSObject>(CurrentContext()->global_object());
12108       case ScopeIterator::ScopeTypeLocal:
12109         // Materialize the content of the local scope into a JSObject.
12110         ASSERT(nested_scope_chain_.length() == 1);
12111         return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
12112       case ScopeIterator::ScopeTypeWith:
12113         // Return the with object.
12114         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
12115       case ScopeIterator::ScopeTypeCatch:
12116         return MaterializeCatchScope(isolate_, CurrentContext());
12117       case ScopeIterator::ScopeTypeClosure:
12118         // Materialize the content of the closure scope into a JSObject.
12119         return MaterializeClosure(isolate_, CurrentContext());
12120       case ScopeIterator::ScopeTypeBlock:
12121         return MaterializeBlockScope(isolate_, CurrentContext());
12122       case ScopeIterator::ScopeTypeModule:
12123         return MaterializeModuleScope(isolate_, CurrentContext());
12124     }
12125     UNREACHABLE();
12126     return Handle<JSObject>();
12127   }
12128 
SetVariableValue(Handle<String> variable_name,Handle<Object> new_value)12129   bool SetVariableValue(Handle<String> variable_name,
12130                         Handle<Object> new_value) {
12131     ASSERT(!failed_);
12132     switch (Type()) {
12133       case ScopeIterator::ScopeTypeGlobal:
12134         break;
12135       case ScopeIterator::ScopeTypeLocal:
12136         return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
12137             variable_name, new_value);
12138       case ScopeIterator::ScopeTypeWith:
12139         break;
12140       case ScopeIterator::ScopeTypeCatch:
12141         return SetCatchVariableValue(isolate_, CurrentContext(),
12142             variable_name, new_value);
12143       case ScopeIterator::ScopeTypeClosure:
12144         return SetClosureVariableValue(isolate_, CurrentContext(),
12145             variable_name, new_value);
12146       case ScopeIterator::ScopeTypeBlock:
12147         // TODO(2399): should we implement it?
12148         break;
12149       case ScopeIterator::ScopeTypeModule:
12150         // TODO(2399): should we implement it?
12151         break;
12152     }
12153     return false;
12154   }
12155 
CurrentScopeInfo()12156   Handle<ScopeInfo> CurrentScopeInfo() {
12157     ASSERT(!failed_);
12158     if (!nested_scope_chain_.is_empty()) {
12159       return nested_scope_chain_.last();
12160     } else if (context_->IsBlockContext()) {
12161       return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
12162     } else if (context_->IsFunctionContext()) {
12163       return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
12164     }
12165     return Handle<ScopeInfo>::null();
12166   }
12167 
12168   // Return the context for this scope. For the local context there might not
12169   // be an actual context.
CurrentContext()12170   Handle<Context> CurrentContext() {
12171     ASSERT(!failed_);
12172     if (Type() == ScopeTypeGlobal ||
12173         nested_scope_chain_.is_empty()) {
12174       return context_;
12175     } else if (nested_scope_chain_.last()->HasContext()) {
12176       return context_;
12177     } else {
12178       return Handle<Context>();
12179     }
12180   }
12181 
12182 #ifdef DEBUG
12183   // Debug print of the content of the current scope.
DebugPrint()12184   void DebugPrint() {
12185     ASSERT(!failed_);
12186     switch (Type()) {
12187       case ScopeIterator::ScopeTypeGlobal:
12188         PrintF("Global:\n");
12189         CurrentContext()->Print();
12190         break;
12191 
12192       case ScopeIterator::ScopeTypeLocal: {
12193         PrintF("Local:\n");
12194         function_->shared()->scope_info()->Print();
12195         if (!CurrentContext().is_null()) {
12196           CurrentContext()->Print();
12197           if (CurrentContext()->has_extension()) {
12198             Handle<Object> extension(CurrentContext()->extension(), isolate_);
12199             if (extension->IsJSContextExtensionObject()) {
12200               extension->Print();
12201             }
12202           }
12203         }
12204         break;
12205       }
12206 
12207       case ScopeIterator::ScopeTypeWith:
12208         PrintF("With:\n");
12209         CurrentContext()->extension()->Print();
12210         break;
12211 
12212       case ScopeIterator::ScopeTypeCatch:
12213         PrintF("Catch:\n");
12214         CurrentContext()->extension()->Print();
12215         CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
12216         break;
12217 
12218       case ScopeIterator::ScopeTypeClosure:
12219         PrintF("Closure:\n");
12220         CurrentContext()->Print();
12221         if (CurrentContext()->has_extension()) {
12222           Handle<Object> extension(CurrentContext()->extension(), isolate_);
12223           if (extension->IsJSContextExtensionObject()) {
12224             extension->Print();
12225           }
12226         }
12227         break;
12228 
12229       default:
12230         UNREACHABLE();
12231     }
12232     PrintF("\n");
12233   }
12234 #endif
12235 
12236  private:
12237   Isolate* isolate_;
12238   JavaScriptFrame* frame_;
12239   int inlined_jsframe_index_;
12240   Handle<JSFunction> function_;
12241   Handle<Context> context_;
12242   List<Handle<ScopeInfo> > nested_scope_chain_;
12243   bool failed_;
12244 
RetrieveScopeChain(Scope * scope,Handle<SharedFunctionInfo> shared_info)12245   void RetrieveScopeChain(Scope* scope,
12246                           Handle<SharedFunctionInfo> shared_info) {
12247     if (scope != NULL) {
12248       int source_position = shared_info->code()->SourcePosition(frame_->pc());
12249       scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
12250     } else {
12251       // A failed reparse indicates that the preparser has diverged from the
12252       // parser or that the preparse data given to the initial parse has been
12253       // faulty. We fail in debug mode but in release mode we only provide the
12254       // information we get from the context chain but nothing about
12255       // completely stack allocated scopes or stack allocated locals.
12256       // Or it could be due to stack overflow.
12257       ASSERT(isolate_->has_pending_exception());
12258       failed_ = true;
12259     }
12260   }
12261 
12262   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
12263 };
12264 
12265 
RUNTIME_FUNCTION(Runtime_GetScopeCount)12266 RUNTIME_FUNCTION(Runtime_GetScopeCount) {
12267   HandleScope scope(isolate);
12268   ASSERT(args.length() == 2);
12269   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12270   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12271 
12272   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12273 
12274   // Get the frame where the debugging is performed.
12275   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12276   JavaScriptFrameIterator it(isolate, id);
12277   JavaScriptFrame* frame = it.frame();
12278 
12279   // Count the visible scopes.
12280   int n = 0;
12281   for (ScopeIterator it(isolate, frame, 0);
12282        !it.Done();
12283        it.Next()) {
12284     n++;
12285   }
12286 
12287   return Smi::FromInt(n);
12288 }
12289 
12290 
12291 // Returns the list of step-in positions (text offset) in a function of the
12292 // stack frame in a range from the current debug break position to the end
12293 // of the corresponding statement.
RUNTIME_FUNCTION(Runtime_GetStepInPositions)12294 RUNTIME_FUNCTION(Runtime_GetStepInPositions) {
12295   HandleScope scope(isolate);
12296   ASSERT(args.length() == 2);
12297   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12298   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12299 
12300   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12301 
12302   // Get the frame where the debugging is performed.
12303   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12304   JavaScriptFrameIterator frame_it(isolate, id);
12305   RUNTIME_ASSERT(!frame_it.done());
12306 
12307   JavaScriptFrame* frame = frame_it.frame();
12308 
12309   Handle<JSFunction> fun =
12310       Handle<JSFunction>(frame->function());
12311   Handle<SharedFunctionInfo> shared =
12312       Handle<SharedFunctionInfo>(fun->shared());
12313 
12314   if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12315     return isolate->heap()->undefined_value();
12316   }
12317 
12318   Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12319 
12320   int len = 0;
12321   Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12322   // Find the break point where execution has stopped.
12323   BreakLocationIterator break_location_iterator(debug_info,
12324                                                 ALL_BREAK_LOCATIONS);
12325 
12326   break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12327   int current_statement_pos = break_location_iterator.statement_position();
12328 
12329   while (!break_location_iterator.Done()) {
12330     bool accept;
12331     if (break_location_iterator.pc() > frame->pc()) {
12332       accept = true;
12333     } else {
12334       StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
12335       // The break point is near our pc. Could be a step-in possibility,
12336       // that is currently taken by active debugger call.
12337       if (break_frame_id == StackFrame::NO_ID) {
12338         // We are not stepping.
12339         accept = false;
12340       } else {
12341         JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id);
12342         // If our frame is a top frame and we are stepping, we can do step-in
12343         // at this place.
12344         accept = additional_frame_it.frame()->id() == id;
12345       }
12346     }
12347     if (accept) {
12348       if (break_location_iterator.IsStepInLocation(isolate)) {
12349         Smi* position_value = Smi::FromInt(break_location_iterator.position());
12350         RETURN_FAILURE_ON_EXCEPTION(
12351             isolate,
12352             JSObject::SetElement(array, len,
12353                                  Handle<Object>(position_value, isolate),
12354                                  NONE, SLOPPY));
12355         len++;
12356       }
12357     }
12358     // Advance iterator.
12359     break_location_iterator.Next();
12360     if (current_statement_pos !=
12361         break_location_iterator.statement_position()) {
12362       break;
12363     }
12364   }
12365   return *array;
12366 }
12367 
12368 
12369 static const int kScopeDetailsTypeIndex = 0;
12370 static const int kScopeDetailsObjectIndex = 1;
12371 static const int kScopeDetailsSize = 2;
12372 
12373 
MaterializeScopeDetails(Isolate * isolate,ScopeIterator * it)12374 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeScopeDetails(
12375     Isolate* isolate,
12376     ScopeIterator* it) {
12377   // Calculate the size of the result.
12378   int details_size = kScopeDetailsSize;
12379   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12380 
12381   // Fill in scope details.
12382   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12383   Handle<JSObject> scope_object;
12384   ASSIGN_RETURN_ON_EXCEPTION(
12385       isolate, scope_object, it->ScopeObject(), JSObject);
12386   details->set(kScopeDetailsObjectIndex, *scope_object);
12387 
12388   return isolate->factory()->NewJSArrayWithElements(details);
12389 }
12390 
12391 
12392 // Return an array with scope details
12393 // args[0]: number: break id
12394 // args[1]: number: frame index
12395 // args[2]: number: inlined frame index
12396 // args[3]: number: scope index
12397 //
12398 // The array returned contains the following information:
12399 // 0: Scope type
12400 // 1: Scope object
RUNTIME_FUNCTION(Runtime_GetScopeDetails)12401 RUNTIME_FUNCTION(Runtime_GetScopeDetails) {
12402   HandleScope scope(isolate);
12403   ASSERT(args.length() == 4);
12404   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12405   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12406 
12407   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12408   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12409   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12410 
12411   // Get the frame where the debugging is performed.
12412   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12413   JavaScriptFrameIterator frame_it(isolate, id);
12414   JavaScriptFrame* frame = frame_it.frame();
12415 
12416   // Find the requested scope.
12417   int n = 0;
12418   ScopeIterator it(isolate, frame, inlined_jsframe_index);
12419   for (; !it.Done() && n < index; it.Next()) {
12420     n++;
12421   }
12422   if (it.Done()) {
12423     return isolate->heap()->undefined_value();
12424   }
12425   Handle<JSObject> details;
12426   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12427       isolate, details, MaterializeScopeDetails(isolate, &it));
12428   return *details;
12429 }
12430 
12431 
12432 // Return an array of scope details
12433 // args[0]: number: break id
12434 // args[1]: number: frame index
12435 // args[2]: number: inlined frame index
12436 // args[3]: boolean: ignore nested scopes
12437 //
12438 // The array returned contains arrays with the following information:
12439 // 0: Scope type
12440 // 1: Scope object
RUNTIME_FUNCTION(Runtime_GetAllScopesDetails)12441 RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
12442   HandleScope scope(isolate);
12443   ASSERT(args.length() == 3 || args.length() == 4);
12444   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12445   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12446 
12447   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12448   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12449 
12450   bool ignore_nested_scopes = false;
12451   if (args.length() == 4) {
12452     CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
12453     ignore_nested_scopes = flag;
12454   }
12455 
12456   // Get the frame where the debugging is performed.
12457   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12458   JavaScriptFrameIterator frame_it(isolate, id);
12459   JavaScriptFrame* frame = frame_it.frame();
12460 
12461   List<Handle<JSObject> > result(4);
12462   ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes);
12463   for (; !it.Done(); it.Next()) {
12464     Handle<JSObject> details;
12465     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12466         isolate, details, MaterializeScopeDetails(isolate, &it));
12467     result.Add(details);
12468   }
12469 
12470   Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
12471   for (int i = 0; i < result.length(); ++i) {
12472     array->set(i, *result[i]);
12473   }
12474   return *isolate->factory()->NewJSArrayWithElements(array);
12475 }
12476 
12477 
RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount)12478 RUNTIME_FUNCTION(Runtime_GetFunctionScopeCount) {
12479   HandleScope scope(isolate);
12480   ASSERT(args.length() == 1);
12481 
12482   // Check arguments.
12483   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12484 
12485   // Count the visible scopes.
12486   int n = 0;
12487   for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12488     n++;
12489   }
12490 
12491   return Smi::FromInt(n);
12492 }
12493 
12494 
RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails)12495 RUNTIME_FUNCTION(Runtime_GetFunctionScopeDetails) {
12496   HandleScope scope(isolate);
12497   ASSERT(args.length() == 2);
12498 
12499   // Check arguments.
12500   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12501   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12502 
12503   // Find the requested scope.
12504   int n = 0;
12505   ScopeIterator it(isolate, fun);
12506   for (; !it.Done() && n < index; it.Next()) {
12507     n++;
12508   }
12509   if (it.Done()) {
12510     return isolate->heap()->undefined_value();
12511   }
12512 
12513   Handle<JSObject> details;
12514   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12515       isolate, details, MaterializeScopeDetails(isolate, &it));
12516   return *details;
12517 }
12518 
12519 
SetScopeVariableValue(ScopeIterator * it,int index,Handle<String> variable_name,Handle<Object> new_value)12520 static bool SetScopeVariableValue(ScopeIterator* it, int index,
12521                                   Handle<String> variable_name,
12522                                   Handle<Object> new_value) {
12523   for (int n = 0; !it->Done() && n < index; it->Next()) {
12524     n++;
12525   }
12526   if (it->Done()) {
12527     return false;
12528   }
12529   return it->SetVariableValue(variable_name, new_value);
12530 }
12531 
12532 
12533 // Change variable value in closure or local scope
12534 // args[0]: number or JsFunction: break id or function
12535 // args[1]: number: frame index (when arg[0] is break id)
12536 // args[2]: number: inlined frame index (when arg[0] is break id)
12537 // args[3]: number: scope index
12538 // args[4]: string: variable name
12539 // args[5]: object: new value
12540 //
12541 // Return true if success and false otherwise
RUNTIME_FUNCTION(Runtime_SetScopeVariableValue)12542 RUNTIME_FUNCTION(Runtime_SetScopeVariableValue) {
12543   HandleScope scope(isolate);
12544   ASSERT(args.length() == 6);
12545 
12546   // Check arguments.
12547   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12548   CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12549   CONVERT_ARG_HANDLE_CHECKED(Object, new_value, 5);
12550 
12551   bool res;
12552   if (args[0]->IsNumber()) {
12553     CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12554     RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12555 
12556     CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12557     CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12558 
12559     // Get the frame where the debugging is performed.
12560     StackFrame::Id id = UnwrapFrameId(wrapped_id);
12561     JavaScriptFrameIterator frame_it(isolate, id);
12562     JavaScriptFrame* frame = frame_it.frame();
12563 
12564     ScopeIterator it(isolate, frame, inlined_jsframe_index);
12565     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12566   } else {
12567     CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12568     ScopeIterator it(isolate, fun);
12569     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12570   }
12571 
12572   return isolate->heap()->ToBoolean(res);
12573 }
12574 
12575 
RUNTIME_FUNCTION(Runtime_DebugPrintScopes)12576 RUNTIME_FUNCTION(Runtime_DebugPrintScopes) {
12577   HandleScope scope(isolate);
12578   ASSERT(args.length() == 0);
12579 
12580 #ifdef DEBUG
12581   // Print the scopes for the top frame.
12582   StackFrameLocator locator(isolate);
12583   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12584   for (ScopeIterator it(isolate, frame, 0);
12585        !it.Done();
12586        it.Next()) {
12587     it.DebugPrint();
12588   }
12589 #endif
12590   return isolate->heap()->undefined_value();
12591 }
12592 
12593 
RUNTIME_FUNCTION(Runtime_GetThreadCount)12594 RUNTIME_FUNCTION(Runtime_GetThreadCount) {
12595   HandleScope scope(isolate);
12596   ASSERT(args.length() == 1);
12597   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12598   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12599 
12600   // Count all archived V8 threads.
12601   int n = 0;
12602   for (ThreadState* thread =
12603           isolate->thread_manager()->FirstThreadStateInUse();
12604        thread != NULL;
12605        thread = thread->Next()) {
12606     n++;
12607   }
12608 
12609   // Total number of threads is current thread and archived threads.
12610   return Smi::FromInt(n + 1);
12611 }
12612 
12613 
12614 static const int kThreadDetailsCurrentThreadIndex = 0;
12615 static const int kThreadDetailsThreadIdIndex = 1;
12616 static const int kThreadDetailsSize = 2;
12617 
12618 // Return an array with thread details
12619 // args[0]: number: break id
12620 // args[1]: number: thread index
12621 //
12622 // The array returned contains the following information:
12623 // 0: Is current thread?
12624 // 1: Thread id
RUNTIME_FUNCTION(Runtime_GetThreadDetails)12625 RUNTIME_FUNCTION(Runtime_GetThreadDetails) {
12626   HandleScope scope(isolate);
12627   ASSERT(args.length() == 2);
12628   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12629   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12630 
12631   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12632 
12633   // Allocate array for result.
12634   Handle<FixedArray> details =
12635       isolate->factory()->NewFixedArray(kThreadDetailsSize);
12636 
12637   // Thread index 0 is current thread.
12638   if (index == 0) {
12639     // Fill the details.
12640     details->set(kThreadDetailsCurrentThreadIndex,
12641                  isolate->heap()->true_value());
12642     details->set(kThreadDetailsThreadIdIndex,
12643                  Smi::FromInt(ThreadId::Current().ToInteger()));
12644   } else {
12645     // Find the thread with the requested index.
12646     int n = 1;
12647     ThreadState* thread =
12648         isolate->thread_manager()->FirstThreadStateInUse();
12649     while (index != n && thread != NULL) {
12650       thread = thread->Next();
12651       n++;
12652     }
12653     if (thread == NULL) {
12654       return isolate->heap()->undefined_value();
12655     }
12656 
12657     // Fill the details.
12658     details->set(kThreadDetailsCurrentThreadIndex,
12659                  isolate->heap()->false_value());
12660     details->set(kThreadDetailsThreadIdIndex,
12661                  Smi::FromInt(thread->id().ToInteger()));
12662   }
12663 
12664   // Convert to JS array and return.
12665   return *isolate->factory()->NewJSArrayWithElements(details);
12666 }
12667 
12668 
12669 // Sets the disable break state
12670 // args[0]: disable break state
RUNTIME_FUNCTION(Runtime_SetDisableBreak)12671 RUNTIME_FUNCTION(Runtime_SetDisableBreak) {
12672   HandleScope scope(isolate);
12673   ASSERT(args.length() == 1);
12674   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12675   isolate->debug()->set_disable_break(disable_break);
12676   return  isolate->heap()->undefined_value();
12677 }
12678 
12679 
IsPositionAlignmentCodeCorrect(int alignment)12680 static bool IsPositionAlignmentCodeCorrect(int alignment) {
12681   return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12682 }
12683 
12684 
RUNTIME_FUNCTION(Runtime_GetBreakLocations)12685 RUNTIME_FUNCTION(Runtime_GetBreakLocations) {
12686   HandleScope scope(isolate);
12687   ASSERT(args.length() == 2);
12688 
12689   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12690   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12691 
12692   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12693     return isolate->ThrowIllegalOperation();
12694   }
12695   BreakPositionAlignment alignment =
12696       static_cast<BreakPositionAlignment>(statement_aligned_code);
12697 
12698   Handle<SharedFunctionInfo> shared(fun->shared());
12699   // Find the number of break points
12700   Handle<Object> break_locations =
12701       Debug::GetSourceBreakLocations(shared, alignment);
12702   if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12703   // Return array as JS array
12704   return *isolate->factory()->NewJSArrayWithElements(
12705       Handle<FixedArray>::cast(break_locations));
12706 }
12707 
12708 
12709 // Set a break point in a function.
12710 // args[0]: function
12711 // args[1]: number: break source position (within the function source)
12712 // args[2]: number: break point object
RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint)12713 RUNTIME_FUNCTION(Runtime_SetFunctionBreakPoint) {
12714   HandleScope scope(isolate);
12715   ASSERT(args.length() == 3);
12716   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12717   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12718   RUNTIME_ASSERT(source_position >= function->shared()->start_position() &&
12719                  source_position <= function->shared()->end_position());
12720   CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 2);
12721 
12722   // Set break point.
12723   RUNTIME_ASSERT(isolate->debug()->SetBreakPoint(
12724       function, break_point_object_arg, &source_position));
12725 
12726   return Smi::FromInt(source_position);
12727 }
12728 
12729 
12730 // Changes the state of a break point in a script and returns source position
12731 // where break point was set. NOTE: Regarding performance see the NOTE for
12732 // GetScriptFromScriptData.
12733 // args[0]: script to set break point in
12734 // args[1]: number: break source position (within the script source)
12735 // args[2]: number, breakpoint position alignment
12736 // args[3]: number: break point object
RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint)12737 RUNTIME_FUNCTION(Runtime_SetScriptBreakPoint) {
12738   HandleScope scope(isolate);
12739   ASSERT(args.length() == 4);
12740   CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12741   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12742   RUNTIME_ASSERT(source_position >= 0);
12743   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12744   CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 3);
12745 
12746   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12747     return isolate->ThrowIllegalOperation();
12748   }
12749   BreakPositionAlignment alignment =
12750       static_cast<BreakPositionAlignment>(statement_aligned_code);
12751 
12752   // Get the script from the script wrapper.
12753   RUNTIME_ASSERT(wrapper->value()->IsScript());
12754   Handle<Script> script(Script::cast(wrapper->value()));
12755 
12756   // Set break point.
12757   if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12758                                                 &source_position,
12759                                                 alignment)) {
12760     return isolate->heap()->undefined_value();
12761   }
12762 
12763   return Smi::FromInt(source_position);
12764 }
12765 
12766 
12767 // Clear a break point
12768 // args[0]: number: break point object
RUNTIME_FUNCTION(Runtime_ClearBreakPoint)12769 RUNTIME_FUNCTION(Runtime_ClearBreakPoint) {
12770   HandleScope scope(isolate);
12771   ASSERT(args.length() == 1);
12772   CONVERT_ARG_HANDLE_CHECKED(Object, break_point_object_arg, 0);
12773 
12774   // Clear break point.
12775   isolate->debug()->ClearBreakPoint(break_point_object_arg);
12776 
12777   return isolate->heap()->undefined_value();
12778 }
12779 
12780 
12781 // Change the state of break on exceptions.
12782 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12783 // args[1]: Boolean indicating on/off.
RUNTIME_FUNCTION(Runtime_ChangeBreakOnException)12784 RUNTIME_FUNCTION(Runtime_ChangeBreakOnException) {
12785   HandleScope scope(isolate);
12786   ASSERT(args.length() == 2);
12787   CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
12788   CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12789 
12790   // If the number doesn't match an enum value, the ChangeBreakOnException
12791   // function will default to affecting caught exceptions.
12792   ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
12793   // Update break point state.
12794   isolate->debug()->ChangeBreakOnException(type, enable);
12795   return isolate->heap()->undefined_value();
12796 }
12797 
12798 
12799 // Returns the state of break on exceptions
12800 // args[0]: boolean indicating uncaught exceptions
RUNTIME_FUNCTION(Runtime_IsBreakOnException)12801 RUNTIME_FUNCTION(Runtime_IsBreakOnException) {
12802   HandleScope scope(isolate);
12803   ASSERT(args.length() == 1);
12804   CONVERT_NUMBER_CHECKED(uint32_t, type_arg, Uint32, args[0]);
12805 
12806   ExceptionBreakType type = static_cast<ExceptionBreakType>(type_arg);
12807   bool result = isolate->debug()->IsBreakOnException(type);
12808   return Smi::FromInt(result);
12809 }
12810 
12811 
12812 // Prepare for stepping
12813 // args[0]: break id for checking execution state
12814 // args[1]: step action from the enumeration StepAction
12815 // args[2]: number of times to perform the step, for step out it is the number
12816 //          of frames to step down.
RUNTIME_FUNCTION(Runtime_PrepareStep)12817 RUNTIME_FUNCTION(Runtime_PrepareStep) {
12818   HandleScope scope(isolate);
12819   ASSERT(args.length() == 4);
12820   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12821   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12822 
12823   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12824     return isolate->Throw(isolate->heap()->illegal_argument_string());
12825   }
12826 
12827   CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]);
12828 
12829   StackFrame::Id frame_id;
12830   if (wrapped_frame_id == 0) {
12831     frame_id = StackFrame::NO_ID;
12832   } else {
12833     frame_id = UnwrapFrameId(wrapped_frame_id);
12834   }
12835 
12836   // Get the step action and check validity.
12837   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12838   if (step_action != StepIn &&
12839       step_action != StepNext &&
12840       step_action != StepOut &&
12841       step_action != StepInMin &&
12842       step_action != StepMin) {
12843     return isolate->Throw(isolate->heap()->illegal_argument_string());
12844   }
12845 
12846   if (frame_id != StackFrame::NO_ID && step_action != StepNext &&
12847       step_action != StepMin && step_action != StepOut) {
12848     return isolate->ThrowIllegalOperation();
12849   }
12850 
12851   // Get the number of steps.
12852   int step_count = NumberToInt32(args[2]);
12853   if (step_count < 1) {
12854     return isolate->Throw(isolate->heap()->illegal_argument_string());
12855   }
12856 
12857   // Clear all current stepping setup.
12858   isolate->debug()->ClearStepping();
12859 
12860   // Prepare step.
12861   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12862                                 step_count,
12863                                 frame_id);
12864   return isolate->heap()->undefined_value();
12865 }
12866 
12867 
12868 // Clear all stepping set by PrepareStep.
RUNTIME_FUNCTION(Runtime_ClearStepping)12869 RUNTIME_FUNCTION(Runtime_ClearStepping) {
12870   HandleScope scope(isolate);
12871   ASSERT(args.length() == 0);
12872   isolate->debug()->ClearStepping();
12873   return isolate->heap()->undefined_value();
12874 }
12875 
12876 
12877 // Helper function to find or create the arguments object for
12878 // Runtime_DebugEvaluate.
MaterializeArgumentsObject(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function)12879 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject(
12880     Isolate* isolate,
12881     Handle<JSObject> target,
12882     Handle<JSFunction> function) {
12883   // Do not materialize the arguments object for eval or top-level code.
12884   // Skip if "arguments" is already taken.
12885   if (!function->shared()->is_function() ||
12886       JSReceiver::HasOwnProperty(
12887           target, isolate->factory()->arguments_string())) {
12888     return target;
12889   }
12890 
12891   // FunctionGetArguments can't throw an exception.
12892   Handle<JSObject> arguments = Handle<JSObject>::cast(
12893       Accessors::FunctionGetArguments(function));
12894   Handle<String> arguments_str = isolate->factory()->arguments_string();
12895   RETURN_ON_EXCEPTION(
12896       isolate,
12897       Runtime::SetObjectProperty(
12898           isolate, target, arguments_str, arguments, ::NONE, SLOPPY),
12899       JSObject);
12900   return target;
12901 }
12902 
12903 
12904 // Compile and evaluate source for the given context.
DebugEvaluate(Isolate * isolate,Handle<Context> context,Handle<Object> context_extension,Handle<Object> receiver,Handle<String> source)12905 static MaybeHandle<Object> DebugEvaluate(Isolate* isolate,
12906                                          Handle<Context> context,
12907                                          Handle<Object> context_extension,
12908                                          Handle<Object> receiver,
12909                                          Handle<String> source) {
12910   if (context_extension->IsJSObject()) {
12911     Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12912     Handle<JSFunction> closure(context->closure(), isolate);
12913     context = isolate->factory()->NewWithContext(closure, context, extension);
12914   }
12915 
12916   Handle<JSFunction> eval_fun;
12917   ASSIGN_RETURN_ON_EXCEPTION(
12918       isolate, eval_fun,
12919       Compiler::GetFunctionFromEval(source,
12920                                     context,
12921                                     SLOPPY,
12922                                     NO_PARSE_RESTRICTION,
12923                                     RelocInfo::kNoPosition),
12924       Object);
12925 
12926   Handle<Object> result;
12927   ASSIGN_RETURN_ON_EXCEPTION(
12928       isolate, result,
12929       Execution::Call(isolate, eval_fun, receiver, 0, NULL),
12930       Object);
12931 
12932   // Skip the global proxy as it has no properties and always delegates to the
12933   // real global object.
12934   if (result->IsJSGlobalProxy()) {
12935     result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
12936   }
12937 
12938   // Clear the oneshot breakpoints so that the debugger does not step further.
12939   isolate->debug()->ClearStepping();
12940   return result;
12941 }
12942 
12943 
12944 // Evaluate a piece of JavaScript in the context of a stack frame for
12945 // debugging.  Things that need special attention are:
12946 // - Parameters and stack-allocated locals need to be materialized.  Altered
12947 //   values need to be written back to the stack afterwards.
12948 // - The arguments object needs to materialized.
RUNTIME_FUNCTION(Runtime_DebugEvaluate)12949 RUNTIME_FUNCTION(Runtime_DebugEvaluate) {
12950   HandleScope scope(isolate);
12951 
12952   // Check the execution state and decode arguments frame and source to be
12953   // evaluated.
12954   ASSERT(args.length() == 6);
12955   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
12956   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
12957 
12958   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12959   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12960   CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
12961   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
12962   CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 5);
12963 
12964   // Handle the processing of break.
12965   DisableBreak disable_break_scope(isolate->debug(), disable_break);
12966 
12967   // Get the frame where the debugging is performed.
12968   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12969   JavaScriptFrameIterator it(isolate, id);
12970   JavaScriptFrame* frame = it.frame();
12971   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12972   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12973 
12974   // Traverse the saved contexts chain to find the active context for the
12975   // selected frame.
12976   SaveContext* save = FindSavedContextForFrame(isolate, frame);
12977 
12978   SaveContext savex(isolate);
12979   isolate->set_context(*(save->context()));
12980 
12981   // Evaluate on the context of the frame.
12982   Handle<Context> context(Context::cast(frame->context()));
12983   ASSERT(!context.is_null());
12984 
12985   // Materialize stack locals and the arguments object.
12986   Handle<JSObject> materialized =
12987       isolate->factory()->NewJSObject(isolate->object_function());
12988 
12989   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12990       isolate, materialized,
12991       MaterializeStackLocalsWithFrameInspector(
12992           isolate, materialized, function, &frame_inspector));
12993 
12994   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
12995       isolate, materialized,
12996       MaterializeArgumentsObject(isolate, materialized, function));
12997 
12998   // Add the materialized object in a with-scope to shadow the stack locals.
12999   context = isolate->factory()->NewWithContext(function, context, materialized);
13000 
13001   Handle<Object> receiver(frame->receiver(), isolate);
13002   Handle<Object> result;
13003   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13004       isolate, result,
13005       DebugEvaluate(isolate, context, context_extension, receiver, source));
13006 
13007   // Write back potential changes to materialized stack locals to the stack.
13008   UpdateStackLocalsFromMaterializedObject(
13009       isolate, materialized, function, frame, inlined_jsframe_index);
13010 
13011   return *result;
13012 }
13013 
13014 
RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal)13015 RUNTIME_FUNCTION(Runtime_DebugEvaluateGlobal) {
13016   HandleScope scope(isolate);
13017 
13018   // Check the execution state and decode arguments frame and source to be
13019   // evaluated.
13020   ASSERT(args.length() == 4);
13021   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
13022   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
13023 
13024   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13025   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
13026   CONVERT_ARG_HANDLE_CHECKED(Object, context_extension, 3);
13027 
13028   // Handle the processing of break.
13029   DisableBreak disable_break_scope(isolate->debug(), disable_break);
13030 
13031   // Enter the top context from before the debugger was invoked.
13032   SaveContext save(isolate);
13033   SaveContext* top = &save;
13034   while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
13035     top = top->prev();
13036   }
13037   if (top != NULL) {
13038     isolate->set_context(*top->context());
13039   }
13040 
13041   // Get the native context now set to the top context from before the
13042   // debugger was invoked.
13043   Handle<Context> context = isolate->native_context();
13044   Handle<Object> receiver = isolate->global_object();
13045   Handle<Object> result;
13046   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13047       isolate, result,
13048       DebugEvaluate(isolate, context, context_extension, receiver, source));
13049   return *result;
13050 }
13051 
13052 
RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts)13053 RUNTIME_FUNCTION(Runtime_DebugGetLoadedScripts) {
13054   HandleScope scope(isolate);
13055   ASSERT(args.length() == 0);
13056 
13057   // Fill the script objects.
13058   Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
13059 
13060   // Convert the script objects to proper JS objects.
13061   for (int i = 0; i < instances->length(); i++) {
13062     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
13063     // Get the script wrapper in a local handle before calling GetScriptWrapper,
13064     // because using
13065     //   instances->set(i, *GetScriptWrapper(script))
13066     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
13067     // already have dereferenced the instances handle.
13068     Handle<JSObject> wrapper = Script::GetWrapper(script);
13069     instances->set(i, *wrapper);
13070   }
13071 
13072   // Return result as a JS array.
13073   Handle<JSObject> result =
13074       isolate->factory()->NewJSObject(isolate->array_function());
13075   JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13076   return *result;
13077 }
13078 
13079 
13080 // Helper function used by Runtime_DebugReferencedBy below.
DebugReferencedBy(HeapIterator * iterator,JSObject * target,Object * instance_filter,int max_references,FixedArray * instances,int instances_size,JSFunction * arguments_function)13081 static int DebugReferencedBy(HeapIterator* iterator,
13082                              JSObject* target,
13083                              Object* instance_filter, int max_references,
13084                              FixedArray* instances, int instances_size,
13085                              JSFunction* arguments_function) {
13086   Isolate* isolate = target->GetIsolate();
13087   SealHandleScope shs(isolate);
13088   DisallowHeapAllocation no_allocation;
13089 
13090   // Iterate the heap.
13091   int count = 0;
13092   JSObject* last = NULL;
13093   HeapObject* heap_obj = NULL;
13094   while (((heap_obj = iterator->next()) != NULL) &&
13095          (max_references == 0 || count < max_references)) {
13096     // Only look at all JSObjects.
13097     if (heap_obj->IsJSObject()) {
13098       // Skip context extension objects and argument arrays as these are
13099       // checked in the context of functions using them.
13100       JSObject* obj = JSObject::cast(heap_obj);
13101       if (obj->IsJSContextExtensionObject() ||
13102           obj->map()->constructor() == arguments_function) {
13103         continue;
13104       }
13105 
13106       // Check if the JS object has a reference to the object looked for.
13107       if (obj->ReferencesObject(target)) {
13108         // Check instance filter if supplied. This is normally used to avoid
13109         // references from mirror objects (see Runtime_IsInPrototypeChain).
13110         if (!instance_filter->IsUndefined()) {
13111           Object* V = obj;
13112           while (true) {
13113             Object* prototype = V->GetPrototype(isolate);
13114             if (prototype->IsNull()) {
13115               break;
13116             }
13117             if (instance_filter == prototype) {
13118               obj = NULL;  // Don't add this object.
13119               break;
13120             }
13121             V = prototype;
13122           }
13123         }
13124 
13125         if (obj != NULL) {
13126           // Valid reference found add to instance array if supplied an update
13127           // count.
13128           if (instances != NULL && count < instances_size) {
13129             instances->set(count, obj);
13130           }
13131           last = obj;
13132           count++;
13133         }
13134       }
13135     }
13136   }
13137 
13138   // Check for circular reference only. This can happen when the object is only
13139   // referenced from mirrors and has a circular reference in which case the
13140   // object is not really alive and would have been garbage collected if not
13141   // referenced from the mirror.
13142   if (count == 1 && last == target) {
13143     count = 0;
13144   }
13145 
13146   // Return the number of referencing objects found.
13147   return count;
13148 }
13149 
13150 
13151 // Scan the heap for objects with direct references to an object
13152 // args[0]: the object to find references to
13153 // args[1]: constructor function for instances to exclude (Mirror)
13154 // args[2]: the the maximum number of objects to return
RUNTIME_FUNCTION(Runtime_DebugReferencedBy)13155 RUNTIME_FUNCTION(Runtime_DebugReferencedBy) {
13156   HandleScope scope(isolate);
13157   ASSERT(args.length() == 3);
13158 
13159   // Check parameters.
13160   CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
13161   CONVERT_ARG_HANDLE_CHECKED(Object, instance_filter, 1);
13162   RUNTIME_ASSERT(instance_filter->IsUndefined() ||
13163                  instance_filter->IsJSObject());
13164   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
13165   RUNTIME_ASSERT(max_references >= 0);
13166 
13167 
13168   // Get the constructor function for context extension and arguments array.
13169   Handle<JSObject> arguments_boilerplate(
13170       isolate->context()->native_context()->sloppy_arguments_boilerplate());
13171   Handle<JSFunction> arguments_function(
13172       JSFunction::cast(arguments_boilerplate->map()->constructor()));
13173 
13174   // Get the number of referencing objects.
13175   int count;
13176   // First perform a full GC in order to avoid dead objects and to make the heap
13177   // iterable.
13178   Heap* heap = isolate->heap();
13179   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13180   {
13181     HeapIterator heap_iterator(heap);
13182     count = DebugReferencedBy(&heap_iterator,
13183                               *target, *instance_filter, max_references,
13184                               NULL, 0, *arguments_function);
13185   }
13186 
13187   // Allocate an array to hold the result.
13188   Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13189 
13190   // Fill the referencing objects.
13191   {
13192     HeapIterator heap_iterator(heap);
13193     count = DebugReferencedBy(&heap_iterator,
13194                               *target, *instance_filter, max_references,
13195                               *instances, count, *arguments_function);
13196   }
13197 
13198   // Return result as JS array.
13199   Handle<JSFunction> constructor(
13200       isolate->context()->native_context()->array_function());
13201 
13202   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
13203   JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13204   return *result;
13205 }
13206 
13207 
13208 // Helper function used by Runtime_DebugConstructedBy below.
DebugConstructedBy(HeapIterator * iterator,JSFunction * constructor,int max_references,FixedArray * instances,int instances_size)13209 static int DebugConstructedBy(HeapIterator* iterator,
13210                               JSFunction* constructor,
13211                               int max_references,
13212                               FixedArray* instances,
13213                               int instances_size) {
13214   DisallowHeapAllocation no_allocation;
13215 
13216   // Iterate the heap.
13217   int count = 0;
13218   HeapObject* heap_obj = NULL;
13219   while (((heap_obj = iterator->next()) != NULL) &&
13220          (max_references == 0 || count < max_references)) {
13221     // Only look at all JSObjects.
13222     if (heap_obj->IsJSObject()) {
13223       JSObject* obj = JSObject::cast(heap_obj);
13224       if (obj->map()->constructor() == constructor) {
13225         // Valid reference found add to instance array if supplied an update
13226         // count.
13227         if (instances != NULL && count < instances_size) {
13228           instances->set(count, obj);
13229         }
13230         count++;
13231       }
13232     }
13233   }
13234 
13235   // Return the number of referencing objects found.
13236   return count;
13237 }
13238 
13239 
13240 // Scan the heap for objects constructed by a specific function.
13241 // args[0]: the constructor to find instances of
13242 // args[1]: the the maximum number of objects to return
RUNTIME_FUNCTION(Runtime_DebugConstructedBy)13243 RUNTIME_FUNCTION(Runtime_DebugConstructedBy) {
13244   HandleScope scope(isolate);
13245   ASSERT(args.length() == 2);
13246 
13247 
13248   // Check parameters.
13249   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
13250   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
13251   RUNTIME_ASSERT(max_references >= 0);
13252 
13253   // Get the number of referencing objects.
13254   int count;
13255   // First perform a full GC in order to avoid dead objects and to make the heap
13256   // iterable.
13257   Heap* heap = isolate->heap();
13258   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13259   {
13260     HeapIterator heap_iterator(heap);
13261     count = DebugConstructedBy(&heap_iterator,
13262                                *constructor,
13263                                max_references,
13264                                NULL,
13265                                0);
13266   }
13267 
13268   // Allocate an array to hold the result.
13269   Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13270 
13271   // Fill the referencing objects.
13272   {
13273     HeapIterator heap_iterator2(heap);
13274     count = DebugConstructedBy(&heap_iterator2,
13275                                *constructor,
13276                                max_references,
13277                                *instances,
13278                                count);
13279   }
13280 
13281   // Return result as JS array.
13282   Handle<JSFunction> array_function(
13283       isolate->context()->native_context()->array_function());
13284   Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
13285   JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13286   return *result;
13287 }
13288 
13289 
13290 // Find the effective prototype object as returned by __proto__.
13291 // args[0]: the object to find the prototype for.
RUNTIME_FUNCTION(Runtime_DebugGetPrototype)13292 RUNTIME_FUNCTION(Runtime_DebugGetPrototype) {
13293   HandleScope shs(isolate);
13294   ASSERT(args.length() == 1);
13295   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
13296   return *GetPrototypeSkipHiddenPrototypes(isolate, obj);
13297 }
13298 
13299 
13300 // Patches script source (should be called upon BeforeCompile event).
RUNTIME_FUNCTION(Runtime_DebugSetScriptSource)13301 RUNTIME_FUNCTION(Runtime_DebugSetScriptSource) {
13302   HandleScope scope(isolate);
13303   ASSERT(args.length() == 2);
13304 
13305   CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
13306   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13307 
13308   RUNTIME_ASSERT(script_wrapper->value()->IsScript());
13309   Handle<Script> script(Script::cast(script_wrapper->value()));
13310 
13311   int compilation_state = script->compilation_state();
13312   RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
13313   script->set_source(*source);
13314 
13315   return isolate->heap()->undefined_value();
13316 }
13317 
13318 
RUNTIME_FUNCTION(Runtime_SystemBreak)13319 RUNTIME_FUNCTION(Runtime_SystemBreak) {
13320   SealHandleScope shs(isolate);
13321   ASSERT(args.length() == 0);
13322   OS::DebugBreak();
13323   return isolate->heap()->undefined_value();
13324 }
13325 
13326 
RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction)13327 RUNTIME_FUNCTION(Runtime_DebugDisassembleFunction) {
13328   HandleScope scope(isolate);
13329 #ifdef DEBUG
13330   ASSERT(args.length() == 1);
13331   // Get the function and make sure it is compiled.
13332   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13333   if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
13334     return isolate->heap()->exception();
13335   }
13336   func->code()->PrintLn();
13337 #endif  // DEBUG
13338   return isolate->heap()->undefined_value();
13339 }
13340 
13341 
RUNTIME_FUNCTION(Runtime_DebugDisassembleConstructor)13342 RUNTIME_FUNCTION(Runtime_DebugDisassembleConstructor) {
13343   HandleScope scope(isolate);
13344 #ifdef DEBUG
13345   ASSERT(args.length() == 1);
13346   // Get the function and make sure it is compiled.
13347   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13348   if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
13349     return isolate->heap()->exception();
13350   }
13351   func->shared()->construct_stub()->PrintLn();
13352 #endif  // DEBUG
13353   return isolate->heap()->undefined_value();
13354 }
13355 
13356 
RUNTIME_FUNCTION(Runtime_FunctionGetInferredName)13357 RUNTIME_FUNCTION(Runtime_FunctionGetInferredName) {
13358   SealHandleScope shs(isolate);
13359   ASSERT(args.length() == 1);
13360 
13361   CONVERT_ARG_CHECKED(JSFunction, f, 0);
13362   return f->shared()->inferred_name();
13363 }
13364 
13365 
FindSharedFunctionInfosForScript(HeapIterator * iterator,Script * script,FixedArray * buffer)13366 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13367                                             Script* script,
13368                                             FixedArray* buffer) {
13369   DisallowHeapAllocation no_allocation;
13370   int counter = 0;
13371   int buffer_size = buffer->length();
13372   for (HeapObject* obj = iterator->next();
13373        obj != NULL;
13374        obj = iterator->next()) {
13375     ASSERT(obj != NULL);
13376     if (!obj->IsSharedFunctionInfo()) {
13377       continue;
13378     }
13379     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13380     if (shared->script() != script) {
13381       continue;
13382     }
13383     if (counter < buffer_size) {
13384       buffer->set(counter, shared);
13385     }
13386     counter++;
13387   }
13388   return counter;
13389 }
13390 
13391 
13392 // For a script finds all SharedFunctionInfo's in the heap that points
13393 // to this script. Returns JSArray of SharedFunctionInfo wrapped
13394 // in OpaqueReferences.
RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript)13395 RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
13396   HandleScope scope(isolate);
13397   CHECK(isolate->debug()->live_edit_enabled());
13398   ASSERT(args.length() == 1);
13399   CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13400 
13401   RUNTIME_ASSERT(script_value->value()->IsScript());
13402   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13403 
13404   const int kBufferSize = 32;
13405 
13406   Handle<FixedArray> array;
13407   array = isolate->factory()->NewFixedArray(kBufferSize);
13408   int number;
13409   Heap* heap = isolate->heap();
13410   {
13411     HeapIterator heap_iterator(heap);
13412     Script* scr = *script;
13413     FixedArray* arr = *array;
13414     number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13415   }
13416   if (number > kBufferSize) {
13417     array = isolate->factory()->NewFixedArray(number);
13418     HeapIterator heap_iterator(heap);
13419     Script* scr = *script;
13420     FixedArray* arr = *array;
13421     FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13422   }
13423 
13424   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13425   result->set_length(Smi::FromInt(number));
13426 
13427   LiveEdit::WrapSharedFunctionInfos(result);
13428 
13429   return *result;
13430 }
13431 
13432 
13433 // For a script calculates compilation information about all its functions.
13434 // The script source is explicitly specified by the second argument.
13435 // The source of the actual script is not used, however it is important that
13436 // all generated code keeps references to this particular instance of script.
13437 // Returns a JSArray of compilation infos. The array is ordered so that
13438 // each function with all its descendant is always stored in a continues range
13439 // with the function itself going first. The root function is a script function.
RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo)13440 RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) {
13441   HandleScope scope(isolate);
13442   CHECK(isolate->debug()->live_edit_enabled());
13443   ASSERT(args.length() == 2);
13444   CONVERT_ARG_CHECKED(JSValue, script, 0);
13445   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13446 
13447   RUNTIME_ASSERT(script->value()->IsScript());
13448   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13449 
13450   Handle<JSArray> result;
13451   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13452       isolate, result, LiveEdit::GatherCompileInfo(script_handle, source));
13453   return *result;
13454 }
13455 
13456 
13457 // Changes the source of the script to a new_source.
13458 // If old_script_name is provided (i.e. is a String), also creates a copy of
13459 // the script with its original source and sends notification to debugger.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript)13460 RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) {
13461   HandleScope scope(isolate);
13462   CHECK(isolate->debug()->live_edit_enabled());
13463   ASSERT(args.length() == 3);
13464   CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13465   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13466   CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2);
13467 
13468   RUNTIME_ASSERT(original_script_value->value()->IsScript());
13469   Handle<Script> original_script(Script::cast(original_script_value->value()));
13470 
13471   Handle<Object> old_script = LiveEdit::ChangeScriptSource(
13472       original_script,  new_source,  old_script_name);
13473 
13474   if (old_script->IsScript()) {
13475     Handle<Script> script_handle = Handle<Script>::cast(old_script);
13476     return *Script::GetWrapper(script_handle);
13477   } else {
13478     return isolate->heap()->null_value();
13479   }
13480 }
13481 
13482 
RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated)13483 RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
13484   HandleScope scope(isolate);
13485   CHECK(isolate->debug()->live_edit_enabled());
13486   ASSERT(args.length() == 1);
13487   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13488   RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
13489 
13490   LiveEdit::FunctionSourceUpdated(shared_info);
13491   return isolate->heap()->undefined_value();
13492 }
13493 
13494 
13495 // Replaces code of SharedFunctionInfo with a new one.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode)13496 RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
13497   HandleScope scope(isolate);
13498   CHECK(isolate->debug()->live_edit_enabled());
13499   ASSERT(args.length() == 2);
13500   CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13501   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13502   RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_info));
13503 
13504   LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13505   return isolate->heap()->undefined_value();
13506 }
13507 
13508 
13509 // Connects SharedFunctionInfo to another script.
RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript)13510 RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
13511   HandleScope scope(isolate);
13512   CHECK(isolate->debug()->live_edit_enabled());
13513   ASSERT(args.length() == 2);
13514   CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
13515   CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1);
13516 
13517   if (function_object->IsJSValue()) {
13518     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13519     if (script_object->IsJSValue()) {
13520       RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13521       Script* script = Script::cast(JSValue::cast(*script_object)->value());
13522       script_object = Handle<Object>(script, isolate);
13523     }
13524     RUNTIME_ASSERT(function_wrapper->value()->IsSharedFunctionInfo());
13525     LiveEdit::SetFunctionScript(function_wrapper, script_object);
13526   } else {
13527     // Just ignore this. We may not have a SharedFunctionInfo for some functions
13528     // and we check it in this function.
13529   }
13530 
13531   return isolate->heap()->undefined_value();
13532 }
13533 
13534 
13535 // In a code of a parent function replaces original function as embedded object
13536 // with a substitution one.
RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction)13537 RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
13538   HandleScope scope(isolate);
13539   CHECK(isolate->debug()->live_edit_enabled());
13540   ASSERT(args.length() == 3);
13541 
13542   CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13543   CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13544   CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13545   RUNTIME_ASSERT(parent_wrapper->value()->IsSharedFunctionInfo());
13546   RUNTIME_ASSERT(orig_wrapper->value()->IsSharedFunctionInfo());
13547   RUNTIME_ASSERT(subst_wrapper->value()->IsSharedFunctionInfo());
13548 
13549   LiveEdit::ReplaceRefToNestedFunction(
13550       parent_wrapper, orig_wrapper, subst_wrapper);
13551   return isolate->heap()->undefined_value();
13552 }
13553 
13554 
13555 // Updates positions of a shared function info (first parameter) according
13556 // to script source change. Text change is described in second parameter as
13557 // array of groups of 3 numbers:
13558 // (change_begin, change_end, change_end_new_position).
13559 // Each group describes a change in text; groups are sorted by change_begin.
RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions)13560 RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) {
13561   HandleScope scope(isolate);
13562   CHECK(isolate->debug()->live_edit_enabled());
13563   ASSERT(args.length() == 2);
13564   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13565   CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13566   RUNTIME_ASSERT(SharedInfoWrapper::IsInstance(shared_array))
13567 
13568   LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13569   return isolate->heap()->undefined_value();
13570 }
13571 
13572 
13573 // For array of SharedFunctionInfo's (each wrapped in JSValue)
13574 // checks that none of them have activations on stacks (of any thread).
13575 // Returns array of the same length with corresponding results of
13576 // LiveEdit::FunctionPatchabilityStatus type.
RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations)13577 RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) {
13578   HandleScope scope(isolate);
13579   CHECK(isolate->debug()->live_edit_enabled());
13580   ASSERT(args.length() == 2);
13581   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13582   CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13583   RUNTIME_ASSERT(shared_array->length()->IsSmi());
13584   int array_length = Smi::cast(shared_array->length())->value();
13585   for (int i = 0; i < array_length; i++) {
13586     Handle<Object> element =
13587         Object::GetElement(isolate, shared_array, i).ToHandleChecked();
13588     RUNTIME_ASSERT(
13589         element->IsJSValue() &&
13590         Handle<JSValue>::cast(element)->value()->IsSharedFunctionInfo());
13591   }
13592 
13593   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13594 }
13595 
13596 
13597 // Compares 2 strings line-by-line, then token-wise and returns diff in form
13598 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13599 // of diff chunks.
RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings)13600 RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
13601   HandleScope scope(isolate);
13602   CHECK(isolate->debug()->live_edit_enabled());
13603   ASSERT(args.length() == 2);
13604   CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13605   CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13606 
13607   return *LiveEdit::CompareStrings(s1, s2);
13608 }
13609 
13610 
13611 // Restarts a call frame and completely drops all frames above.
13612 // Returns true if successful. Otherwise returns undefined or an error message.
RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame)13613 RUNTIME_FUNCTION(Runtime_LiveEditRestartFrame) {
13614   HandleScope scope(isolate);
13615   CHECK(isolate->debug()->live_edit_enabled());
13616   ASSERT(args.length() == 2);
13617   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
13618   RUNTIME_ASSERT(CheckExecutionState(isolate, break_id));
13619 
13620   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13621   Heap* heap = isolate->heap();
13622 
13623   // Find the relevant frame with the requested index.
13624   StackFrame::Id id = isolate->debug()->break_frame_id();
13625   if (id == StackFrame::NO_ID) {
13626     // If there are no JavaScript stack frames return undefined.
13627     return heap->undefined_value();
13628   }
13629 
13630   int count = 0;
13631   JavaScriptFrameIterator it(isolate, id);
13632   for (; !it.done(); it.Advance()) {
13633     if (index < count + it.frame()->GetInlineCount()) break;
13634     count += it.frame()->GetInlineCount();
13635   }
13636   if (it.done()) return heap->undefined_value();
13637 
13638   const char* error_message = LiveEdit::RestartFrame(it.frame());
13639   if (error_message) {
13640     return *(isolate->factory()->InternalizeUtf8String(error_message));
13641   }
13642   return heap->true_value();
13643 }
13644 
13645 
13646 // A testing entry. Returns statement position which is the closest to
13647 // source_position.
RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource)13648 RUNTIME_FUNCTION(Runtime_GetFunctionCodePositionFromSource) {
13649   HandleScope scope(isolate);
13650   CHECK(isolate->debug()->live_edit_enabled());
13651   ASSERT(args.length() == 2);
13652   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13653   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13654 
13655   Handle<Code> code(function->code(), isolate);
13656 
13657   if (code->kind() != Code::FUNCTION &&
13658       code->kind() != Code::OPTIMIZED_FUNCTION) {
13659     return isolate->heap()->undefined_value();
13660   }
13661 
13662   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13663   int closest_pc = 0;
13664   int distance = kMaxInt;
13665   while (!it.done()) {
13666     int statement_position = static_cast<int>(it.rinfo()->data());
13667     // Check if this break point is closer that what was previously found.
13668     if (source_position <= statement_position &&
13669         statement_position - source_position < distance) {
13670       closest_pc =
13671           static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13672       distance = statement_position - source_position;
13673       // Check whether we can't get any closer.
13674       if (distance == 0) break;
13675     }
13676     it.next();
13677   }
13678 
13679   return Smi::FromInt(closest_pc);
13680 }
13681 
13682 
13683 // Calls specified function with or without entering the debugger.
13684 // This is used in unit tests to run code as if debugger is entered or simply
13685 // to have a stack with C++ frame in the middle.
RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext)13686 RUNTIME_FUNCTION(Runtime_ExecuteInDebugContext) {
13687   HandleScope scope(isolate);
13688   ASSERT(args.length() == 2);
13689   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13690   CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13691 
13692   MaybeHandle<Object> maybe_result;
13693   if (without_debugger) {
13694     maybe_result = Execution::Call(isolate,
13695                                    function,
13696                                    isolate->global_object(),
13697                                    0,
13698                                    NULL);
13699   } else {
13700     DebugScope debug_scope(isolate->debug());
13701     maybe_result = Execution::Call(isolate,
13702                                    function,
13703                                    isolate->global_object(),
13704                                    0,
13705                                    NULL);
13706   }
13707   Handle<Object> result;
13708   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result);
13709   return *result;
13710 }
13711 
13712 
13713 // Sets a v8 flag.
RUNTIME_FUNCTION(Runtime_SetFlags)13714 RUNTIME_FUNCTION(Runtime_SetFlags) {
13715   SealHandleScope shs(isolate);
13716   ASSERT(args.length() == 1);
13717   CONVERT_ARG_CHECKED(String, arg, 0);
13718   SmartArrayPointer<char> flags =
13719       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13720   FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
13721   return isolate->heap()->undefined_value();
13722 }
13723 
13724 
13725 // Performs a GC.
13726 // Presently, it only does a full GC.
RUNTIME_FUNCTION(Runtime_CollectGarbage)13727 RUNTIME_FUNCTION(Runtime_CollectGarbage) {
13728   SealHandleScope shs(isolate);
13729   ASSERT(args.length() == 1);
13730   isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13731   return isolate->heap()->undefined_value();
13732 }
13733 
13734 
13735 // Gets the current heap usage.
RUNTIME_FUNCTION(Runtime_GetHeapUsage)13736 RUNTIME_FUNCTION(Runtime_GetHeapUsage) {
13737   SealHandleScope shs(isolate);
13738   ASSERT(args.length() == 0);
13739   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13740   if (!Smi::IsValid(usage)) {
13741     return *isolate->factory()->NewNumberFromInt(usage);
13742   }
13743   return Smi::FromInt(usage);
13744 }
13745 
13746 
13747 #ifdef V8_I18N_SUPPORT
RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag)13748 RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
13749   HandleScope scope(isolate);
13750   Factory* factory = isolate->factory();
13751 
13752   ASSERT(args.length() == 1);
13753   CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13754 
13755   v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13756 
13757   // Return value which denotes invalid language tag.
13758   const char* const kInvalidTag = "invalid-tag";
13759 
13760   UErrorCode error = U_ZERO_ERROR;
13761   char icu_result[ULOC_FULLNAME_CAPACITY];
13762   int icu_length = 0;
13763 
13764   uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13765                       &icu_length, &error);
13766   if (U_FAILURE(error) || icu_length == 0) {
13767     return *factory->NewStringFromAsciiChecked(kInvalidTag);
13768   }
13769 
13770   char result[ULOC_FULLNAME_CAPACITY];
13771 
13772   // Force strict BCP47 rules.
13773   uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13774 
13775   if (U_FAILURE(error)) {
13776     return *factory->NewStringFromAsciiChecked(kInvalidTag);
13777   }
13778 
13779   return *factory->NewStringFromAsciiChecked(result);
13780 }
13781 
13782 
RUNTIME_FUNCTION(Runtime_AvailableLocalesOf)13783 RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) {
13784   HandleScope scope(isolate);
13785   Factory* factory = isolate->factory();
13786 
13787   ASSERT(args.length() == 1);
13788   CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13789 
13790   const icu::Locale* available_locales = NULL;
13791   int32_t count = 0;
13792 
13793   if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13794     available_locales = icu::Collator::getAvailableLocales(count);
13795   } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13796     available_locales = icu::NumberFormat::getAvailableLocales(count);
13797   } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13798     available_locales = icu::DateFormat::getAvailableLocales(count);
13799   } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13800     available_locales = icu::BreakIterator::getAvailableLocales(count);
13801   }
13802 
13803   UErrorCode error = U_ZERO_ERROR;
13804   char result[ULOC_FULLNAME_CAPACITY];
13805   Handle<JSObject> locales =
13806       factory->NewJSObject(isolate->object_function());
13807 
13808   for (int32_t i = 0; i < count; ++i) {
13809     const char* icu_name = available_locales[i].getName();
13810 
13811     error = U_ZERO_ERROR;
13812     // No need to force strict BCP47 rules.
13813     uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13814     if (U_FAILURE(error)) {
13815       // This shouldn't happen, but lets not break the user.
13816       continue;
13817     }
13818 
13819     RETURN_FAILURE_ON_EXCEPTION(isolate,
13820         JSObject::SetOwnPropertyIgnoreAttributes(
13821             locales,
13822             factory->NewStringFromAsciiChecked(result),
13823             factory->NewNumber(i),
13824             NONE));
13825   }
13826 
13827   return *locales;
13828 }
13829 
13830 
RUNTIME_FUNCTION(Runtime_GetDefaultICULocale)13831 RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
13832   HandleScope scope(isolate);
13833   Factory* factory = isolate->factory();
13834 
13835   ASSERT(args.length() == 0);
13836 
13837   icu::Locale default_locale;
13838 
13839   // Set the locale
13840   char result[ULOC_FULLNAME_CAPACITY];
13841   UErrorCode status = U_ZERO_ERROR;
13842   uloc_toLanguageTag(
13843       default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13844   if (U_SUCCESS(status)) {
13845     return *factory->NewStringFromAsciiChecked(result);
13846   }
13847 
13848   return *factory->NewStringFromStaticAscii("und");
13849 }
13850 
13851 
RUNTIME_FUNCTION(Runtime_GetLanguageTagVariants)13852 RUNTIME_FUNCTION(Runtime_GetLanguageTagVariants) {
13853   HandleScope scope(isolate);
13854   Factory* factory = isolate->factory();
13855 
13856   ASSERT(args.length() == 1);
13857 
13858   CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13859 
13860   uint32_t length = static_cast<uint32_t>(input->length()->Number());
13861   // Set some limit to prevent fuzz tests from going OOM.
13862   // Can be bumped when callers' requirements change.
13863   RUNTIME_ASSERT(length < 100);
13864   Handle<FixedArray> output = factory->NewFixedArray(length);
13865   Handle<Name> maximized = factory->NewStringFromStaticAscii("maximized");
13866   Handle<Name> base = factory->NewStringFromStaticAscii("base");
13867   for (unsigned int i = 0; i < length; ++i) {
13868     Handle<Object> locale_id;
13869     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
13870         isolate, locale_id, Object::GetElement(isolate, input, i));
13871     if (!locale_id->IsString()) {
13872       return isolate->Throw(*factory->illegal_argument_string());
13873     }
13874 
13875     v8::String::Utf8Value utf8_locale_id(
13876         v8::Utils::ToLocal(Handle<String>::cast(locale_id)));
13877 
13878     UErrorCode error = U_ZERO_ERROR;
13879 
13880     // Convert from BCP47 to ICU format.
13881     // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13882     char icu_locale[ULOC_FULLNAME_CAPACITY];
13883     int icu_locale_length = 0;
13884     uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13885                         &icu_locale_length, &error);
13886     if (U_FAILURE(error) || icu_locale_length == 0) {
13887       return isolate->Throw(*factory->illegal_argument_string());
13888     }
13889 
13890     // Maximize the locale.
13891     // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13892     char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13893     uloc_addLikelySubtags(
13894         icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13895 
13896     // Remove extensions from maximized locale.
13897     // de_Latn_DE@collation=phonebook -> de_Latn_DE
13898     char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13899     uloc_getBaseName(
13900         icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13901 
13902     // Get original name without extensions.
13903     // de_DE@collation=phonebook -> de_DE
13904     char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13905     uloc_getBaseName(
13906         icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13907 
13908     // Convert from ICU locale format to BCP47 format.
13909     // de_Latn_DE -> de-Latn-DE
13910     char base_max_locale[ULOC_FULLNAME_CAPACITY];
13911     uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13912                        ULOC_FULLNAME_CAPACITY, FALSE, &error);
13913 
13914     // de_DE -> de-DE
13915     char base_locale[ULOC_FULLNAME_CAPACITY];
13916     uloc_toLanguageTag(
13917         icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13918 
13919     if (U_FAILURE(error)) {
13920       return isolate->Throw(*factory->illegal_argument_string());
13921     }
13922 
13923     Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
13924     RETURN_FAILURE_ON_EXCEPTION(isolate,
13925         JSObject::SetOwnPropertyIgnoreAttributes(
13926             result,
13927             maximized,
13928             factory->NewStringFromAsciiChecked(base_max_locale),
13929             NONE));
13930     RETURN_FAILURE_ON_EXCEPTION(isolate,
13931         JSObject::SetOwnPropertyIgnoreAttributes(
13932             result,
13933             base,
13934             factory->NewStringFromAsciiChecked(base_locale),
13935             NONE));
13936     output->set(i, *result);
13937   }
13938 
13939   Handle<JSArray> result = factory->NewJSArrayWithElements(output);
13940   result->set_length(Smi::FromInt(length));
13941   return *result;
13942 }
13943 
13944 
RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject)13945 RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject) {
13946   HandleScope scope(isolate);
13947 
13948   ASSERT(args.length() == 1);
13949 
13950   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
13951 
13952   if (!input->IsJSObject()) return isolate->heap()->false_value();
13953   Handle<JSObject> obj = Handle<JSObject>::cast(input);
13954 
13955   Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
13956   Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
13957   return isolate->heap()->ToBoolean(!tag->IsTheHole());
13958 }
13959 
13960 
RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType)13961 RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
13962   HandleScope scope(isolate);
13963 
13964   ASSERT(args.length() == 2);
13965 
13966   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
13967   CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
13968 
13969   if (!input->IsJSObject()) return isolate->heap()->false_value();
13970   Handle<JSObject> obj = Handle<JSObject>::cast(input);
13971 
13972   Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
13973   Handle<Object> tag(obj->GetHiddenProperty(marker), isolate);
13974   return isolate->heap()->ToBoolean(
13975       tag->IsString() && String::cast(*tag)->Equals(*expected_type));
13976 }
13977 
13978 
RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType)13979 RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
13980   HandleScope scope(isolate);
13981 
13982   ASSERT(args.length() == 3);
13983 
13984   CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
13985   CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
13986   CONVERT_ARG_HANDLE_CHECKED(JSObject, impl, 2);
13987 
13988   Handle<String> marker = isolate->factory()->intl_initialized_marker_string();
13989   JSObject::SetHiddenProperty(input, marker, type);
13990 
13991   marker = isolate->factory()->intl_impl_object_string();
13992   JSObject::SetHiddenProperty(input, marker, impl);
13993 
13994   return isolate->heap()->undefined_value();
13995 }
13996 
13997 
RUNTIME_FUNCTION(Runtime_GetImplFromInitializedIntlObject)13998 RUNTIME_FUNCTION(Runtime_GetImplFromInitializedIntlObject) {
13999   HandleScope scope(isolate);
14000 
14001   ASSERT(args.length() == 1);
14002 
14003   CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
14004 
14005   if (!input->IsJSObject()) {
14006     Vector< Handle<Object> > arguments = HandleVector(&input, 1);
14007     Handle<Object> type_error =
14008         isolate->factory()->NewTypeError("not_intl_object", arguments);
14009     return isolate->Throw(*type_error);
14010   }
14011 
14012   Handle<JSObject> obj = Handle<JSObject>::cast(input);
14013 
14014   Handle<String> marker = isolate->factory()->intl_impl_object_string();
14015   Handle<Object> impl(obj->GetHiddenProperty(marker), isolate);
14016   if (impl->IsTheHole()) {
14017     Vector< Handle<Object> > arguments = HandleVector(&obj, 1);
14018     Handle<Object> type_error =
14019         isolate->factory()->NewTypeError("not_intl_object", arguments);
14020     return isolate->Throw(*type_error);
14021   }
14022   return *impl;
14023 }
14024 
14025 
RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat)14026 RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
14027   HandleScope scope(isolate);
14028 
14029   ASSERT(args.length() == 3);
14030 
14031   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14032   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14033   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14034 
14035   Handle<ObjectTemplateInfo> date_format_template =
14036       I18N::GetTemplate(isolate);
14037 
14038   // Create an empty object wrapper.
14039   Handle<JSObject> local_object;
14040   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14041       isolate, local_object,
14042       Execution::InstantiateObject(date_format_template));
14043 
14044   // Set date time formatter as internal field of the resulting JS object.
14045   icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
14046       isolate, locale, options, resolved);
14047 
14048   if (!date_format) return isolate->ThrowIllegalOperation();
14049 
14050   local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
14051 
14052   RETURN_FAILURE_ON_EXCEPTION(isolate,
14053       JSObject::SetOwnPropertyIgnoreAttributes(
14054           local_object,
14055           isolate->factory()->NewStringFromStaticAscii("dateFormat"),
14056           isolate->factory()->NewStringFromStaticAscii("valid"),
14057           NONE));
14058 
14059   // Make object handle weak so we can delete the data format once GC kicks in.
14060   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14061   GlobalHandles::MakeWeak(wrapper.location(),
14062                           reinterpret_cast<void*>(wrapper.location()),
14063                           DateFormat::DeleteDateFormat);
14064   return *local_object;
14065 }
14066 
14067 
RUNTIME_FUNCTION(Runtime_InternalDateFormat)14068 RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
14069   HandleScope scope(isolate);
14070 
14071   ASSERT(args.length() == 2);
14072 
14073   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
14074   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
14075 
14076   Handle<Object> value;
14077   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14078       isolate, value, Execution::ToNumber(isolate, date));
14079 
14080   icu::SimpleDateFormat* date_format =
14081       DateFormat::UnpackDateFormat(isolate, date_format_holder);
14082   if (!date_format) return isolate->ThrowIllegalOperation();
14083 
14084   icu::UnicodeString result;
14085   date_format->format(value->Number(), result);
14086 
14087   Handle<String> result_str;
14088   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14089       isolate, result_str,
14090       isolate->factory()->NewStringFromTwoByte(
14091           Vector<const uint16_t>(
14092               reinterpret_cast<const uint16_t*>(result.getBuffer()),
14093               result.length())));
14094   return *result_str;
14095 }
14096 
14097 
RUNTIME_FUNCTION(Runtime_InternalDateParse)14098 RUNTIME_FUNCTION(Runtime_InternalDateParse) {
14099   HandleScope scope(isolate);
14100 
14101   ASSERT(args.length() == 2);
14102 
14103   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
14104   CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
14105 
14106   v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
14107   icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
14108   icu::SimpleDateFormat* date_format =
14109       DateFormat::UnpackDateFormat(isolate, date_format_holder);
14110   if (!date_format) return isolate->ThrowIllegalOperation();
14111 
14112   UErrorCode status = U_ZERO_ERROR;
14113   UDate date = date_format->parse(u_date, status);
14114   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14115 
14116   Handle<Object> result;
14117   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14118       isolate, result,
14119       Execution::NewDate(isolate, static_cast<double>(date)));
14120   ASSERT(result->IsJSDate());
14121   return *result;
14122 }
14123 
14124 
RUNTIME_FUNCTION(Runtime_CreateNumberFormat)14125 RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
14126   HandleScope scope(isolate);
14127 
14128   ASSERT(args.length() == 3);
14129 
14130   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14131   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14132   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14133 
14134   Handle<ObjectTemplateInfo> number_format_template =
14135       I18N::GetTemplate(isolate);
14136 
14137   // Create an empty object wrapper.
14138   Handle<JSObject> local_object;
14139   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14140       isolate, local_object,
14141       Execution::InstantiateObject(number_format_template));
14142 
14143   // Set number formatter as internal field of the resulting JS object.
14144   icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
14145       isolate, locale, options, resolved);
14146 
14147   if (!number_format) return isolate->ThrowIllegalOperation();
14148 
14149   local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
14150 
14151   RETURN_FAILURE_ON_EXCEPTION(isolate,
14152       JSObject::SetOwnPropertyIgnoreAttributes(
14153           local_object,
14154           isolate->factory()->NewStringFromStaticAscii("numberFormat"),
14155           isolate->factory()->NewStringFromStaticAscii("valid"),
14156           NONE));
14157 
14158   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14159   GlobalHandles::MakeWeak(wrapper.location(),
14160                           reinterpret_cast<void*>(wrapper.location()),
14161                           NumberFormat::DeleteNumberFormat);
14162   return *local_object;
14163 }
14164 
14165 
RUNTIME_FUNCTION(Runtime_InternalNumberFormat)14166 RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
14167   HandleScope scope(isolate);
14168 
14169   ASSERT(args.length() == 2);
14170 
14171   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14172   CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
14173 
14174   Handle<Object> value;
14175   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14176       isolate, value, Execution::ToNumber(isolate, number));
14177 
14178   icu::DecimalFormat* number_format =
14179       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14180   if (!number_format) return isolate->ThrowIllegalOperation();
14181 
14182   icu::UnicodeString result;
14183   number_format->format(value->Number(), result);
14184 
14185   Handle<String> result_str;
14186   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14187       isolate, result_str,
14188       isolate->factory()->NewStringFromTwoByte(
14189           Vector<const uint16_t>(
14190               reinterpret_cast<const uint16_t*>(result.getBuffer()),
14191               result.length())));
14192   return *result_str;
14193 }
14194 
14195 
RUNTIME_FUNCTION(Runtime_InternalNumberParse)14196 RUNTIME_FUNCTION(Runtime_InternalNumberParse) {
14197   HandleScope scope(isolate);
14198 
14199   ASSERT(args.length() == 2);
14200 
14201   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14202   CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
14203 
14204   v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
14205   icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
14206   icu::DecimalFormat* number_format =
14207       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14208   if (!number_format) return isolate->ThrowIllegalOperation();
14209 
14210   UErrorCode status = U_ZERO_ERROR;
14211   icu::Formattable result;
14212   // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
14213   // to be part of Chrome.
14214   // TODO(cira): Include currency parsing code using parseCurrency call.
14215   // We need to check if the formatter parses all currencies or only the
14216   // one it was constructed with (it will impact the API - how to return ISO
14217   // code and the value).
14218   number_format->parse(u_number, result, status);
14219   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14220 
14221   switch (result.getType()) {
14222   case icu::Formattable::kDouble:
14223     return *isolate->factory()->NewNumber(result.getDouble());
14224   case icu::Formattable::kLong:
14225     return *isolate->factory()->NewNumberFromInt(result.getLong());
14226   case icu::Formattable::kInt64:
14227     return *isolate->factory()->NewNumber(
14228         static_cast<double>(result.getInt64()));
14229   default:
14230     return isolate->heap()->undefined_value();
14231   }
14232 }
14233 
14234 
RUNTIME_FUNCTION(Runtime_CreateCollator)14235 RUNTIME_FUNCTION(Runtime_CreateCollator) {
14236   HandleScope scope(isolate);
14237 
14238   ASSERT(args.length() == 3);
14239 
14240   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14241   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14242   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14243 
14244   Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
14245 
14246   // Create an empty object wrapper.
14247   Handle<JSObject> local_object;
14248   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14249       isolate, local_object, Execution::InstantiateObject(collator_template));
14250 
14251   // Set collator as internal field of the resulting JS object.
14252   icu::Collator* collator = Collator::InitializeCollator(
14253       isolate, locale, options, resolved);
14254 
14255   if (!collator) return isolate->ThrowIllegalOperation();
14256 
14257   local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
14258 
14259   RETURN_FAILURE_ON_EXCEPTION(isolate,
14260       JSObject::SetOwnPropertyIgnoreAttributes(
14261           local_object,
14262           isolate->factory()->NewStringFromStaticAscii("collator"),
14263           isolate->factory()->NewStringFromStaticAscii("valid"),
14264           NONE));
14265 
14266   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14267   GlobalHandles::MakeWeak(wrapper.location(),
14268                           reinterpret_cast<void*>(wrapper.location()),
14269                           Collator::DeleteCollator);
14270   return *local_object;
14271 }
14272 
14273 
RUNTIME_FUNCTION(Runtime_InternalCompare)14274 RUNTIME_FUNCTION(Runtime_InternalCompare) {
14275   HandleScope scope(isolate);
14276 
14277   ASSERT(args.length() == 3);
14278 
14279   CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
14280   CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
14281   CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
14282 
14283   icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
14284   if (!collator) return isolate->ThrowIllegalOperation();
14285 
14286   v8::String::Value string_value1(v8::Utils::ToLocal(string1));
14287   v8::String::Value string_value2(v8::Utils::ToLocal(string2));
14288   const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
14289   const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
14290   UErrorCode status = U_ZERO_ERROR;
14291   UCollationResult result = collator->compare(u_string1,
14292                                               string_value1.length(),
14293                                               u_string2,
14294                                               string_value2.length(),
14295                                               status);
14296   if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
14297 
14298   return *isolate->factory()->NewNumberFromInt(result);
14299 }
14300 
14301 
RUNTIME_FUNCTION(Runtime_StringNormalize)14302 RUNTIME_FUNCTION(Runtime_StringNormalize) {
14303   HandleScope scope(isolate);
14304   static const UNormalizationMode normalizationForms[] =
14305       { UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD };
14306 
14307   ASSERT(args.length() == 2);
14308 
14309   CONVERT_ARG_HANDLE_CHECKED(String, stringValue, 0);
14310   CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
14311   RUNTIME_ASSERT(form_id >= 0 &&
14312                  static_cast<size_t>(form_id) < ARRAY_SIZE(normalizationForms));
14313 
14314   v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
14315   const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
14316 
14317   // TODO(mnita): check Normalizer2 (not available in ICU 46)
14318   UErrorCode status = U_ZERO_ERROR;
14319   icu::UnicodeString result;
14320   icu::Normalizer::normalize(u_value, normalizationForms[form_id], 0,
14321       result, status);
14322   if (U_FAILURE(status)) {
14323     return isolate->heap()->undefined_value();
14324   }
14325 
14326   Handle<String> result_str;
14327   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14328       isolate, result_str,
14329       isolate->factory()->NewStringFromTwoByte(
14330           Vector<const uint16_t>(
14331               reinterpret_cast<const uint16_t*>(result.getBuffer()),
14332               result.length())));
14333   return *result_str;
14334 }
14335 
14336 
RUNTIME_FUNCTION(Runtime_CreateBreakIterator)14337 RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
14338   HandleScope scope(isolate);
14339 
14340   ASSERT(args.length() == 3);
14341 
14342   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14343   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14344   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14345 
14346   Handle<ObjectTemplateInfo> break_iterator_template =
14347       I18N::GetTemplate2(isolate);
14348 
14349   // Create an empty object wrapper.
14350   Handle<JSObject> local_object;
14351   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14352       isolate, local_object,
14353       Execution::InstantiateObject(break_iterator_template));
14354 
14355   // Set break iterator as internal field of the resulting JS object.
14356   icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
14357       isolate, locale, options, resolved);
14358 
14359   if (!break_iterator) return isolate->ThrowIllegalOperation();
14360 
14361   local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
14362   // Make sure that the pointer to adopted text is NULL.
14363   local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
14364 
14365   RETURN_FAILURE_ON_EXCEPTION(isolate,
14366       JSObject::SetOwnPropertyIgnoreAttributes(
14367           local_object,
14368           isolate->factory()->NewStringFromStaticAscii("breakIterator"),
14369           isolate->factory()->NewStringFromStaticAscii("valid"),
14370           NONE));
14371 
14372   // Make object handle weak so we can delete the break iterator once GC kicks
14373   // in.
14374   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14375   GlobalHandles::MakeWeak(wrapper.location(),
14376                           reinterpret_cast<void*>(wrapper.location()),
14377                           BreakIterator::DeleteBreakIterator);
14378   return *local_object;
14379 }
14380 
14381 
RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText)14382 RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
14383   HandleScope scope(isolate);
14384 
14385   ASSERT(args.length() == 2);
14386 
14387   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14388   CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
14389 
14390   icu::BreakIterator* break_iterator =
14391       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14392   if (!break_iterator) return isolate->ThrowIllegalOperation();
14393 
14394   icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
14395       break_iterator_holder->GetInternalField(1));
14396   delete u_text;
14397 
14398   v8::String::Value text_value(v8::Utils::ToLocal(text));
14399   u_text = new icu::UnicodeString(
14400       reinterpret_cast<const UChar*>(*text_value), text_value.length());
14401   break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
14402 
14403   break_iterator->setText(*u_text);
14404 
14405   return isolate->heap()->undefined_value();
14406 }
14407 
14408 
RUNTIME_FUNCTION(Runtime_BreakIteratorFirst)14409 RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
14410   HandleScope scope(isolate);
14411 
14412   ASSERT(args.length() == 1);
14413 
14414   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14415 
14416   icu::BreakIterator* break_iterator =
14417       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14418   if (!break_iterator) return isolate->ThrowIllegalOperation();
14419 
14420   return *isolate->factory()->NewNumberFromInt(break_iterator->first());
14421 }
14422 
14423 
RUNTIME_FUNCTION(Runtime_BreakIteratorNext)14424 RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
14425   HandleScope scope(isolate);
14426 
14427   ASSERT(args.length() == 1);
14428 
14429   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14430 
14431   icu::BreakIterator* break_iterator =
14432       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14433   if (!break_iterator) return isolate->ThrowIllegalOperation();
14434 
14435   return *isolate->factory()->NewNumberFromInt(break_iterator->next());
14436 }
14437 
14438 
RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent)14439 RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
14440   HandleScope scope(isolate);
14441 
14442   ASSERT(args.length() == 1);
14443 
14444   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14445 
14446   icu::BreakIterator* break_iterator =
14447       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14448   if (!break_iterator) return isolate->ThrowIllegalOperation();
14449 
14450   return *isolate->factory()->NewNumberFromInt(break_iterator->current());
14451 }
14452 
14453 
RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType)14454 RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
14455   HandleScope scope(isolate);
14456 
14457   ASSERT(args.length() == 1);
14458 
14459   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14460 
14461   icu::BreakIterator* break_iterator =
14462       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14463   if (!break_iterator) return isolate->ThrowIllegalOperation();
14464 
14465   // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
14466   icu::RuleBasedBreakIterator* rule_based_iterator =
14467       static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
14468   int32_t status = rule_based_iterator->getRuleStatus();
14469   // Keep return values in sync with JavaScript BreakType enum.
14470   if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
14471     return *isolate->factory()->NewStringFromStaticAscii("none");
14472   } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
14473     return *isolate->factory()->NewStringFromStaticAscii("number");
14474   } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
14475     return *isolate->factory()->NewStringFromStaticAscii("letter");
14476   } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
14477     return *isolate->factory()->NewStringFromStaticAscii("kana");
14478   } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
14479     return *isolate->factory()->NewStringFromStaticAscii("ideo");
14480   } else {
14481     return *isolate->factory()->NewStringFromStaticAscii("unknown");
14482   }
14483 }
14484 #endif  // V8_I18N_SUPPORT
14485 
14486 
14487 // Finds the script object from the script data. NOTE: This operation uses
14488 // heap traversal to find the function generated for the source position
14489 // for the requested break point. For lazily compiled functions several heap
14490 // traversals might be required rendering this operation as a rather slow
14491 // operation. However for setting break points which is normally done through
14492 // some kind of user interaction the performance is not crucial.
Runtime_GetScriptFromScriptName(Handle<String> script_name)14493 static Handle<Object> Runtime_GetScriptFromScriptName(
14494     Handle<String> script_name) {
14495   // Scan the heap for Script objects to find the script with the requested
14496   // script data.
14497   Handle<Script> script;
14498   Factory* factory = script_name->GetIsolate()->factory();
14499   Heap* heap = script_name->GetHeap();
14500   HeapIterator iterator(heap);
14501   HeapObject* obj = NULL;
14502   while (script.is_null() && ((obj = iterator.next()) != NULL)) {
14503     // If a script is found check if it has the script data requested.
14504     if (obj->IsScript()) {
14505       if (Script::cast(obj)->name()->IsString()) {
14506         if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
14507           script = Handle<Script>(Script::cast(obj));
14508         }
14509       }
14510     }
14511   }
14512 
14513   // If no script with the requested script data is found return undefined.
14514   if (script.is_null()) return factory->undefined_value();
14515 
14516   // Return the script found.
14517   return Script::GetWrapper(script);
14518 }
14519 
14520 
14521 // Get the script object from script data. NOTE: Regarding performance
14522 // see the NOTE for GetScriptFromScriptData.
14523 // args[0]: script data for the script to find the source for
RUNTIME_FUNCTION(Runtime_GetScript)14524 RUNTIME_FUNCTION(Runtime_GetScript) {
14525   HandleScope scope(isolate);
14526 
14527   ASSERT(args.length() == 1);
14528 
14529   CONVERT_ARG_CHECKED(String, script_name, 0);
14530 
14531   // Find the requested script.
14532   Handle<Object> result =
14533       Runtime_GetScriptFromScriptName(Handle<String>(script_name));
14534   return *result;
14535 }
14536 
14537 
14538 // Collect the raw data for a stack trace.  Returns an array of 4
14539 // element segments each containing a receiver, function, code and
14540 // native code offset.
RUNTIME_FUNCTION(Runtime_CollectStackTrace)14541 RUNTIME_FUNCTION(Runtime_CollectStackTrace) {
14542   HandleScope scope(isolate);
14543   ASSERT(args.length() == 3);
14544   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14545   CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1);
14546   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
14547 
14548   // Optionally capture a more detailed stack trace for the message.
14549   isolate->CaptureAndSetDetailedStackTrace(error_object);
14550   // Capture a simple stack trace for the stack property.
14551   return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
14552 }
14553 
14554 
14555 // Retrieve the stack trace.  This is the raw stack trace that yet has to
14556 // be formatted.  Since we only need this once, clear it afterwards.
RUNTIME_FUNCTION(Runtime_GetAndClearOverflowedStackTrace)14557 RUNTIME_FUNCTION(Runtime_GetAndClearOverflowedStackTrace) {
14558   HandleScope scope(isolate);
14559   ASSERT(args.length() == 1);
14560   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14561   Handle<String> key = isolate->factory()->hidden_stack_trace_string();
14562   Handle<Object> result(error_object->GetHiddenProperty(key), isolate);
14563   if (result->IsTheHole()) return isolate->heap()->undefined_value();
14564   RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
14565   JSObject::DeleteHiddenProperty(error_object, key);
14566   return *result;
14567 }
14568 
14569 
14570 // Returns V8 version as a string.
RUNTIME_FUNCTION(Runtime_GetV8Version)14571 RUNTIME_FUNCTION(Runtime_GetV8Version) {
14572   HandleScope scope(isolate);
14573   ASSERT(args.length() == 0);
14574 
14575   const char* version_string = v8::V8::GetVersion();
14576 
14577   return *isolate->factory()->NewStringFromAsciiChecked(version_string);
14578 }
14579 
14580 
RUNTIME_FUNCTION(Runtime_Abort)14581 RUNTIME_FUNCTION(Runtime_Abort) {
14582   SealHandleScope shs(isolate);
14583   ASSERT(args.length() == 1);
14584   CONVERT_SMI_ARG_CHECKED(message_id, 0);
14585   const char* message = GetBailoutReason(
14586       static_cast<BailoutReason>(message_id));
14587   OS::PrintError("abort: %s\n", message);
14588   isolate->PrintStack(stderr);
14589   OS::Abort();
14590   UNREACHABLE();
14591   return NULL;
14592 }
14593 
14594 
RUNTIME_FUNCTION(Runtime_AbortJS)14595 RUNTIME_FUNCTION(Runtime_AbortJS) {
14596   HandleScope scope(isolate);
14597   ASSERT(args.length() == 1);
14598   CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
14599   OS::PrintError("abort: %s\n", message->ToCString().get());
14600   isolate->PrintStack(stderr);
14601   OS::Abort();
14602   UNREACHABLE();
14603   return NULL;
14604 }
14605 
14606 
RUNTIME_FUNCTION(Runtime_FlattenString)14607 RUNTIME_FUNCTION(Runtime_FlattenString) {
14608   HandleScope scope(isolate);
14609   ASSERT(args.length() == 1);
14610   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
14611   return *String::Flatten(str);
14612 }
14613 
14614 
RUNTIME_FUNCTION(Runtime_NotifyContextDisposed)14615 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
14616   HandleScope scope(isolate);
14617   ASSERT(args.length() == 0);
14618   isolate->heap()->NotifyContextDisposed();
14619   return isolate->heap()->undefined_value();
14620 }
14621 
14622 
RUNTIME_FUNCTION(Runtime_LoadMutableDouble)14623 RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
14624   HandleScope scope(isolate);
14625   ASSERT(args.length() == 2);
14626   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
14627   CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
14628   RUNTIME_ASSERT((index->value() & 1) == 1);
14629   FieldIndex field_index =
14630       FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
14631   if (field_index.is_inobject()) {
14632     RUNTIME_ASSERT(field_index.property_index() <
14633                    object->map()->inobject_properties());
14634   } else {
14635     RUNTIME_ASSERT(field_index.outobject_array_index() <
14636                    object->properties()->length());
14637   }
14638   Handle<Object> raw_value(object->RawFastPropertyAt(field_index), isolate);
14639   RUNTIME_ASSERT(raw_value->IsNumber() || raw_value->IsUninitialized());
14640   return *Object::NewStorageFor(isolate, raw_value, Representation::Double());
14641 }
14642 
14643 
RUNTIME_FUNCTION(Runtime_TryMigrateInstance)14644 RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
14645   HandleScope scope(isolate);
14646   ASSERT(args.length() == 1);
14647   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14648   if (!object->IsJSObject()) return Smi::FromInt(0);
14649   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14650   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14651   // This call must not cause lazy deopts, because it's called from deferred
14652   // code where we can't handle lazy deopts for lack of a suitable bailout
14653   // ID. So we just try migration and signal failure if necessary,
14654   // which will also trigger a deopt.
14655   if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
14656   return *object;
14657 }
14658 
14659 
RUNTIME_FUNCTION(RuntimeHidden_GetFromCache)14660 RUNTIME_FUNCTION(RuntimeHidden_GetFromCache) {
14661   SealHandleScope shs(isolate);
14662   // This is only called from codegen, so checks might be more lax.
14663   CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
14664   CONVERT_ARG_CHECKED(Object, key, 1);
14665 
14666   {
14667     DisallowHeapAllocation no_alloc;
14668 
14669     int finger_index = cache->finger_index();
14670     Object* o = cache->get(finger_index);
14671     if (o == key) {
14672       // The fastest case: hit the same place again.
14673       return cache->get(finger_index + 1);
14674     }
14675 
14676     for (int i = finger_index - 2;
14677          i >= JSFunctionResultCache::kEntriesIndex;
14678          i -= 2) {
14679       o = cache->get(i);
14680       if (o == key) {
14681         cache->set_finger_index(i);
14682         return cache->get(i + 1);
14683       }
14684     }
14685 
14686     int size = cache->size();
14687     ASSERT(size <= cache->length());
14688 
14689     for (int i = size - 2; i > finger_index; i -= 2) {
14690       o = cache->get(i);
14691       if (o == key) {
14692         cache->set_finger_index(i);
14693         return cache->get(i + 1);
14694       }
14695     }
14696   }
14697 
14698   // There is no value in the cache.  Invoke the function and cache result.
14699   HandleScope scope(isolate);
14700 
14701   Handle<JSFunctionResultCache> cache_handle(cache);
14702   Handle<Object> key_handle(key, isolate);
14703   Handle<Object> value;
14704   {
14705     Handle<JSFunction> factory(JSFunction::cast(
14706           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14707     // TODO(antonm): consider passing a receiver when constructing a cache.
14708     Handle<Object> receiver(isolate->native_context()->global_object(),
14709                             isolate);
14710     // This handle is nor shared, nor used later, so it's safe.
14711     Handle<Object> argv[] = { key_handle };
14712     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
14713         isolate, value,
14714         Execution::Call(isolate, factory, receiver, ARRAY_SIZE(argv), argv));
14715   }
14716 
14717 #ifdef VERIFY_HEAP
14718   if (FLAG_verify_heap) {
14719     cache_handle->JSFunctionResultCacheVerify();
14720   }
14721 #endif
14722 
14723   // Function invocation may have cleared the cache.  Reread all the data.
14724   int finger_index = cache_handle->finger_index();
14725   int size = cache_handle->size();
14726 
14727   // If we have spare room, put new data into it, otherwise evict post finger
14728   // entry which is likely to be the least recently used.
14729   int index = -1;
14730   if (size < cache_handle->length()) {
14731     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14732     index = size;
14733   } else {
14734     index = finger_index + JSFunctionResultCache::kEntrySize;
14735     if (index == cache_handle->length()) {
14736       index = JSFunctionResultCache::kEntriesIndex;
14737     }
14738   }
14739 
14740   ASSERT(index % 2 == 0);
14741   ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
14742   ASSERT(index < cache_handle->length());
14743 
14744   cache_handle->set(index, *key_handle);
14745   cache_handle->set(index + 1, *value);
14746   cache_handle->set_finger_index(index);
14747 
14748 #ifdef VERIFY_HEAP
14749   if (FLAG_verify_heap) {
14750     cache_handle->JSFunctionResultCacheVerify();
14751   }
14752 #endif
14753 
14754   return *value;
14755 }
14756 
14757 
RUNTIME_FUNCTION(Runtime_MessageGetStartPosition)14758 RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) {
14759   SealHandleScope shs(isolate);
14760   ASSERT(args.length() == 1);
14761   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14762   return Smi::FromInt(message->start_position());
14763 }
14764 
14765 
RUNTIME_FUNCTION(Runtime_MessageGetScript)14766 RUNTIME_FUNCTION(Runtime_MessageGetScript) {
14767   SealHandleScope shs(isolate);
14768   ASSERT(args.length() == 1);
14769   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14770   return message->script();
14771 }
14772 
14773 
14774 #ifdef DEBUG
14775 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
14776 // Exclude the code in release mode.
RUNTIME_FUNCTION(Runtime_ListNatives)14777 RUNTIME_FUNCTION(Runtime_ListNatives) {
14778   HandleScope scope(isolate);
14779   ASSERT(args.length() == 0);
14780 #define COUNT_ENTRY(Name, argc, ressize) + 1
14781   int entry_count = 0
14782       RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14783       RUNTIME_HIDDEN_FUNCTION_LIST(COUNT_ENTRY)
14784       INLINE_FUNCTION_LIST(COUNT_ENTRY)
14785       INLINE_OPTIMIZED_FUNCTION_LIST(COUNT_ENTRY);
14786 #undef COUNT_ENTRY
14787   Factory* factory = isolate->factory();
14788   Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14789   int index = 0;
14790   bool inline_runtime_functions = false;
14791 #define ADD_ENTRY(Name, argc, ressize)                                       \
14792   {                                                                          \
14793     HandleScope inner(isolate);                                              \
14794     Handle<String> name;                                                     \
14795     /* Inline runtime functions have an underscore in front of the name. */  \
14796     if (inline_runtime_functions) {                                          \
14797       name = factory->NewStringFromStaticAscii("_" #Name);                   \
14798     } else {                                                                 \
14799       name = factory->NewStringFromStaticAscii(#Name);                       \
14800     }                                                                        \
14801     Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
14802     pair_elements->set(0, *name);                                            \
14803     pair_elements->set(1, Smi::FromInt(argc));                               \
14804     Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
14805     elements->set(index++, *pair);                                           \
14806   }
14807   inline_runtime_functions = false;
14808   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14809   INLINE_OPTIMIZED_FUNCTION_LIST(ADD_ENTRY)
14810   // Calling hidden runtime functions should just throw.
14811   RUNTIME_HIDDEN_FUNCTION_LIST(ADD_ENTRY)
14812   inline_runtime_functions = true;
14813   INLINE_FUNCTION_LIST(ADD_ENTRY)
14814 #undef ADD_ENTRY
14815   ASSERT_EQ(index, entry_count);
14816   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14817   return *result;
14818 }
14819 #endif
14820 
14821 
RUNTIME_FUNCTION(Runtime_IS_VAR)14822 RUNTIME_FUNCTION(Runtime_IS_VAR) {
14823   UNREACHABLE();  // implemented as macro in the parser
14824   return NULL;
14825 }
14826 
14827 
14828 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
14829   RUNTIME_FUNCTION(Runtime_Has##Name) {          \
14830     CONVERT_ARG_CHECKED(JSObject, obj, 0);                \
14831     return isolate->heap()->ToBoolean(obj->Has##Name());  \
14832   }
14833 
14834 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)14835 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14836 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14837 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14838 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14839 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14840 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
14841 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14842 // Properties test sitting with elements tests - not fooling anyone.
14843 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
14844 
14845 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14846 
14847 
14848 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size)     \
14849   RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) {             \
14850     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                     \
14851     return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements());     \
14852   }
14853 
14854 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
14855 
14856 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14857 
14858 
14859 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s)  \
14860   RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) {                \
14861     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                     \
14862     return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements());        \
14863   }
14864 
14865 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
14866 
14867 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14868 
14869 
14870 RUNTIME_FUNCTION(Runtime_HaveSameMap) {
14871   SealHandleScope shs(isolate);
14872   ASSERT(args.length() == 2);
14873   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14874   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14875   return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14876 }
14877 
14878 
RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy)14879 RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
14880   SealHandleScope shs(isolate);
14881   ASSERT(args.length() == 1);
14882   CONVERT_ARG_CHECKED(Object, obj, 0);
14883   return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
14884 }
14885 
14886 
RUNTIME_FUNCTION(Runtime_IsObserved)14887 RUNTIME_FUNCTION(Runtime_IsObserved) {
14888   SealHandleScope shs(isolate);
14889   ASSERT(args.length() == 1);
14890 
14891   if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14892   CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
14893   ASSERT(!obj->IsJSGlobalProxy() || !obj->map()->is_observed());
14894   return isolate->heap()->ToBoolean(obj->map()->is_observed());
14895 }
14896 
14897 
RUNTIME_FUNCTION(Runtime_SetIsObserved)14898 RUNTIME_FUNCTION(Runtime_SetIsObserved) {
14899   HandleScope scope(isolate);
14900   ASSERT(args.length() == 1);
14901   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
14902   RUNTIME_ASSERT(!obj->IsJSGlobalProxy());
14903   if (obj->IsJSProxy()) return isolate->heap()->undefined_value();
14904   RUNTIME_ASSERT(!obj->map()->is_observed());
14905 
14906   ASSERT(obj->IsJSObject());
14907   JSObject::SetObserved(Handle<JSObject>::cast(obj));
14908   return isolate->heap()->undefined_value();
14909 }
14910 
14911 
RUNTIME_FUNCTION(Runtime_EnqueueMicrotask)14912 RUNTIME_FUNCTION(Runtime_EnqueueMicrotask) {
14913   HandleScope scope(isolate);
14914   ASSERT(args.length() == 1);
14915   CONVERT_ARG_HANDLE_CHECKED(JSFunction, microtask, 0);
14916   isolate->EnqueueMicrotask(microtask);
14917   return isolate->heap()->undefined_value();
14918 }
14919 
14920 
RUNTIME_FUNCTION(Runtime_RunMicrotasks)14921 RUNTIME_FUNCTION(Runtime_RunMicrotasks) {
14922   HandleScope scope(isolate);
14923   ASSERT(args.length() == 0);
14924   isolate->RunMicrotasks();
14925   return isolate->heap()->undefined_value();
14926 }
14927 
14928 
RUNTIME_FUNCTION(Runtime_GetObservationState)14929 RUNTIME_FUNCTION(Runtime_GetObservationState) {
14930   SealHandleScope shs(isolate);
14931   ASSERT(args.length() == 0);
14932   return isolate->heap()->observation_state();
14933 }
14934 
14935 
RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate)14936 RUNTIME_FUNCTION(Runtime_ObservationWeakMapCreate) {
14937   HandleScope scope(isolate);
14938   ASSERT(args.length() == 0);
14939   // TODO(adamk): Currently this runtime function is only called three times per
14940   // isolate. If it's called more often, the map should be moved into the
14941   // strong root list.
14942   Handle<Map> map =
14943       isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
14944   Handle<JSWeakMap> weakmap =
14945       Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
14946   return *WeakCollectionInitialize(isolate, weakmap);
14947 }
14948 
14949 
ContextsHaveSameOrigin(Handle<Context> context1,Handle<Context> context2)14950 static bool ContextsHaveSameOrigin(Handle<Context> context1,
14951                                    Handle<Context> context2) {
14952   return context1->security_token() == context2->security_token();
14953 }
14954 
14955 
RUNTIME_FUNCTION(Runtime_ObserverObjectAndRecordHaveSameOrigin)14956 RUNTIME_FUNCTION(Runtime_ObserverObjectAndRecordHaveSameOrigin) {
14957   HandleScope scope(isolate);
14958   ASSERT(args.length() == 3);
14959   CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
14960   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
14961   CONVERT_ARG_HANDLE_CHECKED(JSObject, record, 2);
14962 
14963   Handle<Context> observer_context(observer->context()->native_context(),
14964       isolate);
14965   Handle<Context> object_context(object->GetCreationContext());
14966   Handle<Context> record_context(record->GetCreationContext());
14967 
14968   return isolate->heap()->ToBoolean(
14969       ContextsHaveSameOrigin(object_context, observer_context) &&
14970       ContextsHaveSameOrigin(object_context, record_context));
14971 }
14972 
14973 
RUNTIME_FUNCTION(Runtime_ObjectWasCreatedInCurrentOrigin)14974 RUNTIME_FUNCTION(Runtime_ObjectWasCreatedInCurrentOrigin) {
14975   HandleScope scope(isolate);
14976   ASSERT(args.length() == 1);
14977   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
14978 
14979   Handle<Context> creation_context(object->GetCreationContext(), isolate);
14980   return isolate->heap()->ToBoolean(
14981       ContextsHaveSameOrigin(creation_context, isolate->native_context()));
14982 }
14983 
14984 
RUNTIME_FUNCTION(Runtime_GetObjectContextObjectObserve)14985 RUNTIME_FUNCTION(Runtime_GetObjectContextObjectObserve) {
14986   HandleScope scope(isolate);
14987   ASSERT(args.length() == 1);
14988   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
14989 
14990   Handle<Context> context(object->GetCreationContext(), isolate);
14991   return context->native_object_observe();
14992 }
14993 
14994 
RUNTIME_FUNCTION(Runtime_GetObjectContextObjectGetNotifier)14995 RUNTIME_FUNCTION(Runtime_GetObjectContextObjectGetNotifier) {
14996   HandleScope scope(isolate);
14997   ASSERT(args.length() == 1);
14998   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
14999 
15000   Handle<Context> context(object->GetCreationContext(), isolate);
15001   return context->native_object_get_notifier();
15002 }
15003 
15004 
RUNTIME_FUNCTION(Runtime_GetObjectContextNotifierPerformChange)15005 RUNTIME_FUNCTION(Runtime_GetObjectContextNotifierPerformChange) {
15006   HandleScope scope(isolate);
15007   ASSERT(args.length() == 1);
15008   CONVERT_ARG_HANDLE_CHECKED(JSObject, object_info, 0);
15009 
15010   Handle<Context> context(object_info->GetCreationContext(), isolate);
15011   return context->native_object_notifier_perform_change();
15012 }
15013 
15014 
ArrayConstructorCommon(Isolate * isolate,Handle<JSFunction> constructor,Handle<AllocationSite> site,Arguments * caller_args)15015 static Object* ArrayConstructorCommon(Isolate* isolate,
15016                                            Handle<JSFunction> constructor,
15017                                            Handle<AllocationSite> site,
15018                                            Arguments* caller_args) {
15019   Factory* factory = isolate->factory();
15020 
15021   bool holey = false;
15022   bool can_use_type_feedback = true;
15023   if (caller_args->length() == 1) {
15024     Handle<Object> argument_one = caller_args->at<Object>(0);
15025     if (argument_one->IsSmi()) {
15026       int value = Handle<Smi>::cast(argument_one)->value();
15027       if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
15028         // the array is a dictionary in this case.
15029         can_use_type_feedback = false;
15030       } else if (value != 0) {
15031         holey = true;
15032       }
15033     } else {
15034       // Non-smi length argument produces a dictionary
15035       can_use_type_feedback = false;
15036     }
15037   }
15038 
15039   Handle<JSArray> array;
15040   if (!site.is_null() && can_use_type_feedback) {
15041     ElementsKind to_kind = site->GetElementsKind();
15042     if (holey && !IsFastHoleyElementsKind(to_kind)) {
15043       to_kind = GetHoleyElementsKind(to_kind);
15044       // Update the allocation site info to reflect the advice alteration.
15045       site->SetElementsKind(to_kind);
15046     }
15047 
15048     // We should allocate with an initial map that reflects the allocation site
15049     // advice. Therefore we use AllocateJSObjectFromMap instead of passing
15050     // the constructor.
15051     Handle<Map> initial_map(constructor->initial_map(), isolate);
15052     if (to_kind != initial_map->elements_kind()) {
15053       initial_map = Map::AsElementsKind(initial_map, to_kind);
15054     }
15055 
15056     // If we don't care to track arrays of to_kind ElementsKind, then
15057     // don't emit a memento for them.
15058     Handle<AllocationSite> allocation_site;
15059     if (AllocationSite::GetMode(to_kind) == TRACK_ALLOCATION_SITE) {
15060       allocation_site = site;
15061     }
15062 
15063     array = Handle<JSArray>::cast(factory->NewJSObjectFromMap(
15064         initial_map, NOT_TENURED, true, allocation_site));
15065   } else {
15066     array = Handle<JSArray>::cast(factory->NewJSObject(constructor));
15067 
15068     // We might need to transition to holey
15069     ElementsKind kind = constructor->initial_map()->elements_kind();
15070     if (holey && !IsFastHoleyElementsKind(kind)) {
15071       kind = GetHoleyElementsKind(kind);
15072       JSObject::TransitionElementsKind(array, kind);
15073     }
15074   }
15075 
15076   factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
15077 
15078   ElementsKind old_kind = array->GetElementsKind();
15079   RETURN_FAILURE_ON_EXCEPTION(
15080       isolate, ArrayConstructInitializeElements(array, caller_args));
15081   if (!site.is_null() &&
15082       (old_kind != array->GetElementsKind() ||
15083        !can_use_type_feedback)) {
15084     // The arguments passed in caused a transition. This kind of complexity
15085     // can't be dealt with in the inlined hydrogen array constructor case.
15086     // We must mark the allocationsite as un-inlinable.
15087     site->SetDoNotInlineCall();
15088   }
15089   return *array;
15090 }
15091 
15092 
RUNTIME_FUNCTION(RuntimeHidden_ArrayConstructor)15093 RUNTIME_FUNCTION(RuntimeHidden_ArrayConstructor) {
15094   HandleScope scope(isolate);
15095   // If we get 2 arguments then they are the stub parameters (constructor, type
15096   // info).  If we get 4, then the first one is a pointer to the arguments
15097   // passed by the caller, and the last one is the length of the arguments
15098   // passed to the caller (redundant, but useful to check on the deoptimizer
15099   // with an assert).
15100   Arguments empty_args(0, NULL);
15101   bool no_caller_args = args.length() == 2;
15102   ASSERT(no_caller_args || args.length() == 4);
15103   int parameters_start = no_caller_args ? 0 : 1;
15104   Arguments* caller_args = no_caller_args
15105       ? &empty_args
15106       : reinterpret_cast<Arguments*>(args[0]);
15107   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15108   CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
15109 #ifdef DEBUG
15110   if (!no_caller_args) {
15111     CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
15112     ASSERT(arg_count == caller_args->length());
15113   }
15114 #endif
15115 
15116   Handle<AllocationSite> site;
15117   if (!type_info.is_null() &&
15118       *type_info != isolate->heap()->undefined_value()) {
15119     site = Handle<AllocationSite>::cast(type_info);
15120     ASSERT(!site->SitePointsToLiteral());
15121   }
15122 
15123   return ArrayConstructorCommon(isolate,
15124                                 constructor,
15125                                 site,
15126                                 caller_args);
15127 }
15128 
15129 
RUNTIME_FUNCTION(RuntimeHidden_InternalArrayConstructor)15130 RUNTIME_FUNCTION(RuntimeHidden_InternalArrayConstructor) {
15131   HandleScope scope(isolate);
15132   Arguments empty_args(0, NULL);
15133   bool no_caller_args = args.length() == 1;
15134   ASSERT(no_caller_args || args.length() == 3);
15135   int parameters_start = no_caller_args ? 0 : 1;
15136   Arguments* caller_args = no_caller_args
15137       ? &empty_args
15138       : reinterpret_cast<Arguments*>(args[0]);
15139   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15140 #ifdef DEBUG
15141   if (!no_caller_args) {
15142     CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
15143     ASSERT(arg_count == caller_args->length());
15144   }
15145 #endif
15146   return ArrayConstructorCommon(isolate,
15147                                 constructor,
15148                                 Handle<AllocationSite>::null(),
15149                                 caller_args);
15150 }
15151 
15152 
RUNTIME_FUNCTION(Runtime_MaxSmi)15153 RUNTIME_FUNCTION(Runtime_MaxSmi) {
15154   ASSERT(args.length() == 0);
15155   return Smi::FromInt(Smi::kMaxValue);
15156 }
15157 
15158 
15159 // ----------------------------------------------------------------------------
15160 // Implementation of Runtime
15161 
15162 #define F(name, number_of_args, result_size)                             \
15163   { Runtime::k##name, Runtime::RUNTIME, #name,   \
15164     FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
15165 
15166 
15167 #define FH(name, number_of_args, result_size)                             \
15168   { Runtime::kHidden##name, Runtime::RUNTIME_HIDDEN, NULL,   \
15169     FUNCTION_ADDR(RuntimeHidden_##name), number_of_args, result_size },
15170 
15171 
15172 #define I(name, number_of_args, result_size)                             \
15173   { Runtime::kInline##name, Runtime::INLINE,     \
15174     "_" #name, NULL, number_of_args, result_size },
15175 
15176 
15177 #define IO(name, number_of_args, result_size) \
15178   { Runtime::kInlineOptimized##name, Runtime::INLINE_OPTIMIZED, \
15179     "_" #name, FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
15180 
15181 
15182 static const Runtime::Function kIntrinsicFunctions[] = {
15183   RUNTIME_FUNCTION_LIST(F)
15184   INLINE_OPTIMIZED_FUNCTION_LIST(F)
15185   RUNTIME_HIDDEN_FUNCTION_LIST(FH)
15186   INLINE_FUNCTION_LIST(I)
15187   INLINE_OPTIMIZED_FUNCTION_LIST(IO)
15188 };
15189 
15190 #undef IO
15191 #undef I
15192 #undef FH
15193 #undef F
15194 
15195 
InitializeIntrinsicFunctionNames(Isolate * isolate,Handle<NameDictionary> dict)15196 void Runtime::InitializeIntrinsicFunctionNames(Isolate* isolate,
15197                                                Handle<NameDictionary> dict) {
15198   ASSERT(dict->NumberOfElements() == 0);
15199   HandleScope scope(isolate);
15200   for (int i = 0; i < kNumFunctions; ++i) {
15201     const char* name = kIntrinsicFunctions[i].name;
15202     if (name == NULL) continue;
15203     Handle<NameDictionary> new_dict = NameDictionary::Add(
15204         dict,
15205         isolate->factory()->InternalizeUtf8String(name),
15206         Handle<Smi>(Smi::FromInt(i), isolate),
15207         PropertyDetails(NONE, NORMAL, Representation::None()));
15208     // The dictionary does not need to grow.
15209     CHECK(new_dict.is_identical_to(dict));
15210   }
15211 }
15212 
15213 
FunctionForName(Handle<String> name)15214 const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
15215   Heap* heap = name->GetHeap();
15216   int entry = heap->intrinsic_function_names()->FindEntry(name);
15217   if (entry != kNotFound) {
15218     Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
15219     int function_index = Smi::cast(smi_index)->value();
15220     return &(kIntrinsicFunctions[function_index]);
15221   }
15222   return NULL;
15223 }
15224 
15225 
FunctionForId(Runtime::FunctionId id)15226 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
15227   return &(kIntrinsicFunctions[static_cast<int>(id)]);
15228 }
15229 
15230 } }  // namespace v8::internal
15231