• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdlib.h>
29 #include <limits>
30 
31 #include "v8.h"
32 
33 #include "accessors.h"
34 #include "allocation-site-scopes.h"
35 #include "api.h"
36 #include "arguments.h"
37 #include "bootstrapper.h"
38 #include "codegen.h"
39 #include "compilation-cache.h"
40 #include "compiler.h"
41 #include "cpu.h"
42 #include "cpu-profiler.h"
43 #include "dateparser-inl.h"
44 #include "debug.h"
45 #include "deoptimizer.h"
46 #include "date.h"
47 #include "execution.h"
48 #include "full-codegen.h"
49 #include "global-handles.h"
50 #include "isolate-inl.h"
51 #include "jsregexp.h"
52 #include "jsregexp-inl.h"
53 #include "json-parser.h"
54 #include "json-stringifier.h"
55 #include "liveedit.h"
56 #include "misc-intrinsics.h"
57 #include "parser.h"
58 #include "platform.h"
59 #include "runtime-profiler.h"
60 #include "runtime.h"
61 #include "scopeinfo.h"
62 #include "smart-pointers.h"
63 #include "string-search.h"
64 #include "stub-cache.h"
65 #include "uri.h"
66 #include "v8conversions.h"
67 #include "v8threads.h"
68 #include "vm-state-inl.h"
69 
70 #ifdef V8_I18N_SUPPORT
71 #include "i18n.h"
72 #include "unicode/brkiter.h"
73 #include "unicode/calendar.h"
74 #include "unicode/coll.h"
75 #include "unicode/curramt.h"
76 #include "unicode/datefmt.h"
77 #include "unicode/dcfmtsym.h"
78 #include "unicode/decimfmt.h"
79 #include "unicode/dtfmtsym.h"
80 #include "unicode/dtptngen.h"
81 #include "unicode/locid.h"
82 #include "unicode/numfmt.h"
83 #include "unicode/numsys.h"
84 #include "unicode/rbbi.h"
85 #include "unicode/smpdtfmt.h"
86 #include "unicode/timezone.h"
87 #include "unicode/uchar.h"
88 #include "unicode/ucol.h"
89 #include "unicode/ucurr.h"
90 #include "unicode/uloc.h"
91 #include "unicode/unum.h"
92 #include "unicode/uversion.h"
93 #endif
94 
95 #ifndef _STLP_VENDOR_CSTD
96 // STLPort doesn't import fpclassify and isless into the std namespace.
97 using std::fpclassify;
98 using std::isless;
99 #endif
100 
101 namespace v8 {
102 namespace internal {
103 
104 
105 #define RUNTIME_ASSERT(value) \
106   if (!(value)) return isolate->ThrowIllegalOperation();
107 
108 // Cast the given object to a value of the specified type and store
109 // it in a variable with the given name.  If the object is not of the
110 // expected type call IllegalOperation and return.
111 #define CONVERT_ARG_CHECKED(Type, name, index)                       \
112   RUNTIME_ASSERT(args[index]->Is##Type());                           \
113   Type* name = Type::cast(args[index]);
114 
115 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
116   RUNTIME_ASSERT(args[index]->Is##Type());                           \
117   Handle<Type> name = args.at<Type>(index);
118 
119 // Cast the given object to a boolean and store it in a variable with
120 // the given name.  If the object is not a boolean call IllegalOperation
121 // and return.
122 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
123   RUNTIME_ASSERT(args[index]->IsBoolean());                          \
124   bool name = args[index]->IsTrue();
125 
126 // Cast the given argument to a Smi and store its value in an int variable
127 // with the given name.  If the argument is not a Smi call IllegalOperation
128 // and return.
129 #define CONVERT_SMI_ARG_CHECKED(name, index)                         \
130   RUNTIME_ASSERT(args[index]->IsSmi());                              \
131   int name = args.smi_at(index);
132 
133 // Cast the given argument to a double and store it in a variable with
134 // the given name.  If the argument is not a number (as opposed to
135 // the number not-a-number) call IllegalOperation and return.
136 #define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
137   RUNTIME_ASSERT(args[index]->IsNumber());                           \
138   double name = args.number_at(index);
139 
140 // Call the specified converter on the object *comand store the result in
141 // a variable of the specified type with the given name.  If the
142 // object is not a Number call IllegalOperation and return.
143 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
144   RUNTIME_ASSERT(obj->IsNumber());                                   \
145   type name = NumberTo##Type(obj);
146 
147 
148 // Cast the given argument to PropertyDetails and store its value in a
149 // variable with the given name.  If the argument is not a Smi call
150 // IllegalOperation and return.
151 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
152   RUNTIME_ASSERT(args[index]->IsSmi());                              \
153   PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
154 
155 
156 // Assert that the given argument has a valid value for a StrictModeFlag
157 // and store it in a StrictModeFlag variable with the given name.
158 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
159   RUNTIME_ASSERT(args[index]->IsSmi());                              \
160   RUNTIME_ASSERT(args.smi_at(index) == kStrictMode ||                \
161                  args.smi_at(index) == kNonStrictMode);              \
162   StrictModeFlag name =                                              \
163       static_cast<StrictModeFlag>(args.smi_at(index));
164 
165 
166 // Assert that the given argument has a valid value for a LanguageMode
167 // and store it in a LanguageMode variable with the given name.
168 #define CONVERT_LANGUAGE_MODE_ARG(name, index)                       \
169   ASSERT(args[index]->IsSmi());                                      \
170   ASSERT(args.smi_at(index) == CLASSIC_MODE ||                       \
171          args.smi_at(index) == STRICT_MODE ||                        \
172          args.smi_at(index) == EXTENDED_MODE);                       \
173   LanguageMode name =                                                \
174       static_cast<LanguageMode>(args.smi_at(index));
175 
176 
ComputeObjectLiteralMap(Handle<Context> context,Handle<FixedArray> constant_properties,bool * is_result_from_cache)177 static Handle<Map> ComputeObjectLiteralMap(
178     Handle<Context> context,
179     Handle<FixedArray> constant_properties,
180     bool* is_result_from_cache) {
181   Isolate* isolate = context->GetIsolate();
182   int properties_length = constant_properties->length();
183   int number_of_properties = properties_length / 2;
184   // Check that there are only internal strings and array indices among keys.
185   int number_of_string_keys = 0;
186   for (int p = 0; p != properties_length; p += 2) {
187     Object* key = constant_properties->get(p);
188     uint32_t element_index = 0;
189     if (key->IsInternalizedString()) {
190       number_of_string_keys++;
191     } else if (key->ToArrayIndex(&element_index)) {
192       // An index key does not require space in the property backing store.
193       number_of_properties--;
194     } else {
195       // Bail out as a non-internalized-string non-index key makes caching
196       // impossible.
197       // ASSERT to make sure that the if condition after the loop is false.
198       ASSERT(number_of_string_keys != number_of_properties);
199       break;
200     }
201   }
202   // If we only have internalized strings and array indices among keys then we
203   // can use the map cache in the native context.
204   const int kMaxKeys = 10;
205   if ((number_of_string_keys == number_of_properties) &&
206       (number_of_string_keys < kMaxKeys)) {
207     // Create the fixed array with the key.
208     Handle<FixedArray> keys =
209         isolate->factory()->NewFixedArray(number_of_string_keys);
210     if (number_of_string_keys > 0) {
211       int index = 0;
212       for (int p = 0; p < properties_length; p += 2) {
213         Object* key = constant_properties->get(p);
214         if (key->IsInternalizedString()) {
215           keys->set(index++, key);
216         }
217       }
218       ASSERT(index == number_of_string_keys);
219     }
220     *is_result_from_cache = true;
221     return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
222   }
223   *is_result_from_cache = false;
224   return isolate->factory()->CopyMap(
225       Handle<Map>(context->object_function()->initial_map()),
226       number_of_properties);
227 }
228 
229 
230 static Handle<Object> CreateLiteralBoilerplate(
231     Isolate* isolate,
232     Handle<FixedArray> literals,
233     Handle<FixedArray> constant_properties);
234 
235 
CreateObjectLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> constant_properties,bool should_have_fast_elements,bool has_function_literal)236 static Handle<Object> CreateObjectLiteralBoilerplate(
237     Isolate* isolate,
238     Handle<FixedArray> literals,
239     Handle<FixedArray> constant_properties,
240     bool should_have_fast_elements,
241     bool has_function_literal) {
242   // Get the native context from the literals array.  This is the
243   // context in which the function was created and we use the object
244   // function from this context to create the object literal.  We do
245   // not use the object function from the current native context
246   // because this might be the object function from another context
247   // which we should not have access to.
248   Handle<Context> context =
249       Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
250 
251   // In case we have function literals, we want the object to be in
252   // slow properties mode for now. We don't go in the map cache because
253   // maps with constant functions can't be shared if the functions are
254   // not the same (which is the common case).
255   bool is_result_from_cache = false;
256   Handle<Map> map = has_function_literal
257       ? Handle<Map>(context->object_function()->initial_map())
258       : ComputeObjectLiteralMap(context,
259                                 constant_properties,
260                                 &is_result_from_cache);
261 
262   Handle<JSObject> boilerplate =
263       isolate->factory()->NewJSObjectFromMap(
264           map, isolate->heap()->GetPretenureMode());
265 
266   // Normalize the elements of the boilerplate to save space if needed.
267   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
268 
269   // Add the constant properties to the boilerplate.
270   int length = constant_properties->length();
271   bool should_transform =
272       !is_result_from_cache && boilerplate->HasFastProperties();
273   if (should_transform || has_function_literal) {
274     // Normalize the properties of object to avoid n^2 behavior
275     // when extending the object multiple properties. Indicate the number of
276     // properties to be added.
277     JSObject::NormalizeProperties(
278         boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
279   }
280 
281   // TODO(verwaest): Support tracking representations in the boilerplate.
282   for (int index = 0; index < length; index +=2) {
283     Handle<Object> key(constant_properties->get(index+0), isolate);
284     Handle<Object> value(constant_properties->get(index+1), isolate);
285     if (value->IsFixedArray()) {
286       // The value contains the constant_properties of a
287       // simple object or array literal.
288       Handle<FixedArray> array = Handle<FixedArray>::cast(value);
289       value = CreateLiteralBoilerplate(isolate, literals, array);
290       if (value.is_null()) return value;
291     }
292     Handle<Object> result;
293     uint32_t element_index = 0;
294     StoreMode mode = value->IsJSObject() ? FORCE_FIELD : ALLOW_AS_CONSTANT;
295     if (key->IsInternalizedString()) {
296       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
297         // Array index as string (uint32).
298         result = JSObject::SetOwnElement(
299             boilerplate, element_index, value, kNonStrictMode);
300       } else {
301         Handle<String> name(String::cast(*key));
302         ASSERT(!name->AsArrayIndex(&element_index));
303         result = JSObject::SetLocalPropertyIgnoreAttributes(
304             boilerplate, name, value, NONE,
305             Object::OPTIMAL_REPRESENTATION, mode);
306       }
307     } else if (key->ToArrayIndex(&element_index)) {
308       // Array index (uint32).
309       result = JSObject::SetOwnElement(
310           boilerplate, element_index, value, kNonStrictMode);
311     } else {
312       // Non-uint32 number.
313       ASSERT(key->IsNumber());
314       double num = key->Number();
315       char arr[100];
316       Vector<char> buffer(arr, ARRAY_SIZE(arr));
317       const char* str = DoubleToCString(num, buffer);
318       Handle<String> name =
319           isolate->factory()->NewStringFromAscii(CStrVector(str));
320       result = JSObject::SetLocalPropertyIgnoreAttributes(
321           boilerplate, name, value, NONE,
322           Object::OPTIMAL_REPRESENTATION, mode);
323     }
324     // If setting the property on the boilerplate throws an
325     // exception, the exception is converted to an empty handle in
326     // the handle based operations.  In that case, we need to
327     // convert back to an exception.
328     if (result.is_null()) return result;
329   }
330 
331   // Transform to fast properties if necessary. For object literals with
332   // containing function literals we defer this operation until after all
333   // computed properties have been assigned so that we can generate
334   // constant function properties.
335   if (should_transform && !has_function_literal) {
336     JSObject::TransformToFastProperties(
337         boilerplate, boilerplate->map()->unused_property_fields());
338   }
339 
340   return boilerplate;
341 }
342 
343 
TransitionElements(Handle<Object> object,ElementsKind to_kind,Isolate * isolate)344 MaybeObject* TransitionElements(Handle<Object> object,
345                                 ElementsKind to_kind,
346                                 Isolate* isolate) {
347   HandleScope scope(isolate);
348   if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
349   ElementsKind from_kind =
350       Handle<JSObject>::cast(object)->map()->elements_kind();
351   if (Map::IsValidElementsTransition(from_kind, to_kind)) {
352     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
353     return *object;
354   }
355   return isolate->ThrowIllegalOperation();
356 }
357 
358 
359 static const int kSmiLiteralMinimumLength = 1024;
360 
361 
CreateArrayLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> elements)362 Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
363     Isolate* isolate,
364     Handle<FixedArray> literals,
365     Handle<FixedArray> elements) {
366   // Create the JSArray.
367   Handle<JSFunction> constructor(
368       JSFunction::NativeContextFromLiterals(*literals)->array_function());
369 
370   Handle<JSArray> object = Handle<JSArray>::cast(
371       isolate->factory()->NewJSObject(
372           constructor, isolate->heap()->GetPretenureMode()));
373 
374   ElementsKind constant_elements_kind =
375       static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
376   Handle<FixedArrayBase> constant_elements_values(
377       FixedArrayBase::cast(elements->get(1)));
378 
379   ASSERT(IsFastElementsKind(constant_elements_kind));
380   Context* native_context = isolate->context()->native_context();
381   Object* maybe_maps_array = native_context->js_array_maps();
382   ASSERT(!maybe_maps_array->IsUndefined());
383   Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
384       constant_elements_kind);
385   ASSERT(maybe_map->IsMap());
386   object->set_map(Map::cast(maybe_map));
387 
388   Handle<FixedArrayBase> copied_elements_values;
389   if (IsFastDoubleElementsKind(constant_elements_kind)) {
390     ASSERT(FLAG_smi_only_arrays);
391     copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
392         Handle<FixedDoubleArray>::cast(constant_elements_values));
393   } else {
394     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
395     const bool is_cow =
396         (constant_elements_values->map() ==
397          isolate->heap()->fixed_cow_array_map());
398     if (is_cow) {
399       copied_elements_values = constant_elements_values;
400 #if DEBUG
401       Handle<FixedArray> fixed_array_values =
402           Handle<FixedArray>::cast(copied_elements_values);
403       for (int i = 0; i < fixed_array_values->length(); i++) {
404         ASSERT(!fixed_array_values->get(i)->IsFixedArray());
405       }
406 #endif
407     } else {
408       Handle<FixedArray> fixed_array_values =
409           Handle<FixedArray>::cast(constant_elements_values);
410       Handle<FixedArray> fixed_array_values_copy =
411           isolate->factory()->CopyFixedArray(fixed_array_values);
412       copied_elements_values = fixed_array_values_copy;
413       for (int i = 0; i < fixed_array_values->length(); i++) {
414         Object* current = fixed_array_values->get(i);
415         if (current->IsFixedArray()) {
416           // The value contains the constant_properties of a
417           // simple object or array literal.
418           Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
419           Handle<Object> result =
420               CreateLiteralBoilerplate(isolate, literals, fa);
421           if (result.is_null()) return result;
422           fixed_array_values_copy->set(i, *result);
423         }
424       }
425     }
426   }
427   object->set_elements(*copied_elements_values);
428   object->set_length(Smi::FromInt(copied_elements_values->length()));
429 
430   //  Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
431   //  on or the object is larger than the threshold.
432   if (!FLAG_smi_only_arrays &&
433       constant_elements_values->length() < kSmiLiteralMinimumLength) {
434     ElementsKind elements_kind = object->GetElementsKind();
435     if (!IsFastObjectElementsKind(elements_kind)) {
436       if (IsFastHoleyElementsKind(elements_kind)) {
437         CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
438                                   isolate)->IsFailure());
439       } else {
440         CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
441       }
442     }
443   }
444 
445   object->ValidateElements();
446   return object;
447 }
448 
449 
CreateLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> array)450 static Handle<Object> CreateLiteralBoilerplate(
451     Isolate* isolate,
452     Handle<FixedArray> literals,
453     Handle<FixedArray> array) {
454   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
455   const bool kHasNoFunctionLiteral = false;
456   switch (CompileTimeValue::GetLiteralType(array)) {
457     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
458       return CreateObjectLiteralBoilerplate(isolate,
459                                             literals,
460                                             elements,
461                                             true,
462                                             kHasNoFunctionLiteral);
463     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
464       return CreateObjectLiteralBoilerplate(isolate,
465                                             literals,
466                                             elements,
467                                             false,
468                                             kHasNoFunctionLiteral);
469     case CompileTimeValue::ARRAY_LITERAL:
470       return Runtime::CreateArrayLiteralBoilerplate(
471           isolate, literals, elements);
472     default:
473       UNREACHABLE();
474       return Handle<Object>::null();
475   }
476 }
477 
478 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateObjectLiteral)479 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
480   HandleScope scope(isolate);
481   ASSERT(args.length() == 4);
482   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
483   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
484   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
485   CONVERT_SMI_ARG_CHECKED(flags, 3);
486   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
487   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
488 
489   // Check if boilerplate exists. If not, create it first.
490   Handle<Object> literal_site(literals->get(literals_index), isolate);
491   Handle<AllocationSite> site;
492   Handle<JSObject> boilerplate;
493   if (*literal_site == isolate->heap()->undefined_value()) {
494     Handle<Object> raw_boilerplate = CreateObjectLiteralBoilerplate(
495         isolate,
496         literals,
497         constant_properties,
498         should_have_fast_elements,
499         has_function_literal);
500     RETURN_IF_EMPTY_HANDLE(isolate, raw_boilerplate);
501     boilerplate = Handle<JSObject>::cast(raw_boilerplate);
502 
503     AllocationSiteCreationContext creation_context(isolate);
504     site = creation_context.EnterNewScope();
505     RETURN_IF_EMPTY_HANDLE(isolate,
506                            JSObject::DeepWalk(boilerplate, &creation_context));
507     creation_context.ExitScope(site, boilerplate);
508 
509     // Update the functions literal and return the boilerplate.
510     literals->set(literals_index, *site);
511   } else {
512     site = Handle<AllocationSite>::cast(literal_site);
513     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
514                                    isolate);
515   }
516 
517   AllocationSiteUsageContext usage_context(isolate, site, true);
518   usage_context.EnterNewScope();
519   Handle<Object> copy = JSObject::DeepCopy(boilerplate, &usage_context);
520   usage_context.ExitScope(site, boilerplate);
521   RETURN_IF_EMPTY_HANDLE(isolate, copy);
522   return *copy;
523 }
524 
525 
GetLiteralAllocationSite(Isolate * isolate,Handle<FixedArray> literals,int literals_index,Handle<FixedArray> elements)526 static Handle<AllocationSite> GetLiteralAllocationSite(
527     Isolate* isolate,
528     Handle<FixedArray> literals,
529     int literals_index,
530     Handle<FixedArray> elements) {
531   // Check if boilerplate exists. If not, create it first.
532   Handle<Object> literal_site(literals->get(literals_index), isolate);
533   Handle<AllocationSite> site;
534   if (*literal_site == isolate->heap()->undefined_value()) {
535     ASSERT(*elements != isolate->heap()->empty_fixed_array());
536     Handle<Object> boilerplate =
537         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
538     if (boilerplate.is_null()) return Handle<AllocationSite>::null();
539 
540     AllocationSiteCreationContext creation_context(isolate);
541     site = creation_context.EnterNewScope();
542     if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate),
543                            &creation_context).is_null()) {
544       return Handle<AllocationSite>::null();
545     }
546     creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
547 
548     literals->set(literals_index, *site);
549   } else {
550     site = Handle<AllocationSite>::cast(literal_site);
551   }
552 
553   return site;
554 }
555 
556 
CreateArrayLiteralImpl(Isolate * isolate,Handle<FixedArray> literals,int literals_index,Handle<FixedArray> elements,int flags)557 static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
558                                            Handle<FixedArray> literals,
559                                            int literals_index,
560                                            Handle<FixedArray> elements,
561                                            int flags) {
562   Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
563       literals_index, elements);
564   RETURN_IF_EMPTY_HANDLE(isolate, site);
565 
566   bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
567   Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
568   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
569   usage_context.EnterNewScope();
570   JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
571       ? JSObject::kNoHints
572       : JSObject::kObjectIsShallowArray;
573   Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
574                                              hints);
575   usage_context.ExitScope(site, boilerplate);
576   RETURN_IF_EMPTY_HANDLE(isolate, copy);
577   return *copy;
578 }
579 
580 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateArrayLiteral)581 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
582   HandleScope scope(isolate);
583   ASSERT(args.length() == 4);
584   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
585   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
586   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
587   CONVERT_SMI_ARG_CHECKED(flags, 3);
588 
589   return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
590                                 flags);
591 }
592 
593 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateArrayLiteralStubBailout)594 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralStubBailout) {
595   HandleScope scope(isolate);
596   ASSERT(args.length() == 3);
597   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
598   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
599   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
600 
601   return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
602                                 ArrayLiteral::kShallowElements);
603 }
604 
605 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateSymbol)606 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
607   HandleScope scope(isolate);
608   ASSERT(args.length() == 1);
609   Handle<Object> name(args[0], isolate);
610   RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
611   Symbol* symbol;
612   MaybeObject* maybe = isolate->heap()->AllocateSymbol();
613   if (!maybe->To(&symbol)) return maybe;
614   if (name->IsString()) symbol->set_name(*name);
615   return symbol;
616 }
617 
618 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreatePrivateSymbol)619 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreatePrivateSymbol) {
620   HandleScope scope(isolate);
621   ASSERT(args.length() == 1);
622   Handle<Object> name(args[0], isolate);
623   RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
624   Symbol* symbol;
625   MaybeObject* maybe = isolate->heap()->AllocatePrivateSymbol();
626   if (!maybe->To(&symbol)) return maybe;
627   if (name->IsString()) symbol->set_name(*name);
628   return symbol;
629 }
630 
631 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SymbolName)632 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
633   SealHandleScope shs(isolate);
634   ASSERT(args.length() == 1);
635   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
636   return symbol->name();
637 }
638 
639 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SymbolIsPrivate)640 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolIsPrivate) {
641   SealHandleScope shs(isolate);
642   ASSERT(args.length() == 1);
643   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
644   return isolate->heap()->ToBoolean(symbol->is_private());
645 }
646 
647 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateJSProxy)648 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
649   SealHandleScope shs(isolate);
650   ASSERT(args.length() == 2);
651   CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
652   Object* prototype = args[1];
653   Object* used_prototype =
654       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
655   return isolate->heap()->AllocateJSProxy(handler, used_prototype);
656 }
657 
658 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateJSFunctionProxy)659 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
660   SealHandleScope shs(isolate);
661   ASSERT(args.length() == 4);
662   CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
663   Object* call_trap = args[1];
664   RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
665   CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
666   Object* prototype = args[3];
667   Object* used_prototype =
668       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
669   return isolate->heap()->AllocateJSFunctionProxy(
670       handler, call_trap, construct_trap, used_prototype);
671 }
672 
673 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsJSProxy)674 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
675   SealHandleScope shs(isolate);
676   ASSERT(args.length() == 1);
677   Object* obj = args[0];
678   return isolate->heap()->ToBoolean(obj->IsJSProxy());
679 }
680 
681 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsJSFunctionProxy)682 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
683   SealHandleScope shs(isolate);
684   ASSERT(args.length() == 1);
685   Object* obj = args[0];
686   return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
687 }
688 
689 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetHandler)690 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
691   SealHandleScope shs(isolate);
692   ASSERT(args.length() == 1);
693   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
694   return proxy->handler();
695 }
696 
697 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetCallTrap)698 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
699   SealHandleScope shs(isolate);
700   ASSERT(args.length() == 1);
701   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
702   return proxy->call_trap();
703 }
704 
705 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetConstructTrap)706 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
707   SealHandleScope shs(isolate);
708   ASSERT(args.length() == 1);
709   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
710   return proxy->construct_trap();
711 }
712 
713 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Fix)714 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
715   HandleScope scope(isolate);
716   ASSERT(args.length() == 1);
717   CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
718   JSProxy::Fix(proxy);
719   return isolate->heap()->undefined_value();
720 }
721 
722 
FreeArrayBuffer(Isolate * isolate,JSArrayBuffer * phantom_array_buffer)723 void Runtime::FreeArrayBuffer(Isolate* isolate,
724                               JSArrayBuffer* phantom_array_buffer) {
725   if (phantom_array_buffer->should_be_freed()) {
726     ASSERT(phantom_array_buffer->is_external());
727     free(phantom_array_buffer->backing_store());
728   }
729   if (phantom_array_buffer->is_external()) return;
730 
731   size_t allocated_length = NumberToSize(
732       isolate, phantom_array_buffer->byte_length());
733 
734   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
735       -static_cast<int64_t>(allocated_length));
736   CHECK(V8::ArrayBufferAllocator() != NULL);
737   V8::ArrayBufferAllocator()->Free(
738       phantom_array_buffer->backing_store(),
739       allocated_length);
740 }
741 
742 
SetupArrayBuffer(Isolate * isolate,Handle<JSArrayBuffer> array_buffer,bool is_external,void * data,size_t allocated_length)743 void Runtime::SetupArrayBuffer(Isolate* isolate,
744                                Handle<JSArrayBuffer> array_buffer,
745                                bool is_external,
746                                void* data,
747                                size_t allocated_length) {
748   ASSERT(array_buffer->GetInternalFieldCount() ==
749       v8::ArrayBuffer::kInternalFieldCount);
750   for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
751     array_buffer->SetInternalField(i, Smi::FromInt(0));
752   }
753   array_buffer->set_backing_store(data);
754   array_buffer->set_flag(Smi::FromInt(0));
755   array_buffer->set_is_external(is_external);
756 
757   Handle<Object> byte_length =
758       isolate->factory()->NewNumberFromSize(allocated_length);
759   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
760   array_buffer->set_byte_length(*byte_length);
761 
762   array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
763   isolate->heap()->set_array_buffers_list(*array_buffer);
764   array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
765 }
766 
767 
SetupArrayBufferAllocatingData(Isolate * isolate,Handle<JSArrayBuffer> array_buffer,size_t allocated_length,bool initialize)768 bool Runtime::SetupArrayBufferAllocatingData(
769     Isolate* isolate,
770     Handle<JSArrayBuffer> array_buffer,
771     size_t allocated_length,
772     bool initialize) {
773   void* data;
774   CHECK(V8::ArrayBufferAllocator() != NULL);
775   if (allocated_length != 0) {
776     if (initialize) {
777       data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
778     } else {
779       data =
780         V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
781     }
782     if (data == NULL) return false;
783   } else {
784     data = NULL;
785   }
786 
787   SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
788 
789   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
790 
791   return true;
792 }
793 
794 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayBufferInitialize)795 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
796   HandleScope scope(isolate);
797   ASSERT(args.length() == 2);
798   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
799   CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
800   size_t allocated_length;
801   if (byteLength->IsSmi()) {
802     allocated_length = Smi::cast(*byteLength)->value();
803   } else {
804     ASSERT(byteLength->IsHeapNumber());
805     double value = HeapNumber::cast(*byteLength)->value();
806 
807     ASSERT(value >= 0);
808 
809     if (value > std::numeric_limits<size_t>::max()) {
810       return isolate->Throw(
811           *isolate->factory()->NewRangeError("invalid_array_buffer_length",
812             HandleVector<Object>(NULL, 0)));
813     }
814 
815     allocated_length = static_cast<size_t>(value);
816   }
817 
818   if (!Runtime::SetupArrayBufferAllocatingData(isolate,
819                                                holder, allocated_length)) {
820       return isolate->Throw(*isolate->factory()->
821           NewRangeError("invalid_array_buffer_length",
822             HandleVector<Object>(NULL, 0)));
823   }
824 
825   return *holder;
826 }
827 
828 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayBufferGetByteLength)829 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
830   SealHandleScope shs(isolate);
831   ASSERT(args.length() == 1);
832   CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
833   return holder->byte_length();
834 }
835 
836 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayBufferSliceImpl)837 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
838   HandleScope scope(isolate);
839   ASSERT(args.length() == 3);
840   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
841   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
842   CONVERT_DOUBLE_ARG_CHECKED(first, 2);
843   size_t start = static_cast<size_t>(first);
844   size_t target_length = NumberToSize(isolate, target->byte_length());
845 
846   if (target_length == 0) return isolate->heap()->undefined_value();
847 
848   ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
849   uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
850   uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
851   CopyBytes(target_data, source_data + start, target_length);
852   return isolate->heap()->undefined_value();
853 }
854 
855 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayBufferIsView)856 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) {
857   HandleScope scope(isolate);
858   ASSERT(args.length() == 1);
859   CONVERT_ARG_CHECKED(Object, object, 0);
860   return object->IsJSArrayBufferView()
861     ? isolate->heap()->true_value()
862     : isolate->heap()->false_value();
863 }
864 
865 
ArrayIdToTypeAndSize(int arrayId,ExternalArrayType * array_type,size_t * element_size)866 void Runtime::ArrayIdToTypeAndSize(
867     int arrayId, ExternalArrayType* array_type, size_t* element_size) {
868   switch (arrayId) {
869     case ARRAY_ID_UINT8:
870       *array_type = kExternalUnsignedByteArray;
871       *element_size = 1;
872       break;
873     case ARRAY_ID_INT8:
874       *array_type = kExternalByteArray;
875       *element_size = 1;
876       break;
877     case ARRAY_ID_UINT16:
878       *array_type = kExternalUnsignedShortArray;
879       *element_size = 2;
880       break;
881     case ARRAY_ID_INT16:
882       *array_type = kExternalShortArray;
883       *element_size = 2;
884       break;
885     case ARRAY_ID_UINT32:
886       *array_type = kExternalUnsignedIntArray;
887       *element_size = 4;
888       break;
889     case ARRAY_ID_INT32:
890       *array_type = kExternalIntArray;
891       *element_size = 4;
892       break;
893     case ARRAY_ID_FLOAT32:
894       *array_type = kExternalFloatArray;
895       *element_size = 4;
896       break;
897     case ARRAY_ID_FLOAT64:
898       *array_type = kExternalDoubleArray;
899       *element_size = 8;
900       break;
901     case ARRAY_ID_UINT8C:
902       *array_type = kExternalPixelArray;
903       *element_size = 1;
904       break;
905     default:
906       UNREACHABLE();
907   }
908 }
909 
910 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TypedArrayInitialize)911 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
912   HandleScope scope(isolate);
913   ASSERT(args.length() == 5);
914   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
915   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
916   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
917   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
918   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
919 
920   ASSERT(holder->GetInternalFieldCount() ==
921       v8::ArrayBufferView::kInternalFieldCount);
922   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
923     holder->SetInternalField(i, Smi::FromInt(0));
924   }
925 
926   ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
927   size_t element_size = 1;  // Bogus initialization.
928   Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
929 
930   holder->set_buffer(*buffer);
931   holder->set_byte_offset(*byte_offset_object);
932   holder->set_byte_length(*byte_length_object);
933 
934   size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
935   size_t byte_length = NumberToSize(isolate, *byte_length_object);
936   ASSERT(byte_length % element_size == 0);
937   size_t length = byte_length / element_size;
938 
939   if (length > static_cast<unsigned>(Smi::kMaxValue)) {
940     return isolate->Throw(*isolate->factory()->
941           NewRangeError("invalid_typed_array_length",
942             HandleVector<Object>(NULL, 0)));
943   }
944 
945   Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
946   holder->set_length(*length_obj);
947   holder->set_weak_next(buffer->weak_first_view());
948   buffer->set_weak_first_view(*holder);
949 
950   Handle<ExternalArray> elements =
951       isolate->factory()->NewExternalArray(
952           static_cast<int>(length), array_type,
953           static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
954   holder->set_elements(*elements);
955   return isolate->heap()->undefined_value();
956 }
957 
958 
959 // Initializes a typed array from an array-like object.
960 // If an array-like object happens to be a typed array of the same type,
961 // initializes backing store using memove.
962 //
963 // Returns true if backing store was initialized or false otherwise.
RUNTIME_FUNCTION(MaybeObject *,Runtime_TypedArrayInitializeFromArrayLike)964 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
965   HandleScope scope(isolate);
966   ASSERT(args.length() == 4);
967   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
968   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
969   CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
970   CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
971 
972   ASSERT(holder->GetInternalFieldCount() ==
973       v8::ArrayBufferView::kInternalFieldCount);
974   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
975     holder->SetInternalField(i, Smi::FromInt(0));
976   }
977 
978   ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
979   size_t element_size = 1;  // Bogus initialization.
980   Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
981 
982   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
983   if (source->IsJSTypedArray() &&
984       JSTypedArray::cast(*source)->type() == array_type) {
985     length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate);
986   }
987   size_t length = NumberToSize(isolate, *length_obj);
988 
989   if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
990       (length > (kMaxInt / element_size))) {
991     return isolate->Throw(*isolate->factory()->
992           NewRangeError("invalid_typed_array_length",
993             HandleVector<Object>(NULL, 0)));
994   }
995   size_t byte_length = length * element_size;
996 
997   // NOTE: not initializing backing store.
998   // We assume that the caller of this function will initialize holder
999   // with the loop
1000   //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
1001   // We assume that the caller of this function is always a typed array
1002   // constructor.
1003   // If source is a typed array, this loop will always run to completion,
1004   // so we are sure that the backing store will be initialized.
1005   // Otherwise, the indexing operation might throw, so the loop will not
1006   // run to completion and the typed array might remain partly initialized.
1007   // However we further assume that the caller of this function is a typed array
1008   // constructor, and the exception will propagate out of the constructor,
1009   // therefore uninitialized memory will not be accessible by a user program.
1010   //
1011   // TODO(dslomov): revise this once we support subclassing.
1012 
1013   if (!Runtime::SetupArrayBufferAllocatingData(
1014         isolate, buffer, byte_length, false)) {
1015     return isolate->Throw(*isolate->factory()->
1016           NewRangeError("invalid_array_buffer_length",
1017             HandleVector<Object>(NULL, 0)));
1018   }
1019 
1020   holder->set_buffer(*buffer);
1021   holder->set_byte_offset(Smi::FromInt(0));
1022   Handle<Object> byte_length_obj(
1023       isolate->factory()->NewNumberFromSize(byte_length));
1024   holder->set_byte_length(*byte_length_obj);
1025   holder->set_length(*length_obj);
1026   holder->set_weak_next(buffer->weak_first_view());
1027   buffer->set_weak_first_view(*holder);
1028 
1029   Handle<ExternalArray> elements =
1030       isolate->factory()->NewExternalArray(
1031           static_cast<int>(length), array_type,
1032           static_cast<uint8_t*>(buffer->backing_store()));
1033   holder->set_elements(*elements);
1034 
1035   if (source->IsJSTypedArray()) {
1036     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
1037 
1038     if (typed_array->type() == holder->type()) {
1039       uint8_t* backing_store =
1040         static_cast<uint8_t*>(
1041           JSArrayBuffer::cast(typed_array->buffer())->backing_store());
1042       size_t source_byte_offset =
1043           NumberToSize(isolate, typed_array->byte_offset());
1044       memcpy(
1045           buffer->backing_store(),
1046           backing_store + source_byte_offset,
1047           byte_length);
1048       return *isolate->factory()->true_value();
1049     } else {
1050       return *isolate->factory()->false_value();
1051     }
1052   }
1053 
1054   return *isolate->factory()->false_value();
1055 }
1056 
1057 
1058 #define TYPED_ARRAY_GETTER(getter, accessor) \
1059   RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) {             \
1060     HandleScope scope(isolate);                                               \
1061     ASSERT(args.length() == 1);                                               \
1062     CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0);                            \
1063     if (!holder->IsJSTypedArray())                                            \
1064       return isolate->Throw(*isolate->factory()->NewTypeError(                \
1065           "not_typed_array", HandleVector<Object>(NULL, 0)));                 \
1066     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder));            \
1067     return typed_array->accessor();                                           \
1068   }
1069 
1070 TYPED_ARRAY_GETTER(Buffer, buffer)
1071 TYPED_ARRAY_GETTER(ByteLength, byte_length)
1072 TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
1073 TYPED_ARRAY_GETTER(Length, length)
1074 
1075 #undef TYPED_ARRAY_GETTER
1076 
1077 // Return codes for Runtime_TypedArraySetFastCases.
1078 // Should be synchronized with typedarray.js natives.
1079 enum TypedArraySetResultCodes {
1080   // Set from typed array of the same type.
1081   // This is processed by TypedArraySetFastCases
1082   TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
1083   // Set from typed array of the different type, overlapping in memory.
1084   TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
1085   // Set from typed array of the different type, non-overlapping.
1086   TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
1087   // Set from non-typed array.
1088   TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
1089 };
1090 
1091 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TypedArraySetFastCases)1092 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
1093   HandleScope scope(isolate);
1094   CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
1095   CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
1096   CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
1097 
1098   if (!target_obj->IsJSTypedArray())
1099     return isolate->Throw(*isolate->factory()->NewTypeError(
1100         "not_typed_array", HandleVector<Object>(NULL, 0)));
1101 
1102   if (!source_obj->IsJSTypedArray())
1103     return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
1104 
1105   Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1106   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1107   size_t offset = NumberToSize(isolate, *offset_obj);
1108   size_t target_length = NumberToSize(isolate, target->length());
1109   size_t source_length = NumberToSize(isolate, source->length());
1110   size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1111   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1112   if (offset > target_length ||
1113       offset + source_length > target_length ||
1114       offset + source_length < offset)  // overflow
1115     return isolate->Throw(*isolate->factory()->NewRangeError(
1116           "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
1117 
1118   size_t target_offset = NumberToSize(isolate, target->byte_offset());
1119   size_t source_offset = NumberToSize(isolate, source->byte_offset());
1120   uint8_t* target_base =
1121       static_cast<uint8_t*>(
1122         JSArrayBuffer::cast(target->buffer())->backing_store()) + target_offset;
1123   uint8_t* source_base =
1124       static_cast<uint8_t*>(
1125         JSArrayBuffer::cast(source->buffer())->backing_store()) + source_offset;
1126 
1127   // Typed arrays of the same type: use memmove.
1128   if (target->type() == source->type()) {
1129     memmove(target_base + offset * target->element_size(),
1130         source_base, source_byte_length);
1131     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
1132   }
1133 
1134   // Typed arrays of different types over the same backing store
1135   if ((source_base <= target_base &&
1136         source_base + source_byte_length > target_base) ||
1137       (target_base <= source_base &&
1138         target_base + target_byte_length > source_base)) {
1139     // We do not support overlapping ArrayBuffers
1140     ASSERT(
1141       JSArrayBuffer::cast(target->buffer())->backing_store() ==
1142       JSArrayBuffer::cast(source->buffer())->backing_store());
1143     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
1144   } else {  // Non-overlapping typed arrays
1145     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
1146   }
1147 }
1148 
1149 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DataViewInitialize)1150 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
1151   HandleScope scope(isolate);
1152   ASSERT(args.length() == 4);
1153   CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
1154   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
1155   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
1156   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
1157 
1158   ASSERT(holder->GetInternalFieldCount() ==
1159       v8::ArrayBufferView::kInternalFieldCount);
1160   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1161     holder->SetInternalField(i, Smi::FromInt(0));
1162   }
1163 
1164   holder->set_buffer(*buffer);
1165   ASSERT(byte_offset->IsNumber());
1166   ASSERT(
1167       NumberToSize(isolate, buffer->byte_length()) >=
1168         NumberToSize(isolate, *byte_offset)
1169         + NumberToSize(isolate, *byte_length));
1170   holder->set_byte_offset(*byte_offset);
1171   ASSERT(byte_length->IsNumber());
1172   holder->set_byte_length(*byte_length);
1173 
1174   holder->set_weak_next(buffer->weak_first_view());
1175   buffer->set_weak_first_view(*holder);
1176 
1177   return isolate->heap()->undefined_value();
1178 }
1179 
1180 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DataViewGetBuffer)1181 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
1182   HandleScope scope(isolate);
1183   ASSERT(args.length() == 1);
1184   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1185   return data_view->buffer();
1186 }
1187 
1188 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DataViewGetByteOffset)1189 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
1190   HandleScope scope(isolate);
1191   ASSERT(args.length() == 1);
1192   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1193   return data_view->byte_offset();
1194 }
1195 
1196 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DataViewGetByteLength)1197 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
1198   HandleScope scope(isolate);
1199   ASSERT(args.length() == 1);
1200   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1201   return data_view->byte_length();
1202 }
1203 
1204 
NeedToFlipBytes(bool is_little_endian)1205 inline static bool NeedToFlipBytes(bool is_little_endian) {
1206 #ifdef V8_TARGET_LITTLE_ENDIAN
1207   return !is_little_endian;
1208 #else
1209   return is_little_endian;
1210 #endif
1211 }
1212 
1213 
1214 template<int n>
CopyBytes(uint8_t * target,uint8_t * source)1215 inline void CopyBytes(uint8_t* target, uint8_t* source) {
1216   for (int i = 0; i < n; i++) {
1217     *(target++) = *(source++);
1218   }
1219 }
1220 
1221 
1222 template<int n>
FlipBytes(uint8_t * target,uint8_t * source)1223 inline void FlipBytes(uint8_t* target, uint8_t* source) {
1224   source = source + (n-1);
1225   for (int i = 0; i < n; i++) {
1226     *(target++) = *(source--);
1227   }
1228 }
1229 
1230 
1231 template<typename T>
DataViewGetValue(Isolate * isolate,Handle<JSDataView> data_view,Handle<Object> byte_offset_obj,bool is_little_endian,T * result)1232 inline static bool DataViewGetValue(
1233     Isolate* isolate,
1234     Handle<JSDataView> data_view,
1235     Handle<Object> byte_offset_obj,
1236     bool is_little_endian,
1237     T* result) {
1238   size_t byte_offset = 0;
1239   if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1240     return false;
1241   }
1242   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1243 
1244   size_t data_view_byte_offset =
1245       NumberToSize(isolate, data_view->byte_offset());
1246   size_t data_view_byte_length =
1247       NumberToSize(isolate, data_view->byte_length());
1248   if (byte_offset + sizeof(T) > data_view_byte_length ||
1249       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1250     return false;
1251   }
1252 
1253   union Value {
1254     T data;
1255     uint8_t bytes[sizeof(T)];
1256   };
1257 
1258   Value value;
1259   size_t buffer_offset = data_view_byte_offset + byte_offset;
1260   ASSERT(
1261       NumberToSize(isolate, buffer->byte_length())
1262       >= buffer_offset + sizeof(T));
1263   uint8_t* source =
1264         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1265   if (NeedToFlipBytes(is_little_endian)) {
1266     FlipBytes<sizeof(T)>(value.bytes, source);
1267   } else {
1268     CopyBytes<sizeof(T)>(value.bytes, source);
1269   }
1270   *result = value.data;
1271   return true;
1272 }
1273 
1274 
1275 template<typename T>
DataViewSetValue(Isolate * isolate,Handle<JSDataView> data_view,Handle<Object> byte_offset_obj,bool is_little_endian,T data)1276 static bool DataViewSetValue(
1277     Isolate* isolate,
1278     Handle<JSDataView> data_view,
1279     Handle<Object> byte_offset_obj,
1280     bool is_little_endian,
1281     T data) {
1282   size_t byte_offset = 0;
1283   if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1284     return false;
1285   }
1286   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1287 
1288   size_t data_view_byte_offset =
1289       NumberToSize(isolate, data_view->byte_offset());
1290   size_t data_view_byte_length =
1291       NumberToSize(isolate, data_view->byte_length());
1292   if (byte_offset + sizeof(T) > data_view_byte_length ||
1293       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1294     return false;
1295   }
1296 
1297   union Value {
1298     T data;
1299     uint8_t bytes[sizeof(T)];
1300   };
1301 
1302   Value value;
1303   value.data = data;
1304   size_t buffer_offset = data_view_byte_offset + byte_offset;
1305   ASSERT(
1306       NumberToSize(isolate, buffer->byte_length())
1307       >= buffer_offset + sizeof(T));
1308   uint8_t* target =
1309         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1310   if (NeedToFlipBytes(is_little_endian)) {
1311     FlipBytes<sizeof(T)>(target, value.bytes);
1312   } else {
1313     CopyBytes<sizeof(T)>(target, value.bytes);
1314   }
1315   return true;
1316 }
1317 
1318 
1319 #define DATA_VIEW_GETTER(TypeName, Type, Converter)                           \
1320   RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) {             \
1321     HandleScope scope(isolate);                                               \
1322     ASSERT(args.length() == 3);                                               \
1323     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1324     CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1325     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2);                         \
1326     Type result;                                                              \
1327     if (DataViewGetValue(                                                     \
1328           isolate, holder, offset, is_little_endian, &result)) {              \
1329       return isolate->heap()->Converter(result);                              \
1330     } else {                                                                  \
1331       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1332           "invalid_data_view_accessor_offset",                                \
1333           HandleVector<Object>(NULL, 0)));                                    \
1334     }                                                                         \
1335   }
1336 
1337 DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
1338 DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
1339 DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
1340 DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
1341 DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
1342 DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
1343 DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
1344 DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
1345 
1346 #undef DATA_VIEW_GETTER
1347 
1348 
1349 template <typename T>
1350 static T DataViewConvertValue(double value);
1351 
1352 
1353 template <>
DataViewConvertValue(double value)1354 int8_t DataViewConvertValue<int8_t>(double value) {
1355   return static_cast<int8_t>(DoubleToInt32(value));
1356 }
1357 
1358 
1359 template <>
DataViewConvertValue(double value)1360 int16_t DataViewConvertValue<int16_t>(double value) {
1361   return static_cast<int16_t>(DoubleToInt32(value));
1362 }
1363 
1364 
1365 template <>
DataViewConvertValue(double value)1366 int32_t DataViewConvertValue<int32_t>(double value) {
1367   return DoubleToInt32(value);
1368 }
1369 
1370 
1371 template <>
DataViewConvertValue(double value)1372 uint8_t DataViewConvertValue<uint8_t>(double value) {
1373   return static_cast<uint8_t>(DoubleToUint32(value));
1374 }
1375 
1376 
1377 template <>
DataViewConvertValue(double value)1378 uint16_t DataViewConvertValue<uint16_t>(double value) {
1379   return static_cast<uint16_t>(DoubleToUint32(value));
1380 }
1381 
1382 
1383 template <>
DataViewConvertValue(double value)1384 uint32_t DataViewConvertValue<uint32_t>(double value) {
1385   return DoubleToUint32(value);
1386 }
1387 
1388 
1389 template <>
DataViewConvertValue(double value)1390 float DataViewConvertValue<float>(double value) {
1391   return static_cast<float>(value);
1392 }
1393 
1394 
1395 template <>
DataViewConvertValue(double value)1396 double DataViewConvertValue<double>(double value) {
1397   return value;
1398 }
1399 
1400 
1401 #define DATA_VIEW_SETTER(TypeName, Type)                                      \
1402   RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) {             \
1403     HandleScope scope(isolate);                                               \
1404     ASSERT(args.length() == 4);                                               \
1405     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1406     CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1407     CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);                             \
1408     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3);                         \
1409     Type v = DataViewConvertValue<Type>(value->Number());                     \
1410     if (DataViewSetValue(                                                     \
1411           isolate, holder, offset, is_little_endian, v)) {                    \
1412       return isolate->heap()->undefined_value();                              \
1413     } else {                                                                  \
1414       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1415           "invalid_data_view_accessor_offset",                                \
1416           HandleVector<Object>(NULL, 0)));                                    \
1417     }                                                                         \
1418   }
1419 
DATA_VIEW_SETTER(Uint8,uint8_t)1420 DATA_VIEW_SETTER(Uint8, uint8_t)
1421 DATA_VIEW_SETTER(Int8, int8_t)
1422 DATA_VIEW_SETTER(Uint16, uint16_t)
1423 DATA_VIEW_SETTER(Int16, int16_t)
1424 DATA_VIEW_SETTER(Uint32, uint32_t)
1425 DATA_VIEW_SETTER(Int32, int32_t)
1426 DATA_VIEW_SETTER(Float32, float)
1427 DATA_VIEW_SETTER(Float64, double)
1428 
1429 #undef DATA_VIEW_SETTER
1430 
1431 
1432 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
1433   HandleScope scope(isolate);
1434   ASSERT(args.length() == 1);
1435   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1436   Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
1437   holder->set_table(*table);
1438   return *holder;
1439 }
1440 
1441 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetAdd)1442 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
1443   HandleScope scope(isolate);
1444   ASSERT(args.length() == 2);
1445   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1446   Handle<Object> key(args[1], isolate);
1447   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1448   table = ObjectHashSet::Add(table, key);
1449   holder->set_table(*table);
1450   return isolate->heap()->undefined_value();
1451 }
1452 
1453 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetHas)1454 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
1455   HandleScope scope(isolate);
1456   ASSERT(args.length() == 2);
1457   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1458   Handle<Object> key(args[1], isolate);
1459   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1460   return isolate->heap()->ToBoolean(table->Contains(*key));
1461 }
1462 
1463 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDelete)1464 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
1465   HandleScope scope(isolate);
1466   ASSERT(args.length() == 2);
1467   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1468   Handle<Object> key(args[1], isolate);
1469   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1470   table = ObjectHashSet::Remove(table, key);
1471   holder->set_table(*table);
1472   return isolate->heap()->undefined_value();
1473 }
1474 
1475 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetGetSize)1476 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
1477   HandleScope scope(isolate);
1478   ASSERT(args.length() == 1);
1479   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1480   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1481   return Smi::FromInt(table->NumberOfElements());
1482 }
1483 
1484 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapInitialize)1485 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
1486   HandleScope scope(isolate);
1487   ASSERT(args.length() == 1);
1488   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1489   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1490   holder->set_table(*table);
1491   return *holder;
1492 }
1493 
1494 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapGet)1495 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
1496   HandleScope scope(isolate);
1497   ASSERT(args.length() == 2);
1498   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1499   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1500   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1501   Handle<Object> lookup(table->Lookup(*key), isolate);
1502   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1503 }
1504 
1505 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapHas)1506 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
1507   HandleScope scope(isolate);
1508   ASSERT(args.length() == 2);
1509   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1510   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1511   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1512   Handle<Object> lookup(table->Lookup(*key), isolate);
1513   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1514 }
1515 
1516 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapDelete)1517 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
1518   HandleScope scope(isolate);
1519   ASSERT(args.length() == 2);
1520   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1521   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1522   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1523   Handle<Object> lookup(table->Lookup(*key), isolate);
1524   Handle<ObjectHashTable> new_table =
1525       ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
1526   holder->set_table(*new_table);
1527   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1528 }
1529 
1530 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapSet)1531 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
1532   HandleScope scope(isolate);
1533   ASSERT(args.length() == 3);
1534   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1535   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1536   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1537   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1538   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1539   holder->set_table(*new_table);
1540   return isolate->heap()->undefined_value();
1541 }
1542 
1543 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapGetSize)1544 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
1545   HandleScope scope(isolate);
1546   ASSERT(args.length() == 1);
1547   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1548   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1549   return Smi::FromInt(table->NumberOfElements());
1550 }
1551 
1552 
WeakCollectionInitialize(Isolate * isolate,Handle<JSWeakCollection> weak_collection)1553 static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
1554     Handle<JSWeakCollection> weak_collection) {
1555   ASSERT(weak_collection->map()->inobject_properties() == 0);
1556   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1557   weak_collection->set_table(*table);
1558   weak_collection->set_next(Smi::FromInt(0));
1559   return *weak_collection;
1560 }
1561 
1562 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakCollectionInitialize)1563 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
1564   HandleScope scope(isolate);
1565   ASSERT(args.length() == 1);
1566   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1567   return WeakCollectionInitialize(isolate, weak_collection);
1568 }
1569 
1570 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakCollectionGet)1571 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
1572   HandleScope scope(isolate);
1573   ASSERT(args.length() == 2);
1574   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1575   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1576   Handle<ObjectHashTable> table(
1577       ObjectHashTable::cast(weak_collection->table()));
1578   Handle<Object> lookup(table->Lookup(*key), isolate);
1579   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1580 }
1581 
1582 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakCollectionHas)1583 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
1584   HandleScope scope(isolate);
1585   ASSERT(args.length() == 2);
1586   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1587   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1588   Handle<ObjectHashTable> table(
1589       ObjectHashTable::cast(weak_collection->table()));
1590   Handle<Object> lookup(table->Lookup(*key), isolate);
1591   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1592 }
1593 
1594 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakCollectionDelete)1595 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
1596   HandleScope scope(isolate);
1597   ASSERT(args.length() == 2);
1598   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1599   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1600   Handle<ObjectHashTable> table(ObjectHashTable::cast(
1601       weak_collection->table()));
1602   Handle<Object> lookup(table->Lookup(*key), isolate);
1603   Handle<ObjectHashTable> new_table =
1604       ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
1605   weak_collection->set_table(*new_table);
1606   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1607 }
1608 
1609 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakCollectionSet)1610 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
1611   HandleScope scope(isolate);
1612   ASSERT(args.length() == 3);
1613   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1614   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1615   Handle<Object> value(args[2], isolate);
1616   Handle<ObjectHashTable> table(
1617       ObjectHashTable::cast(weak_collection->table()));
1618   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1619   weak_collection->set_table(*new_table);
1620   return isolate->heap()->undefined_value();
1621 }
1622 
1623 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClassOf)1624 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
1625   SealHandleScope shs(isolate);
1626   ASSERT(args.length() == 1);
1627   Object* obj = args[0];
1628   if (!obj->IsJSObject()) return isolate->heap()->null_value();
1629   return JSObject::cast(obj)->class_name();
1630 }
1631 
1632 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPrototype)1633 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
1634   HandleScope scope(isolate);
1635   ASSERT(args.length() == 1);
1636   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
1637   // We don't expect access checks to be needed on JSProxy objects.
1638   ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1639   do {
1640     if (obj->IsAccessCheckNeeded() &&
1641         !isolate->MayNamedAccessWrapper(Handle<JSObject>::cast(obj),
1642                                         isolate->factory()->proto_string(),
1643                                         v8::ACCESS_GET)) {
1644       isolate->ReportFailedAccessCheck(JSObject::cast(*obj), v8::ACCESS_GET);
1645       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1646       return isolate->heap()->undefined_value();
1647     }
1648     obj = handle(obj->GetPrototype(isolate), isolate);
1649   } while (obj->IsJSObject() &&
1650            JSObject::cast(*obj)->map()->is_hidden_prototype());
1651   return *obj;
1652 }
1653 
1654 
GetPrototypeSkipHiddenPrototypes(Isolate * isolate,Object * receiver)1655 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
1656                                                        Object* receiver) {
1657   Object* current = receiver->GetPrototype(isolate);
1658   while (current->IsJSObject() &&
1659          JSObject::cast(current)->map()->is_hidden_prototype()) {
1660     current = current->GetPrototype(isolate);
1661   }
1662   return current;
1663 }
1664 
1665 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetPrototype)1666 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
1667   HandleScope scope(isolate);
1668   ASSERT(args.length() == 2);
1669   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1670   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1671   if (FLAG_harmony_observation && obj->map()->is_observed()) {
1672     Handle<Object> old_value(
1673         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1674 
1675     Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1676     RETURN_IF_EMPTY_HANDLE(isolate, result);
1677 
1678     Handle<Object> new_value(
1679         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1680     if (!new_value->SameValue(*old_value)) {
1681       JSObject::EnqueueChangeRecord(obj, "setPrototype",
1682                                     isolate->factory()->proto_string(),
1683                                     old_value);
1684     }
1685     return *result;
1686   }
1687   Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1688   RETURN_IF_EMPTY_HANDLE(isolate, result);
1689   return *result;
1690 }
1691 
1692 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsInPrototypeChain)1693 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
1694   SealHandleScope shs(isolate);
1695   ASSERT(args.length() == 2);
1696   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1697   Object* O = args[0];
1698   Object* V = args[1];
1699   while (true) {
1700     Object* prototype = V->GetPrototype(isolate);
1701     if (prototype->IsNull()) return isolate->heap()->false_value();
1702     if (O == prototype) return isolate->heap()->true_value();
1703     V = prototype;
1704   }
1705 }
1706 
1707 
CheckAccessException(Object * callback,v8::AccessType access_type)1708 static bool CheckAccessException(Object* callback,
1709                                  v8::AccessType access_type) {
1710   DisallowHeapAllocation no_gc;
1711   if (callback->IsAccessorInfo()) {
1712     AccessorInfo* info = AccessorInfo::cast(callback);
1713     return
1714         (access_type == v8::ACCESS_HAS &&
1715            (info->all_can_read() || info->all_can_write())) ||
1716         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1717         (access_type == v8::ACCESS_SET && info->all_can_write());
1718   }
1719   if (callback->IsAccessorPair()) {
1720     AccessorPair* info = AccessorPair::cast(callback);
1721     return
1722         (access_type == v8::ACCESS_HAS &&
1723            (info->all_can_read() || info->all_can_write())) ||
1724         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1725         (access_type == v8::ACCESS_SET && info->all_can_write());
1726   }
1727   return false;
1728 }
1729 
1730 
1731 template<class Key>
CheckGenericAccess(Handle<JSObject> receiver,Handle<JSObject> holder,Key key,v8::AccessType access_type,bool (Isolate::* mayAccess)(Handle<JSObject>,Key,v8::AccessType))1732 static bool CheckGenericAccess(
1733     Handle<JSObject> receiver,
1734     Handle<JSObject> holder,
1735     Key key,
1736     v8::AccessType access_type,
1737     bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) {
1738   Isolate* isolate = receiver->GetIsolate();
1739   for (Handle<JSObject> current = receiver;
1740        true;
1741        current = handle(JSObject::cast(current->GetPrototype()), isolate)) {
1742     if (current->IsAccessCheckNeeded() &&
1743         !(isolate->*mayAccess)(current, key, access_type)) {
1744       return false;
1745     }
1746     if (current.is_identical_to(holder)) break;
1747   }
1748   return true;
1749 }
1750 
1751 
1752 enum AccessCheckResult {
1753   ACCESS_FORBIDDEN,
1754   ACCESS_ALLOWED,
1755   ACCESS_ABSENT
1756 };
1757 
1758 
CheckPropertyAccess(Handle<JSObject> obj,Handle<Name> name,v8::AccessType access_type)1759 static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
1760                                              Handle<Name> name,
1761                                              v8::AccessType access_type) {
1762   uint32_t index;
1763   if (name->AsArrayIndex(&index)) {
1764     // TODO(1095): we should traverse hidden prototype hierachy as well.
1765     if (CheckGenericAccess(
1766             obj, obj, index, access_type, &Isolate::MayIndexedAccessWrapper)) {
1767       return ACCESS_ALLOWED;
1768     }
1769 
1770     obj->GetIsolate()->ReportFailedAccessCheck(*obj, access_type);
1771     return ACCESS_FORBIDDEN;
1772   }
1773 
1774   Isolate* isolate = obj->GetIsolate();
1775   LookupResult lookup(isolate);
1776   obj->LocalLookup(*name, &lookup, true);
1777 
1778   if (!lookup.IsProperty()) return ACCESS_ABSENT;
1779   Handle<JSObject> holder(lookup.holder(), isolate);
1780   if (CheckGenericAccess<Handle<Object> >(
1781           obj, holder, name, access_type, &Isolate::MayNamedAccessWrapper)) {
1782     return ACCESS_ALLOWED;
1783   }
1784 
1785   // Access check callback denied the access, but some properties
1786   // can have a special permissions which override callbacks descision
1787   // (currently see v8::AccessControl).
1788   // API callbacks can have per callback access exceptions.
1789   switch (lookup.type()) {
1790     case CALLBACKS:
1791       if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1792         return ACCESS_ALLOWED;
1793       }
1794       break;
1795     case INTERCEPTOR:
1796       // If the object has an interceptor, try real named properties.
1797       // Overwrite the result to fetch the correct property later.
1798       holder->LookupRealNamedProperty(*name, &lookup);
1799       if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1800         if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1801           return ACCESS_ALLOWED;
1802         }
1803       }
1804       break;
1805     default:
1806       break;
1807   }
1808 
1809   isolate->ReportFailedAccessCheck(*obj, access_type);
1810   return ACCESS_FORBIDDEN;
1811 }
1812 
1813 
1814 // Enumerator used as indices into the array returned from GetOwnProperty
1815 enum PropertyDescriptorIndices {
1816   IS_ACCESSOR_INDEX,
1817   VALUE_INDEX,
1818   GETTER_INDEX,
1819   SETTER_INDEX,
1820   WRITABLE_INDEX,
1821   ENUMERABLE_INDEX,
1822   CONFIGURABLE_INDEX,
1823   DESCRIPTOR_SIZE
1824 };
1825 
1826 
GetOwnProperty(Isolate * isolate,Handle<JSObject> obj,Handle<Name> name)1827 static Handle<Object> GetOwnProperty(Isolate* isolate,
1828                                      Handle<JSObject> obj,
1829                                      Handle<Name> name) {
1830   Heap* heap = isolate->heap();
1831   Factory* factory = isolate->factory();
1832   // Due to some WebKit tests, we want to make sure that we do not log
1833   // more than one access failure here.
1834   AccessCheckResult access_check_result =
1835       CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
1836   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1837   switch (access_check_result) {
1838     case ACCESS_FORBIDDEN: return factory->false_value();
1839     case ACCESS_ALLOWED: break;
1840     case ACCESS_ABSENT: return factory->undefined_value();
1841   }
1842 
1843   PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
1844   if (attrs == ABSENT) {
1845     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1846     return factory->undefined_value();
1847   }
1848   ASSERT(!isolate->has_scheduled_exception());
1849   AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
1850   Handle<AccessorPair> accessors(raw_accessors, isolate);
1851   Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1852   elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
1853   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
1854   elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
1855 
1856   if (raw_accessors == NULL) {
1857     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
1858     // GetProperty does access check.
1859     Handle<Object> value = GetProperty(isolate, obj, name);
1860     RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<Object>::null());
1861     elms->set(VALUE_INDEX, *value);
1862   } else {
1863     // Access checks are performed for both accessors separately.
1864     // When they fail, the respective field is not set in the descriptor.
1865     Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
1866     Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
1867 
1868     if (!getter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_GET)) {
1869       ASSERT(!isolate->has_scheduled_exception());
1870       elms->set(GETTER_INDEX, *getter);
1871     } else {
1872       RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1873     }
1874 
1875     if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) {
1876       ASSERT(!isolate->has_scheduled_exception());
1877       elms->set(SETTER_INDEX, *setter);
1878     } else {
1879       RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1880     }
1881   }
1882 
1883   return isolate->factory()->NewJSArrayWithElements(elms);
1884 }
1885 
1886 
1887 // Returns an array with the property description:
1888 //  if args[1] is not a property on args[0]
1889 //          returns undefined
1890 //  if args[1] is a data property on args[0]
1891 //         [false, value, Writeable, Enumerable, Configurable]
1892 //  if args[1] is an accessor on args[0]
1893 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetOwnProperty)1894 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1895   HandleScope scope(isolate);
1896   ASSERT(args.length() == 2);
1897   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1898   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1899   Handle<Object> result = GetOwnProperty(isolate, obj, name);
1900   RETURN_IF_EMPTY_HANDLE(isolate, result);
1901   return *result;
1902 }
1903 
1904 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PreventExtensions)1905 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1906   HandleScope scope(isolate);
1907   ASSERT(args.length() == 1);
1908   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1909   Handle<Object> result = JSObject::PreventExtensions(obj);
1910   RETURN_IF_EMPTY_HANDLE(isolate, result);
1911   return *result;
1912 }
1913 
1914 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsExtensible)1915 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1916   SealHandleScope shs(isolate);
1917   ASSERT(args.length() == 1);
1918   CONVERT_ARG_CHECKED(JSObject, obj, 0);
1919   if (obj->IsJSGlobalProxy()) {
1920     Object* proto = obj->GetPrototype();
1921     if (proto->IsNull()) return isolate->heap()->false_value();
1922     ASSERT(proto->IsJSGlobalObject());
1923     obj = JSObject::cast(proto);
1924   }
1925   return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1926 }
1927 
1928 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpCompile)1929 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1930   HandleScope scope(isolate);
1931   ASSERT(args.length() == 3);
1932   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
1933   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1934   CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
1935   Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
1936   RETURN_IF_EMPTY_HANDLE(isolate, result);
1937   return *result;
1938 }
1939 
1940 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateApiFunction)1941 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1942   HandleScope scope(isolate);
1943   ASSERT(args.length() == 1);
1944   CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
1945   return *isolate->factory()->CreateApiFunction(data);
1946 }
1947 
1948 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsTemplate)1949 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1950   SealHandleScope shs(isolate);
1951   ASSERT(args.length() == 1);
1952   Object* arg = args[0];
1953   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1954   return isolate->heap()->ToBoolean(result);
1955 }
1956 
1957 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetTemplateField)1958 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1959   SealHandleScope shs(isolate);
1960   ASSERT(args.length() == 2);
1961   CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1962   CONVERT_SMI_ARG_CHECKED(index, 1)
1963   int offset = index * kPointerSize + HeapObject::kHeaderSize;
1964   InstanceType type = templ->map()->instance_type();
1965   RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
1966                  type ==  OBJECT_TEMPLATE_INFO_TYPE);
1967   RUNTIME_ASSERT(offset > 0);
1968   if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1969     RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1970   } else {
1971     RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1972   }
1973   return *HeapObject::RawField(templ, offset);
1974 }
1975 
1976 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DisableAccessChecks)1977 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1978   SealHandleScope shs(isolate);
1979   ASSERT(args.length() == 1);
1980   CONVERT_ARG_CHECKED(HeapObject, object, 0);
1981   Map* old_map = object->map();
1982   bool needs_access_checks = old_map->is_access_check_needed();
1983   if (needs_access_checks) {
1984     // Copy map so it won't interfere constructor's initial map.
1985     Map* new_map;
1986     MaybeObject* maybe_new_map = old_map->Copy();
1987     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1988 
1989     new_map->set_is_access_check_needed(false);
1990     object->set_map(new_map);
1991   }
1992   return isolate->heap()->ToBoolean(needs_access_checks);
1993 }
1994 
1995 
RUNTIME_FUNCTION(MaybeObject *,Runtime_EnableAccessChecks)1996 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1997   SealHandleScope shs(isolate);
1998   ASSERT(args.length() == 1);
1999   CONVERT_ARG_CHECKED(HeapObject, object, 0);
2000   Map* old_map = object->map();
2001   if (!old_map->is_access_check_needed()) {
2002     // Copy map so it won't interfere constructor's initial map.
2003     Map* new_map;
2004     MaybeObject* maybe_new_map = old_map->Copy();
2005     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2006 
2007     new_map->set_is_access_check_needed(true);
2008     object->set_map(new_map);
2009   }
2010   return isolate->heap()->undefined_value();
2011 }
2012 
2013 
2014 // Transform getter or setter into something DefineAccessor can handle.
InstantiateAccessorComponent(Isolate * isolate,Handle<Object> component)2015 static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
2016                                                    Handle<Object> component) {
2017   if (component->IsUndefined()) return isolate->factory()->null_value();
2018   Handle<FunctionTemplateInfo> info =
2019       Handle<FunctionTemplateInfo>::cast(component);
2020   return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
2021 }
2022 
2023 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetAccessorProperty)2024 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
2025   HandleScope scope(isolate);
2026   ASSERT(args.length() == 6);
2027   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2028   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2029   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
2030   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
2031   CONVERT_SMI_ARG_CHECKED(attribute, 4);
2032   CONVERT_SMI_ARG_CHECKED(access_control, 5);
2033   JSObject::DefineAccessor(object,
2034                            name,
2035                            InstantiateAccessorComponent(isolate, getter),
2036                            InstantiateAccessorComponent(isolate, setter),
2037                            static_cast<PropertyAttributes>(attribute),
2038                            static_cast<v8::AccessControl>(access_control));
2039   return isolate->heap()->undefined_value();
2040 }
2041 
2042 
ThrowRedeclarationError(Isolate * isolate,const char * type,Handle<String> name)2043 static Failure* ThrowRedeclarationError(Isolate* isolate,
2044                                         const char* type,
2045                                         Handle<String> name) {
2046   HandleScope scope(isolate);
2047   Handle<Object> type_handle =
2048       isolate->factory()->NewStringFromAscii(CStrVector(type));
2049   Handle<Object> args[2] = { type_handle, name };
2050   Handle<Object> error =
2051       isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
2052   return isolate->Throw(*error);
2053 }
2054 
2055 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeclareGlobals)2056 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
2057   HandleScope scope(isolate);
2058   ASSERT(args.length() == 3);
2059   Handle<GlobalObject> global = Handle<GlobalObject>(
2060       isolate->context()->global_object());
2061 
2062   Handle<Context> context = args.at<Context>(0);
2063   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
2064   CONVERT_SMI_ARG_CHECKED(flags, 2);
2065 
2066   // Traverse the name/value pairs and set the properties.
2067   int length = pairs->length();
2068   for (int i = 0; i < length; i += 2) {
2069     HandleScope scope(isolate);
2070     Handle<String> name(String::cast(pairs->get(i)));
2071     Handle<Object> value(pairs->get(i + 1), isolate);
2072 
2073     // We have to declare a global const property. To capture we only
2074     // assign to it when evaluating the assignment for "const x =
2075     // <expr>" the initial value is the hole.
2076     bool is_var = value->IsUndefined();
2077     bool is_const = value->IsTheHole();
2078     bool is_function = value->IsSharedFunctionInfo();
2079     ASSERT(is_var + is_const + is_function == 1);
2080 
2081     if (is_var || is_const) {
2082       // Lookup the property in the global object, and don't set the
2083       // value of the variable if the property is already there.
2084       // Do the lookup locally only, see ES5 erratum.
2085       LookupResult lookup(isolate);
2086       if (FLAG_es52_globals) {
2087         global->LocalLookup(*name, &lookup, true);
2088       } else {
2089         global->Lookup(*name, &lookup);
2090       }
2091       if (lookup.IsFound()) {
2092         // We found an existing property. Unless it was an interceptor
2093         // that claims the property is absent, skip this declaration.
2094         if (!lookup.IsInterceptor()) continue;
2095         PropertyAttributes attributes = global->GetPropertyAttribute(*name);
2096         if (attributes != ABSENT) continue;
2097         // Fall-through and introduce the absent property by using
2098         // SetProperty.
2099       }
2100     } else if (is_function) {
2101       // Copy the function and update its context. Use it as value.
2102       Handle<SharedFunctionInfo> shared =
2103           Handle<SharedFunctionInfo>::cast(value);
2104       Handle<JSFunction> function =
2105           isolate->factory()->NewFunctionFromSharedFunctionInfo(
2106               shared, context, TENURED);
2107       value = function;
2108     }
2109 
2110     LookupResult lookup(isolate);
2111     global->LocalLookup(*name, &lookup, true);
2112 
2113     // Compute the property attributes. According to ECMA-262,
2114     // the property must be non-configurable except in eval.
2115     int attr = NONE;
2116     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2117     if (!is_eval) {
2118       attr |= DONT_DELETE;
2119     }
2120     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2121     if (is_const || (is_native && is_function)) {
2122       attr |= READ_ONLY;
2123     }
2124 
2125     LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
2126 
2127     if (!lookup.IsFound() || is_function) {
2128       // If the local property exists, check that we can reconfigure it
2129       // as required for function declarations.
2130       if (lookup.IsFound() && lookup.IsDontDelete()) {
2131         if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2132             lookup.IsPropertyCallbacks()) {
2133           return ThrowRedeclarationError(isolate, "function", name);
2134         }
2135         // If the existing property is not configurable, keep its attributes.
2136         attr = lookup.GetAttributes();
2137       }
2138       // Define or redefine own property.
2139       RETURN_IF_EMPTY_HANDLE(isolate,
2140           JSObject::SetLocalPropertyIgnoreAttributes(
2141               global, name, value, static_cast<PropertyAttributes>(attr)));
2142     } else {
2143       // Do a [[Put]] on the existing (own) property.
2144       RETURN_IF_EMPTY_HANDLE(isolate,
2145           JSObject::SetProperty(
2146               global, name, value, static_cast<PropertyAttributes>(attr),
2147               language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
2148     }
2149   }
2150 
2151   ASSERT(!isolate->has_pending_exception());
2152   return isolate->heap()->undefined_value();
2153 }
2154 
2155 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeclareContextSlot)2156 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
2157   HandleScope scope(isolate);
2158   ASSERT(args.length() == 4);
2159 
2160   // Declarations are always made in a function or native context.  In the
2161   // case of eval code, the context passed is the context of the caller,
2162   // which may be some nested context and not the declaration context.
2163   RUNTIME_ASSERT(args[0]->IsContext());
2164   Handle<Context> context(Context::cast(args[0])->declaration_context());
2165 
2166   Handle<String> name(String::cast(args[1]));
2167   PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
2168   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2169   Handle<Object> initial_value(args[3], isolate);
2170 
2171   int index;
2172   PropertyAttributes attributes;
2173   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2174   BindingFlags binding_flags;
2175   Handle<Object> holder =
2176       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2177 
2178   if (attributes != ABSENT) {
2179     // The name was declared before; check for conflicting re-declarations.
2180     // Note: this is actually inconsistent with what happens for globals (where
2181     // we silently ignore such declarations).
2182     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2183       // Functions are not read-only.
2184       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2185       const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
2186       return ThrowRedeclarationError(isolate, type, name);
2187     }
2188 
2189     // Initialize it if necessary.
2190     if (*initial_value != NULL) {
2191       if (index >= 0) {
2192         ASSERT(holder.is_identical_to(context));
2193         if (((attributes & READ_ONLY) == 0) ||
2194             context->get(index)->IsTheHole()) {
2195           context->set(index, *initial_value);
2196         }
2197       } else {
2198         // Slow case: The property is in the context extension object of a
2199         // function context or the global object of a native context.
2200         Handle<JSObject> object = Handle<JSObject>::cast(holder);
2201         RETURN_IF_EMPTY_HANDLE(
2202             isolate,
2203             JSReceiver::SetProperty(object, name, initial_value, mode,
2204                                     kNonStrictMode));
2205       }
2206     }
2207 
2208   } else {
2209     // The property is not in the function context. It needs to be
2210     // "declared" in the function context's extension context or as a
2211     // property of the the global object.
2212     Handle<JSObject> object;
2213     if (context->has_extension()) {
2214       object = Handle<JSObject>(JSObject::cast(context->extension()));
2215     } else {
2216       // Context extension objects are allocated lazily.
2217       ASSERT(context->IsFunctionContext());
2218       object = isolate->factory()->NewJSObject(
2219           isolate->context_extension_function());
2220       context->set_extension(*object);
2221     }
2222     ASSERT(*object != NULL);
2223 
2224     // Declare the property by setting it to the initial value if provided,
2225     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2226     // constant declarations).
2227     ASSERT(!JSReceiver::HasLocalProperty(object, name));
2228     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2229     if (*initial_value != NULL) value = initial_value;
2230     // Declaring a const context slot is a conflicting declaration if
2231     // there is a callback with that name in a prototype. It is
2232     // allowed to introduce const variables in
2233     // JSContextExtensionObjects. They are treated specially in
2234     // SetProperty and no setters are invoked for those since they are
2235     // not real JSObjects.
2236     if (initial_value->IsTheHole() &&
2237         !object->IsJSContextExtensionObject()) {
2238       LookupResult lookup(isolate);
2239       object->Lookup(*name, &lookup);
2240       if (lookup.IsPropertyCallbacks()) {
2241         return ThrowRedeclarationError(isolate, "const", name);
2242       }
2243     }
2244     if (object->IsJSGlobalObject()) {
2245       // Define own property on the global object.
2246       RETURN_IF_EMPTY_HANDLE(isolate,
2247          JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
2248     } else {
2249       RETURN_IF_EMPTY_HANDLE(isolate,
2250          JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
2251     }
2252   }
2253 
2254   return isolate->heap()->undefined_value();
2255 }
2256 
2257 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeVarGlobal)2258 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
2259   HandleScope scope(isolate);
2260   // args[0] == name
2261   // args[1] == language_mode
2262   // args[2] == value (optional)
2263 
2264   // Determine if we need to assign to the variable if it already
2265   // exists (based on the number of arguments).
2266   RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
2267   bool assign = args.length() == 3;
2268 
2269   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2270   RUNTIME_ASSERT(args[1]->IsSmi());
2271   CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
2272   StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
2273       ? kNonStrictMode : kStrictMode;
2274 
2275   // According to ECMA-262, section 12.2, page 62, the property must
2276   // not be deletable.
2277   PropertyAttributes attributes = DONT_DELETE;
2278 
2279   // Lookup the property locally in the global object. If it isn't
2280   // there, there is a property with this name in the prototype chain.
2281   // We follow Safari and Firefox behavior and only set the property
2282   // locally if there is an explicit initialization value that we have
2283   // to assign to the property.
2284   // Note that objects can have hidden prototypes, so we need to traverse
2285   // the whole chain of hidden prototypes to do a 'local' lookup.
2286   LookupResult lookup(isolate);
2287   isolate->context()->global_object()->LocalLookup(*name, &lookup, true);
2288   if (lookup.IsInterceptor()) {
2289     PropertyAttributes intercepted =
2290         lookup.holder()->GetPropertyAttribute(*name);
2291     if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2292       // Found an interceptor that's not read only.
2293       if (assign) {
2294         CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2295         Handle<Object> result = JSObject::SetPropertyForResult(
2296             handle(lookup.holder()), &lookup, name, value, attributes,
2297             strict_mode_flag);
2298         RETURN_IF_EMPTY_HANDLE(isolate, result);
2299         return *result;
2300       } else {
2301         return isolate->heap()->undefined_value();
2302       }
2303     }
2304   }
2305 
2306   if (assign) {
2307     CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2308     Handle<GlobalObject> global(isolate->context()->global_object());
2309     Handle<Object> result = JSReceiver::SetProperty(
2310         global, name, value, attributes, strict_mode_flag);
2311     RETURN_IF_EMPTY_HANDLE(isolate, result);
2312     return *result;
2313   }
2314   return isolate->heap()->undefined_value();
2315 }
2316 
2317 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeConstGlobal)2318 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
2319   SealHandleScope shs(isolate);
2320   // All constants are declared with an initial value. The name
2321   // of the constant is the first argument and the initial value
2322   // is the second.
2323   RUNTIME_ASSERT(args.length() == 2);
2324   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2325   Handle<Object> value = args.at<Object>(1);
2326 
2327   // Get the current global object from top.
2328   GlobalObject* global = isolate->context()->global_object();
2329 
2330   // According to ECMA-262, section 12.2, page 62, the property must
2331   // not be deletable. Since it's a const, it must be READ_ONLY too.
2332   PropertyAttributes attributes =
2333       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2334 
2335   // Lookup the property locally in the global object. If it isn't
2336   // there, we add the property and take special precautions to always
2337   // add it as a local property even in case of callbacks in the
2338   // prototype chain (this rules out using SetProperty).
2339   // We use SetLocalPropertyIgnoreAttributes instead
2340   LookupResult lookup(isolate);
2341   global->LocalLookup(*name, &lookup);
2342   if (!lookup.IsFound()) {
2343     HandleScope handle_scope(isolate);
2344     Handle<GlobalObject> global(isolate->context()->global_object());
2345     RETURN_IF_EMPTY_HANDLE(
2346         isolate,
2347         JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
2348                                                    attributes));
2349     return *value;
2350   }
2351 
2352   if (!lookup.IsReadOnly()) {
2353     // Restore global object from context (in case of GC) and continue
2354     // with setting the value.
2355     HandleScope handle_scope(isolate);
2356     Handle<GlobalObject> global(isolate->context()->global_object());
2357 
2358     // BUG 1213575: Handle the case where we have to set a read-only
2359     // property through an interceptor and only do it if it's
2360     // uninitialized, e.g. the hole. Nirk...
2361     // Passing non-strict mode because the property is writable.
2362     RETURN_IF_EMPTY_HANDLE(
2363         isolate,
2364         JSReceiver::SetProperty(global, name, value, attributes,
2365                                 kNonStrictMode));
2366     return *value;
2367   }
2368 
2369   // Set the value, but only if we're assigning the initial value to a
2370   // constant. For now, we determine this by checking if the
2371   // current value is the hole.
2372   // Strict mode handling not needed (const is disallowed in strict mode).
2373   if (lookup.IsField()) {
2374     FixedArray* properties = global->properties();
2375     int index = lookup.GetFieldIndex().field_index();
2376     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2377       properties->set(index, *value);
2378     }
2379   } else if (lookup.IsNormal()) {
2380     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2381         !lookup.IsReadOnly()) {
2382       HandleScope scope(isolate);
2383       JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2384     }
2385   } else {
2386     // Ignore re-initialization of constants that have already been
2387     // assigned a constant value.
2388     ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2389   }
2390 
2391   // Use the set value as the result of the operation.
2392   return *value;
2393 }
2394 
2395 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeConstContextSlot)2396 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
2397   HandleScope scope(isolate);
2398   ASSERT(args.length() == 3);
2399 
2400   Handle<Object> value(args[0], isolate);
2401   ASSERT(!value->IsTheHole());
2402 
2403   // Initializations are always done in a function or native context.
2404   RUNTIME_ASSERT(args[1]->IsContext());
2405   Handle<Context> context(Context::cast(args[1])->declaration_context());
2406 
2407   Handle<String> name(String::cast(args[2]));
2408 
2409   int index;
2410   PropertyAttributes attributes;
2411   ContextLookupFlags flags = FOLLOW_CHAINS;
2412   BindingFlags binding_flags;
2413   Handle<Object> holder =
2414       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2415 
2416   if (index >= 0) {
2417     ASSERT(holder->IsContext());
2418     // Property was found in a context.  Perform the assignment if we
2419     // found some non-constant or an uninitialized constant.
2420     Handle<Context> context = Handle<Context>::cast(holder);
2421     if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
2422       context->set(index, *value);
2423     }
2424     return *value;
2425   }
2426 
2427   // The property could not be found, we introduce it as a property of the
2428   // global object.
2429   if (attributes == ABSENT) {
2430     Handle<JSObject> global = Handle<JSObject>(
2431         isolate->context()->global_object());
2432     // Strict mode not needed (const disallowed in strict mode).
2433     RETURN_IF_EMPTY_HANDLE(
2434         isolate,
2435         JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
2436     return *value;
2437   }
2438 
2439   // The property was present in some function's context extension object,
2440   // as a property on the subject of a with, or as a property of the global
2441   // object.
2442   //
2443   // In most situations, eval-introduced consts should still be present in
2444   // the context extension object.  However, because declaration and
2445   // initialization are separate, the property might have been deleted
2446   // before we reach the initialization point.
2447   //
2448   // Example:
2449   //
2450   //    function f() { eval("delete x; const x;"); }
2451   //
2452   // In that case, the initialization behaves like a normal assignment.
2453   Handle<JSObject> object = Handle<JSObject>::cast(holder);
2454 
2455   if (*object == context->extension()) {
2456     // This is the property that was introduced by the const declaration.
2457     // Set it if it hasn't been set before.  NOTE: We cannot use
2458     // GetProperty() to get the current value as it 'unholes' the value.
2459     LookupResult lookup(isolate);
2460     object->LocalLookupRealNamedProperty(*name, &lookup);
2461     ASSERT(lookup.IsFound());  // the property was declared
2462     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
2463 
2464     if (lookup.IsField()) {
2465       FixedArray* properties = object->properties();
2466       int index = lookup.GetFieldIndex().field_index();
2467       if (properties->get(index)->IsTheHole()) {
2468         properties->set(index, *value);
2469       }
2470     } else if (lookup.IsNormal()) {
2471       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2472         JSObject::SetNormalizedProperty(object, &lookup, value);
2473       }
2474     } else {
2475       // We should not reach here. Any real, named property should be
2476       // either a field or a dictionary slot.
2477       UNREACHABLE();
2478     }
2479   } else {
2480     // The property was found on some other object.  Set it if it is not a
2481     // read-only property.
2482     if ((attributes & READ_ONLY) == 0) {
2483       // Strict mode not needed (const disallowed in strict mode).
2484       RETURN_IF_EMPTY_HANDLE(
2485           isolate,
2486           JSReceiver::SetProperty(object, name, value, attributes,
2487                                   kNonStrictMode));
2488     }
2489   }
2490 
2491   return *value;
2492 }
2493 
2494 
RUNTIME_FUNCTION(MaybeObject *,Runtime_OptimizeObjectForAddingMultipleProperties)2495 RUNTIME_FUNCTION(MaybeObject*,
2496                  Runtime_OptimizeObjectForAddingMultipleProperties) {
2497   HandleScope scope(isolate);
2498   ASSERT(args.length() == 2);
2499   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2500   CONVERT_SMI_ARG_CHECKED(properties, 1);
2501   if (object->HasFastProperties()) {
2502     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
2503   }
2504   return *object;
2505 }
2506 
2507 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpExec)2508 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
2509   HandleScope scope(isolate);
2510   ASSERT(args.length() == 4);
2511   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2512   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2513   // Due to the way the JS calls are constructed this must be less than the
2514   // length of a string, i.e. it is always a Smi.  We check anyway for security.
2515   CONVERT_SMI_ARG_CHECKED(index, 2);
2516   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2517   RUNTIME_ASSERT(index >= 0);
2518   RUNTIME_ASSERT(index <= subject->length());
2519   isolate->counters()->regexp_entry_runtime()->Increment();
2520   Handle<Object> result = RegExpImpl::Exec(regexp,
2521                                            subject,
2522                                            index,
2523                                            last_match_info);
2524   RETURN_IF_EMPTY_HANDLE(isolate, result);
2525   return *result;
2526 }
2527 
2528 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpConstructResult)2529 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
2530   SealHandleScope shs(isolate);
2531   ASSERT(args.length() == 3);
2532   CONVERT_SMI_ARG_CHECKED(elements_count, 0);
2533   if (elements_count < 0 ||
2534       elements_count > FixedArray::kMaxLength ||
2535       !Smi::IsValid(elements_count)) {
2536     return isolate->ThrowIllegalOperation();
2537   }
2538   Object* new_object;
2539   { MaybeObject* maybe_new_object =
2540         isolate->heap()->AllocateFixedArray(elements_count);
2541     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2542   }
2543   FixedArray* elements = FixedArray::cast(new_object);
2544   { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
2545       JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
2546     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2547   }
2548   {
2549     DisallowHeapAllocation no_gc;
2550     HandleScope scope(isolate);
2551     reinterpret_cast<HeapObject*>(new_object)->
2552         set_map(isolate->native_context()->regexp_result_map());
2553   }
2554   JSArray* array = JSArray::cast(new_object);
2555   array->set_properties(isolate->heap()->empty_fixed_array());
2556   array->set_elements(elements);
2557   array->set_length(Smi::FromInt(elements_count));
2558   // Write in-object properties after the length of the array.
2559   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
2560   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
2561   return array;
2562 }
2563 
2564 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpInitializeObject)2565 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
2566   HandleScope scope(isolate);
2567   DisallowHeapAllocation no_allocation;
2568   ASSERT(args.length() == 5);
2569   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2570   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2571   // If source is the empty string we set it to "(?:)" instead as
2572   // suggested by ECMA-262, 5th, section 15.10.4.1.
2573   if (source->length() == 0) source = isolate->factory()->query_colon_string();
2574 
2575   CONVERT_ARG_HANDLE_CHECKED(Object, global, 2);
2576   if (!global->IsTrue()) global = isolate->factory()->false_value();
2577 
2578   CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3);
2579   if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value();
2580 
2581   CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4);
2582   if (!multiline->IsTrue()) multiline = isolate->factory()->false_value();
2583 
2584   Map* map = regexp->map();
2585   Object* constructor = map->constructor();
2586   if (constructor->IsJSFunction() &&
2587       JSFunction::cast(constructor)->initial_map() == map) {
2588     // If we still have the original map, set in-object properties directly.
2589     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source);
2590     // Both true and false are immovable immortal objects so no need for write
2591     // barrier.
2592     regexp->InObjectPropertyAtPut(
2593         JSRegExp::kGlobalFieldIndex, *global, SKIP_WRITE_BARRIER);
2594     regexp->InObjectPropertyAtPut(
2595         JSRegExp::kIgnoreCaseFieldIndex, *ignoreCase, SKIP_WRITE_BARRIER);
2596     regexp->InObjectPropertyAtPut(
2597         JSRegExp::kMultilineFieldIndex, *multiline, SKIP_WRITE_BARRIER);
2598     regexp->InObjectPropertyAtPut(
2599         JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
2600     return *regexp;
2601   }
2602 
2603   // Map has changed, so use generic, but slower, method.
2604   PropertyAttributes final =
2605       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2606   PropertyAttributes writable =
2607       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2608   Handle<Object> zero(Smi::FromInt(0), isolate);
2609   Factory* factory = isolate->factory();
2610   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2611       regexp, factory->source_string(), source, final));
2612   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2613       regexp, factory->global_string(), global, final));
2614   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2615       regexp, factory->ignore_case_string(), ignoreCase, final));
2616   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2617       regexp, factory->multiline_string(), multiline, final));
2618   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2619       regexp, factory->last_index_string(), zero, writable));
2620   return *regexp;
2621 }
2622 
2623 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FinishArrayPrototypeSetup)2624 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
2625   HandleScope scope(isolate);
2626   ASSERT(args.length() == 1);
2627   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2628   // This is necessary to enable fast checks for absence of elements
2629   // on Array.prototype and below.
2630   prototype->set_elements(isolate->heap()->empty_fixed_array());
2631   return Smi::FromInt(0);
2632 }
2633 
2634 
InstallBuiltin(Isolate * isolate,Handle<JSObject> holder,const char * name,Builtins::Name builtin_name)2635 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
2636                                          Handle<JSObject> holder,
2637                                          const char* name,
2638                                          Builtins::Name builtin_name) {
2639   Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2640   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2641   Handle<JSFunction> optimized =
2642       isolate->factory()->NewFunction(key,
2643                                       JS_OBJECT_TYPE,
2644                                       JSObject::kHeaderSize,
2645                                       code,
2646                                       false);
2647   optimized->shared()->DontAdaptArguments();
2648   JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
2649   return optimized;
2650 }
2651 
2652 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SpecialArrayFunctions)2653 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
2654   HandleScope scope(isolate);
2655   ASSERT(args.length() == 1);
2656   CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
2657 
2658   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2659   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2660   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2661   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2662   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2663   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2664   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2665 
2666   return *holder;
2667 }
2668 
2669 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsCallable)2670 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsCallable) {
2671   SealHandleScope shs(isolate);
2672   ASSERT(args.length() == 1);
2673   CONVERT_ARG_CHECKED(Object, obj, 0);
2674   return isolate->heap()->ToBoolean(obj->IsCallable());
2675 }
2676 
2677 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsClassicModeFunction)2678 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) {
2679   SealHandleScope shs(isolate);
2680   ASSERT(args.length() == 1);
2681   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2682   if (!callable->IsJSFunction()) {
2683     HandleScope scope(isolate);
2684     bool threw = false;
2685     Handle<Object> delegate = Execution::TryGetFunctionDelegate(
2686         isolate, Handle<JSReceiver>(callable), &threw);
2687     if (threw) return Failure::Exception();
2688     callable = JSFunction::cast(*delegate);
2689   }
2690   JSFunction* function = JSFunction::cast(callable);
2691   SharedFunctionInfo* shared = function->shared();
2692   return isolate->heap()->ToBoolean(shared->is_classic_mode());
2693 }
2694 
2695 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetDefaultReceiver)2696 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
2697   SealHandleScope shs(isolate);
2698   ASSERT(args.length() == 1);
2699   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2700 
2701   if (!callable->IsJSFunction()) {
2702     HandleScope scope(isolate);
2703     bool threw = false;
2704     Handle<Object> delegate = Execution::TryGetFunctionDelegate(
2705         isolate, Handle<JSReceiver>(callable), &threw);
2706     if (threw) return Failure::Exception();
2707     callable = JSFunction::cast(*delegate);
2708   }
2709   JSFunction* function = JSFunction::cast(callable);
2710 
2711   SharedFunctionInfo* shared = function->shared();
2712   if (shared->native() || !shared->is_classic_mode()) {
2713     return isolate->heap()->undefined_value();
2714   }
2715   // Returns undefined for strict or native functions, or
2716   // the associated global receiver for "normal" functions.
2717 
2718   Context* native_context =
2719       function->context()->global_object()->native_context();
2720   return native_context->global_object()->global_receiver();
2721 }
2722 
2723 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MaterializeRegExpLiteral)2724 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
2725   HandleScope scope(isolate);
2726   ASSERT(args.length() == 4);
2727   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2728   int index = args.smi_at(1);
2729   Handle<String> pattern = args.at<String>(2);
2730   Handle<String> flags = args.at<String>(3);
2731 
2732   // Get the RegExp function from the context in the literals array.
2733   // This is the RegExp function from the context in which the
2734   // function was created.  We do not use the RegExp function from the
2735   // current native context because this might be the RegExp function
2736   // from another context which we should not have access to.
2737   Handle<JSFunction> constructor =
2738       Handle<JSFunction>(
2739           JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2740   // Compute the regular expression literal.
2741   bool has_pending_exception;
2742   Handle<Object> regexp =
2743       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2744                                       &has_pending_exception);
2745   if (has_pending_exception) {
2746     ASSERT(isolate->has_pending_exception());
2747     return Failure::Exception();
2748   }
2749   literals->set(index, *regexp);
2750   return *regexp;
2751 }
2752 
2753 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetName)2754 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2755   SealHandleScope shs(isolate);
2756   ASSERT(args.length() == 1);
2757 
2758   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2759   return f->shared()->name();
2760 }
2761 
2762 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetName)2763 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2764   SealHandleScope shs(isolate);
2765   ASSERT(args.length() == 2);
2766 
2767   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2768   CONVERT_ARG_CHECKED(String, name, 1);
2769   f->shared()->set_name(name);
2770   return isolate->heap()->undefined_value();
2771 }
2772 
2773 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionNameShouldPrintAsAnonymous)2774 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2775   SealHandleScope shs(isolate);
2776   ASSERT(args.length() == 1);
2777   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2778   return isolate->heap()->ToBoolean(
2779       f->shared()->name_should_print_as_anonymous());
2780 }
2781 
2782 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionMarkNameShouldPrintAsAnonymous)2783 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2784   SealHandleScope shs(isolate);
2785   ASSERT(args.length() == 1);
2786   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2787   f->shared()->set_name_should_print_as_anonymous(true);
2788   return isolate->heap()->undefined_value();
2789 }
2790 
2791 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionIsGenerator)2792 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
2793   SealHandleScope shs(isolate);
2794   ASSERT(args.length() == 1);
2795   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2796   return isolate->heap()->ToBoolean(f->shared()->is_generator());
2797 }
2798 
2799 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionRemovePrototype)2800 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2801   SealHandleScope shs(isolate);
2802   ASSERT(args.length() == 1);
2803 
2804   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2805   f->RemovePrototype();
2806 
2807   return isolate->heap()->undefined_value();
2808 }
2809 
2810 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetScript)2811 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2812   HandleScope scope(isolate);
2813   ASSERT(args.length() == 1);
2814 
2815   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2816   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2817   if (!script->IsScript()) return isolate->heap()->undefined_value();
2818 
2819   return *GetScriptWrapper(Handle<Script>::cast(script));
2820 }
2821 
2822 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetSourceCode)2823 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2824   HandleScope scope(isolate);
2825   ASSERT(args.length() == 1);
2826 
2827   CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2828   Handle<SharedFunctionInfo> shared(f->shared());
2829   return *shared->GetSourceCode();
2830 }
2831 
2832 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetScriptSourcePosition)2833 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2834   SealHandleScope shs(isolate);
2835   ASSERT(args.length() == 1);
2836 
2837   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2838   int pos = fun->shared()->start_position();
2839   return Smi::FromInt(pos);
2840 }
2841 
2842 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetPositionForOffset)2843 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2844   SealHandleScope shs(isolate);
2845   ASSERT(args.length() == 2);
2846 
2847   CONVERT_ARG_CHECKED(Code, code, 0);
2848   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2849 
2850   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2851 
2852   Address pc = code->address() + offset;
2853   return Smi::FromInt(code->SourcePosition(pc));
2854 }
2855 
2856 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetInstanceClassName)2857 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2858   SealHandleScope shs(isolate);
2859   ASSERT(args.length() == 2);
2860 
2861   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2862   CONVERT_ARG_CHECKED(String, name, 1);
2863   fun->SetInstanceClassName(name);
2864   return isolate->heap()->undefined_value();
2865 }
2866 
2867 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetLength)2868 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2869   SealHandleScope shs(isolate);
2870   ASSERT(args.length() == 2);
2871 
2872   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2873   CONVERT_SMI_ARG_CHECKED(length, 1);
2874   fun->shared()->set_length(length);
2875   return isolate->heap()->undefined_value();
2876 }
2877 
2878 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetPrototype)2879 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2880   HandleScope scope(isolate);
2881   ASSERT(args.length() == 2);
2882 
2883   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
2884   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
2885   ASSERT(fun->should_have_prototype());
2886   Accessors::FunctionSetPrototype(fun, value);
2887   return args[0];  // return TOS
2888 }
2889 
2890 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetReadOnlyPrototype)2891 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2892   SealHandleScope shs(isolate);
2893   RUNTIME_ASSERT(args.length() == 1);
2894   CONVERT_ARG_CHECKED(JSFunction, function, 0);
2895 
2896   String* name = isolate->heap()->prototype_string();
2897 
2898   if (function->HasFastProperties()) {
2899     // Construct a new field descriptor with updated attributes.
2900     DescriptorArray* instance_desc = function->map()->instance_descriptors();
2901 
2902     int index = instance_desc->SearchWithCache(name, function->map());
2903     ASSERT(index != DescriptorArray::kNotFound);
2904     PropertyDetails details = instance_desc->GetDetails(index);
2905 
2906     CallbacksDescriptor new_desc(name,
2907         instance_desc->GetValue(index),
2908         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
2909 
2910     // Create a new map featuring the new field descriptors array.
2911     Map* new_map;
2912     MaybeObject* maybe_map =
2913         function->map()->CopyReplaceDescriptor(
2914             instance_desc, &new_desc, index, OMIT_TRANSITION);
2915     if (!maybe_map->To(&new_map)) return maybe_map;
2916 
2917     function->set_map(new_map);
2918   } else {  // Dictionary properties.
2919     // Directly manipulate the property details.
2920     int entry = function->property_dictionary()->FindEntry(name);
2921     ASSERT(entry != NameDictionary::kNotFound);
2922     PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2923     PropertyDetails new_details(
2924         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2925         details.type(),
2926         details.dictionary_index());
2927     function->property_dictionary()->DetailsAtPut(entry, new_details);
2928   }
2929   return function;
2930 }
2931 
2932 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionIsAPIFunction)2933 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2934   SealHandleScope shs(isolate);
2935   ASSERT(args.length() == 1);
2936 
2937   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2938   return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2939 }
2940 
2941 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionIsBuiltin)2942 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2943   SealHandleScope shs(isolate);
2944   ASSERT(args.length() == 1);
2945 
2946   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2947   return isolate->heap()->ToBoolean(f->IsBuiltin());
2948 }
2949 
2950 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetCode)2951 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2952   HandleScope scope(isolate);
2953   ASSERT(args.length() == 2);
2954 
2955   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2956   Handle<Object> code = args.at<Object>(1);
2957 
2958   if (code->IsNull()) return *target;
2959   RUNTIME_ASSERT(code->IsJSFunction());
2960   Handle<JSFunction> source = Handle<JSFunction>::cast(code);
2961   Handle<SharedFunctionInfo> target_shared(target->shared());
2962   Handle<SharedFunctionInfo> source_shared(source->shared());
2963 
2964   if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
2965     return Failure::Exception();
2966   }
2967 
2968   // Mark both, the source and the target, as un-flushable because the
2969   // shared unoptimized code makes them impossible to enqueue in a list.
2970   ASSERT(target_shared->code()->gc_metadata() == NULL);
2971   ASSERT(source_shared->code()->gc_metadata() == NULL);
2972   target_shared->set_dont_flush(true);
2973   source_shared->set_dont_flush(true);
2974 
2975   // Set the code, scope info, formal parameter count, and the length
2976   // of the target shared function info.
2977   target_shared->ReplaceCode(source_shared->code());
2978   target_shared->set_scope_info(source_shared->scope_info());
2979   target_shared->set_length(source_shared->length());
2980   target_shared->set_formal_parameter_count(
2981       source_shared->formal_parameter_count());
2982   target_shared->set_script(source_shared->script());
2983   target_shared->set_start_position_and_type(
2984       source_shared->start_position_and_type());
2985   target_shared->set_end_position(source_shared->end_position());
2986   bool was_native = target_shared->native();
2987   target_shared->set_compiler_hints(source_shared->compiler_hints());
2988   target_shared->set_native(was_native);
2989 
2990   // Set the code of the target function.
2991   target->ReplaceCode(source_shared->code());
2992   ASSERT(target->next_function_link()->IsUndefined());
2993 
2994   // Make sure we get a fresh copy of the literal vector to avoid cross
2995   // context contamination.
2996   Handle<Context> context(source->context());
2997   int number_of_literals = source->NumberOfLiterals();
2998   Handle<FixedArray> literals =
2999       isolate->factory()->NewFixedArray(number_of_literals, TENURED);
3000   if (number_of_literals > 0) {
3001     literals->set(JSFunction::kLiteralNativeContextIndex,
3002                   context->native_context());
3003   }
3004   target->set_context(*context);
3005   target->set_literals(*literals);
3006 
3007   if (isolate->logger()->is_logging_code_events() ||
3008       isolate->cpu_profiler()->is_profiling()) {
3009     isolate->logger()->LogExistingFunction(
3010         source_shared, Handle<Code>(source_shared->code()));
3011   }
3012 
3013   return *target;
3014 }
3015 
3016 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetExpectedNumberOfProperties)3017 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
3018   HandleScope scope(isolate);
3019   ASSERT(args.length() == 2);
3020   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
3021   CONVERT_SMI_ARG_CHECKED(num, 1);
3022   RUNTIME_ASSERT(num >= 0);
3023   // If objects constructed from this function exist then changing
3024   // 'estimated_nof_properties' is dangerous since the previous value might
3025   // have been compiled into the fast construct stub. Moreover, the inobject
3026   // slack tracking logic might have adjusted the previous value, so even
3027   // passing the same value is risky.
3028   if (!func->shared()->live_objects_may_exist()) {
3029     func->shared()->set_expected_nof_properties(num);
3030     if (func->has_initial_map()) {
3031       Handle<Map> new_initial_map =
3032           func->GetIsolate()->factory()->CopyMap(
3033               Handle<Map>(func->initial_map()));
3034       new_initial_map->set_unused_property_fields(num);
3035       func->set_initial_map(*new_initial_map);
3036     }
3037   }
3038   return isolate->heap()->undefined_value();
3039 }
3040 
3041 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateJSGeneratorObject)3042 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
3043   HandleScope scope(isolate);
3044   ASSERT(args.length() == 0);
3045 
3046   JavaScriptFrameIterator it(isolate);
3047   JavaScriptFrame* frame = it.frame();
3048   Handle<JSFunction> function(frame->function());
3049   RUNTIME_ASSERT(function->shared()->is_generator());
3050 
3051   Handle<JSGeneratorObject> generator;
3052   if (frame->IsConstructor()) {
3053     generator = handle(JSGeneratorObject::cast(frame->receiver()));
3054   } else {
3055     generator = isolate->factory()->NewJSGeneratorObject(function);
3056   }
3057   generator->set_function(*function);
3058   generator->set_context(Context::cast(frame->context()));
3059   generator->set_receiver(frame->receiver());
3060   generator->set_continuation(0);
3061   generator->set_operand_stack(isolate->heap()->empty_fixed_array());
3062   generator->set_stack_handler_index(-1);
3063 
3064   return *generator;
3065 }
3066 
3067 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SuspendJSGeneratorObject)3068 RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
3069   SealHandleScope shs(isolate);
3070   ASSERT(args.length() == 1);
3071   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3072 
3073   JavaScriptFrameIterator stack_iterator(isolate);
3074   JavaScriptFrame* frame = stack_iterator.frame();
3075   RUNTIME_ASSERT(frame->function()->shared()->is_generator());
3076   ASSERT_EQ(frame->function(), generator_object->function());
3077 
3078   // The caller should have saved the context and continuation already.
3079   ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
3080   ASSERT_LT(0, generator_object->continuation());
3081 
3082   // We expect there to be at least two values on the operand stack: the return
3083   // value of the yield expression, and the argument to this runtime call.
3084   // Neither of those should be saved.
3085   int operands_count = frame->ComputeOperandsCount();
3086   ASSERT_GE(operands_count, 2);
3087   operands_count -= 2;
3088 
3089   if (operands_count == 0) {
3090     // Although it's semantically harmless to call this function with an
3091     // operands_count of zero, it is also unnecessary.
3092     ASSERT_EQ(generator_object->operand_stack(),
3093               isolate->heap()->empty_fixed_array());
3094     ASSERT_EQ(generator_object->stack_handler_index(), -1);
3095     // If there are no operands on the stack, there shouldn't be a handler
3096     // active either.
3097     ASSERT(!frame->HasHandler());
3098   } else {
3099     int stack_handler_index = -1;
3100     MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
3101     FixedArray* operand_stack;
3102     if (!alloc->To(&operand_stack)) return alloc;
3103     frame->SaveOperandStack(operand_stack, &stack_handler_index);
3104     generator_object->set_operand_stack(operand_stack);
3105     generator_object->set_stack_handler_index(stack_handler_index);
3106   }
3107 
3108   return isolate->heap()->undefined_value();
3109 }
3110 
3111 
3112 // Note that this function is the slow path for resuming generators.  It is only
3113 // called if the suspended activation had operands on the stack, stack handlers
3114 // needing rewinding, or if the resume should throw an exception.  The fast path
3115 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3116 // inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
3117 // called in any case, as it needs to reconstruct the stack frame and make space
3118 // for arguments and operands.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ResumeJSGeneratorObject)3119 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
3120   SealHandleScope shs(isolate);
3121   ASSERT(args.length() == 3);
3122   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3123   CONVERT_ARG_CHECKED(Object, value, 1);
3124   CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3125   JavaScriptFrameIterator stack_iterator(isolate);
3126   JavaScriptFrame* frame = stack_iterator.frame();
3127 
3128   ASSERT_EQ(frame->function(), generator_object->function());
3129   ASSERT(frame->function()->is_compiled());
3130 
3131   STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
3132   STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
3133 
3134   Address pc = generator_object->function()->code()->instruction_start();
3135   int offset = generator_object->continuation();
3136   ASSERT(offset > 0);
3137   frame->set_pc(pc + offset);
3138   generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3139 
3140   FixedArray* operand_stack = generator_object->operand_stack();
3141   int operands_count = operand_stack->length();
3142   if (operands_count != 0) {
3143     frame->RestoreOperandStack(operand_stack,
3144                                generator_object->stack_handler_index());
3145     generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3146     generator_object->set_stack_handler_index(-1);
3147   }
3148 
3149   JSGeneratorObject::ResumeMode resume_mode =
3150       static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3151   switch (resume_mode) {
3152     case JSGeneratorObject::NEXT:
3153       return value;
3154     case JSGeneratorObject::THROW:
3155       return isolate->Throw(value);
3156   }
3157 
3158   UNREACHABLE();
3159   return isolate->ThrowIllegalOperation();
3160 }
3161 
3162 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ThrowGeneratorStateError)3163 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
3164   HandleScope scope(isolate);
3165   ASSERT(args.length() == 1);
3166   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
3167   int continuation = generator->continuation();
3168   const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3169       "generator_finished" : "generator_running";
3170   Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3171   Handle<Object> error = isolate->factory()->NewError(message, argv);
3172   return isolate->Throw(*error);
3173 }
3174 
3175 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ObjectFreeze)3176 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
3177   HandleScope scope(isolate);
3178   ASSERT(args.length() == 1);
3179   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
3180   Handle<Object> result = JSObject::Freeze(object);
3181   RETURN_IF_EMPTY_HANDLE(isolate, result);
3182   return *result;
3183 }
3184 
3185 
CharFromCode(Isolate * isolate,Object * char_code)3186 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
3187                                                  Object* char_code) {
3188   if (char_code->IsNumber()) {
3189     return isolate->heap()->LookupSingleCharacterStringFromCode(
3190         NumberToUint32(char_code) & 0xffff);
3191   }
3192   return isolate->heap()->empty_string();
3193 }
3194 
3195 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringCharCodeAt)3196 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
3197   SealHandleScope shs(isolate);
3198   ASSERT(args.length() == 2);
3199 
3200   CONVERT_ARG_CHECKED(String, subject, 0);
3201   CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3202 
3203   // Flatten the string.  If someone wants to get a char at an index
3204   // in a cons string, it is likely that more indices will be
3205   // accessed.
3206   Object* flat;
3207   { MaybeObject* maybe_flat = subject->TryFlatten();
3208     if (!maybe_flat->ToObject(&flat)) return maybe_flat;
3209   }
3210   subject = String::cast(flat);
3211 
3212   if (i >= static_cast<uint32_t>(subject->length())) {
3213     return isolate->heap()->nan_value();
3214   }
3215 
3216   return Smi::FromInt(subject->Get(i));
3217 }
3218 
3219 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CharFromCode)3220 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
3221   SealHandleScope shs(isolate);
3222   ASSERT(args.length() == 1);
3223   return CharFromCode(isolate, args[0]);
3224 }
3225 
3226 
3227 class FixedArrayBuilder {
3228  public:
FixedArrayBuilder(Isolate * isolate,int initial_capacity)3229   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3230       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3231         length_(0),
3232         has_non_smi_elements_(false) {
3233     // Require a non-zero initial size. Ensures that doubling the size to
3234     // extend the array will work.
3235     ASSERT(initial_capacity > 0);
3236   }
3237 
FixedArrayBuilder(Handle<FixedArray> backing_store)3238   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3239       : array_(backing_store),
3240         length_(0),
3241         has_non_smi_elements_(false) {
3242     // Require a non-zero initial size. Ensures that doubling the size to
3243     // extend the array will work.
3244     ASSERT(backing_store->length() > 0);
3245   }
3246 
HasCapacity(int elements)3247   bool HasCapacity(int elements) {
3248     int length = array_->length();
3249     int required_length = length_ + elements;
3250     return (length >= required_length);
3251   }
3252 
EnsureCapacity(int elements)3253   void EnsureCapacity(int elements) {
3254     int length = array_->length();
3255     int required_length = length_ + elements;
3256     if (length < required_length) {
3257       int new_length = length;
3258       do {
3259         new_length *= 2;
3260       } while (new_length < required_length);
3261       Handle<FixedArray> extended_array =
3262           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3263       array_->CopyTo(0, *extended_array, 0, length_);
3264       array_ = extended_array;
3265     }
3266   }
3267 
Add(Object * value)3268   void Add(Object* value) {
3269     ASSERT(!value->IsSmi());
3270     ASSERT(length_ < capacity());
3271     array_->set(length_, value);
3272     length_++;
3273     has_non_smi_elements_ = true;
3274   }
3275 
Add(Smi * value)3276   void Add(Smi* value) {
3277     ASSERT(value->IsSmi());
3278     ASSERT(length_ < capacity());
3279     array_->set(length_, value);
3280     length_++;
3281   }
3282 
array()3283   Handle<FixedArray> array() {
3284     return array_;
3285   }
3286 
length()3287   int length() {
3288     return length_;
3289   }
3290 
capacity()3291   int capacity() {
3292     return array_->length();
3293   }
3294 
ToJSArray(Handle<JSArray> target_array)3295   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
3296     Factory* factory = target_array->GetIsolate()->factory();
3297     factory->SetContent(target_array, array_);
3298     target_array->set_length(Smi::FromInt(length_));
3299     return target_array;
3300   }
3301 
3302 
3303  private:
3304   Handle<FixedArray> array_;
3305   int length_;
3306   bool has_non_smi_elements_;
3307 };
3308 
3309 
3310 // Forward declarations.
3311 const int kStringBuilderConcatHelperLengthBits = 11;
3312 const int kStringBuilderConcatHelperPositionBits = 19;
3313 
3314 template <typename schar>
3315 static inline void StringBuilderConcatHelper(String*,
3316                                              schar*,
3317                                              FixedArray*,
3318                                              int);
3319 
3320 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
3321     StringBuilderSubstringLength;
3322 typedef BitField<int,
3323                  kStringBuilderConcatHelperLengthBits,
3324                  kStringBuilderConcatHelperPositionBits>
3325     StringBuilderSubstringPosition;
3326 
3327 
3328 class ReplacementStringBuilder {
3329  public:
ReplacementStringBuilder(Heap * heap,Handle<String> subject,int estimated_part_count)3330   ReplacementStringBuilder(Heap* heap,
3331                            Handle<String> subject,
3332                            int estimated_part_count)
3333       : heap_(heap),
3334         array_builder_(heap->isolate(), estimated_part_count),
3335         subject_(subject),
3336         character_count_(0),
3337         is_ascii_(subject->IsOneByteRepresentation()) {
3338     // Require a non-zero initial size. Ensures that doubling the size to
3339     // extend the array will work.
3340     ASSERT(estimated_part_count > 0);
3341   }
3342 
AddSubjectSlice(FixedArrayBuilder * builder,int from,int to)3343   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3344                                      int from,
3345                                      int to) {
3346     ASSERT(from >= 0);
3347     int length = to - from;
3348     ASSERT(length > 0);
3349     if (StringBuilderSubstringLength::is_valid(length) &&
3350         StringBuilderSubstringPosition::is_valid(from)) {
3351       int encoded_slice = StringBuilderSubstringLength::encode(length) |
3352           StringBuilderSubstringPosition::encode(from);
3353       builder->Add(Smi::FromInt(encoded_slice));
3354     } else {
3355       // Otherwise encode as two smis.
3356       builder->Add(Smi::FromInt(-length));
3357       builder->Add(Smi::FromInt(from));
3358     }
3359   }
3360 
3361 
EnsureCapacity(int elements)3362   void EnsureCapacity(int elements) {
3363     array_builder_.EnsureCapacity(elements);
3364   }
3365 
3366 
AddSubjectSlice(int from,int to)3367   void AddSubjectSlice(int from, int to) {
3368     AddSubjectSlice(&array_builder_, from, to);
3369     IncrementCharacterCount(to - from);
3370   }
3371 
3372 
AddString(Handle<String> string)3373   void AddString(Handle<String> string) {
3374     int length = string->length();
3375     ASSERT(length > 0);
3376     AddElement(*string);
3377     if (!string->IsOneByteRepresentation()) {
3378       is_ascii_ = false;
3379     }
3380     IncrementCharacterCount(length);
3381   }
3382 
3383 
ToString()3384   Handle<String> ToString() {
3385     if (array_builder_.length() == 0) {
3386       return heap_->isolate()->factory()->empty_string();
3387     }
3388 
3389     Handle<String> joined_string;
3390     if (is_ascii_) {
3391       Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3392       DisallowHeapAllocation no_gc;
3393       uint8_t* char_buffer = seq->GetChars();
3394       StringBuilderConcatHelper(*subject_,
3395                                 char_buffer,
3396                                 *array_builder_.array(),
3397                                 array_builder_.length());
3398       joined_string = Handle<String>::cast(seq);
3399     } else {
3400       // Non-ASCII.
3401       Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3402       DisallowHeapAllocation no_gc;
3403       uc16* char_buffer = seq->GetChars();
3404       StringBuilderConcatHelper(*subject_,
3405                                 char_buffer,
3406                                 *array_builder_.array(),
3407                                 array_builder_.length());
3408       joined_string = Handle<String>::cast(seq);
3409     }
3410     return joined_string;
3411   }
3412 
3413 
IncrementCharacterCount(int by)3414   void IncrementCharacterCount(int by) {
3415     if (character_count_ > String::kMaxLength - by) {
3416       V8::FatalProcessOutOfMemory("String.replace result too large.");
3417     }
3418     character_count_ += by;
3419   }
3420 
3421  private:
NewRawOneByteString(int length)3422   Handle<SeqOneByteString> NewRawOneByteString(int length) {
3423     return heap_->isolate()->factory()->NewRawOneByteString(length);
3424   }
3425 
3426 
NewRawTwoByteString(int length)3427   Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3428     return heap_->isolate()->factory()->NewRawTwoByteString(length);
3429   }
3430 
3431 
AddElement(Object * element)3432   void AddElement(Object* element) {
3433     ASSERT(element->IsSmi() || element->IsString());
3434     ASSERT(array_builder_.capacity() > array_builder_.length());
3435     array_builder_.Add(element);
3436   }
3437 
3438   Heap* heap_;
3439   FixedArrayBuilder array_builder_;
3440   Handle<String> subject_;
3441   int character_count_;
3442   bool is_ascii_;
3443 };
3444 
3445 
3446 class CompiledReplacement {
3447  public:
CompiledReplacement(Zone * zone)3448   explicit CompiledReplacement(Zone* zone)
3449       : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3450 
3451   // Return whether the replacement is simple.
3452   bool Compile(Handle<String> replacement,
3453                int capture_count,
3454                int subject_length);
3455 
3456   // Use Apply only if Compile returned false.
3457   void Apply(ReplacementStringBuilder* builder,
3458              int match_from,
3459              int match_to,
3460              int32_t* match);
3461 
3462   // Number of distinct parts of the replacement pattern.
parts()3463   int parts() {
3464     return parts_.length();
3465   }
3466 
zone() const3467   Zone* zone() const { return zone_; }
3468 
3469  private:
3470   enum PartType {
3471     SUBJECT_PREFIX = 1,
3472     SUBJECT_SUFFIX,
3473     SUBJECT_CAPTURE,
3474     REPLACEMENT_SUBSTRING,
3475     REPLACEMENT_STRING,
3476 
3477     NUMBER_OF_PART_TYPES
3478   };
3479 
3480   struct ReplacementPart {
SubjectMatchv8::internal::CompiledReplacement::ReplacementPart3481     static inline ReplacementPart SubjectMatch() {
3482       return ReplacementPart(SUBJECT_CAPTURE, 0);
3483     }
SubjectCapturev8::internal::CompiledReplacement::ReplacementPart3484     static inline ReplacementPart SubjectCapture(int capture_index) {
3485       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3486     }
SubjectPrefixv8::internal::CompiledReplacement::ReplacementPart3487     static inline ReplacementPart SubjectPrefix() {
3488       return ReplacementPart(SUBJECT_PREFIX, 0);
3489     }
SubjectSuffixv8::internal::CompiledReplacement::ReplacementPart3490     static inline ReplacementPart SubjectSuffix(int subject_length) {
3491       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3492     }
ReplacementStringv8::internal::CompiledReplacement::ReplacementPart3493     static inline ReplacementPart ReplacementString() {
3494       return ReplacementPart(REPLACEMENT_STRING, 0);
3495     }
ReplacementSubStringv8::internal::CompiledReplacement::ReplacementPart3496     static inline ReplacementPart ReplacementSubString(int from, int to) {
3497       ASSERT(from >= 0);
3498       ASSERT(to > from);
3499       return ReplacementPart(-from, to);
3500     }
3501 
3502     // If tag <= 0 then it is the negation of a start index of a substring of
3503     // the replacement pattern, otherwise it's a value from PartType.
ReplacementPartv8::internal::CompiledReplacement::ReplacementPart3504     ReplacementPart(int tag, int data)
3505         : tag(tag), data(data) {
3506       // Must be non-positive or a PartType value.
3507       ASSERT(tag < NUMBER_OF_PART_TYPES);
3508     }
3509     // Either a value of PartType or a non-positive number that is
3510     // the negation of an index into the replacement string.
3511     int tag;
3512     // The data value's interpretation depends on the value of tag:
3513     // tag == SUBJECT_PREFIX ||
3514     // tag == SUBJECT_SUFFIX:  data is unused.
3515     // tag == SUBJECT_CAPTURE: data is the number of the capture.
3516     // tag == REPLACEMENT_SUBSTRING ||
3517     // tag == REPLACEMENT_STRING:    data is index into array of substrings
3518     //                               of the replacement string.
3519     // tag <= 0: Temporary representation of the substring of the replacement
3520     //           string ranging over -tag .. data.
3521     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3522     //           substring objects.
3523     int data;
3524   };
3525 
3526   template<typename Char>
ParseReplacementPattern(ZoneList<ReplacementPart> * parts,Vector<Char> characters,int capture_count,int subject_length,Zone * zone)3527   bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3528                                Vector<Char> characters,
3529                                int capture_count,
3530                                int subject_length,
3531                                Zone* zone) {
3532     int length = characters.length();
3533     int last = 0;
3534     for (int i = 0; i < length; i++) {
3535       Char c = characters[i];
3536       if (c == '$') {
3537         int next_index = i + 1;
3538         if (next_index == length) {  // No next character!
3539           break;
3540         }
3541         Char c2 = characters[next_index];
3542         switch (c2) {
3543         case '$':
3544           if (i > last) {
3545             // There is a substring before. Include the first "$".
3546             parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3547                        zone);
3548             last = next_index + 1;  // Continue after the second "$".
3549           } else {
3550             // Let the next substring start with the second "$".
3551             last = next_index;
3552           }
3553           i = next_index;
3554           break;
3555         case '`':
3556           if (i > last) {
3557             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3558           }
3559           parts->Add(ReplacementPart::SubjectPrefix(), zone);
3560           i = next_index;
3561           last = i + 1;
3562           break;
3563         case '\'':
3564           if (i > last) {
3565             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3566           }
3567           parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3568           i = next_index;
3569           last = i + 1;
3570           break;
3571         case '&':
3572           if (i > last) {
3573             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3574           }
3575           parts->Add(ReplacementPart::SubjectMatch(), zone);
3576           i = next_index;
3577           last = i + 1;
3578           break;
3579         case '0':
3580         case '1':
3581         case '2':
3582         case '3':
3583         case '4':
3584         case '5':
3585         case '6':
3586         case '7':
3587         case '8':
3588         case '9': {
3589           int capture_ref = c2 - '0';
3590           if (capture_ref > capture_count) {
3591             i = next_index;
3592             continue;
3593           }
3594           int second_digit_index = next_index + 1;
3595           if (second_digit_index < length) {
3596             // Peek ahead to see if we have two digits.
3597             Char c3 = characters[second_digit_index];
3598             if ('0' <= c3 && c3 <= '9') {  // Double digits.
3599               int double_digit_ref = capture_ref * 10 + c3 - '0';
3600               if (double_digit_ref <= capture_count) {
3601                 next_index = second_digit_index;
3602                 capture_ref = double_digit_ref;
3603               }
3604             }
3605           }
3606           if (capture_ref > 0) {
3607             if (i > last) {
3608               parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3609             }
3610             ASSERT(capture_ref <= capture_count);
3611             parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3612             last = next_index + 1;
3613           }
3614           i = next_index;
3615           break;
3616         }
3617         default:
3618           i = next_index;
3619           break;
3620         }
3621       }
3622     }
3623     if (length > last) {
3624       if (last == 0) {
3625         // Replacement is simple.  Do not use Apply to do the replacement.
3626         return true;
3627       } else {
3628         parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3629       }
3630     }
3631     return false;
3632   }
3633 
3634   ZoneList<ReplacementPart> parts_;
3635   ZoneList<Handle<String> > replacement_substrings_;
3636   Zone* zone_;
3637 };
3638 
3639 
Compile(Handle<String> replacement,int capture_count,int subject_length)3640 bool CompiledReplacement::Compile(Handle<String> replacement,
3641                                   int capture_count,
3642                                   int subject_length) {
3643   {
3644     DisallowHeapAllocation no_gc;
3645     String::FlatContent content = replacement->GetFlatContent();
3646     ASSERT(content.IsFlat());
3647     bool simple = false;
3648     if (content.IsAscii()) {
3649       simple = ParseReplacementPattern(&parts_,
3650                                        content.ToOneByteVector(),
3651                                        capture_count,
3652                                        subject_length,
3653                                        zone());
3654     } else {
3655       ASSERT(content.IsTwoByte());
3656       simple = ParseReplacementPattern(&parts_,
3657                                        content.ToUC16Vector(),
3658                                        capture_count,
3659                                        subject_length,
3660                                        zone());
3661     }
3662     if (simple) return true;
3663   }
3664 
3665   Isolate* isolate = replacement->GetIsolate();
3666   // Find substrings of replacement string and create them as String objects.
3667   int substring_index = 0;
3668   for (int i = 0, n = parts_.length(); i < n; i++) {
3669     int tag = parts_[i].tag;
3670     if (tag <= 0) {  // A replacement string slice.
3671       int from = -tag;
3672       int to = parts_[i].data;
3673       replacement_substrings_.Add(
3674           isolate->factory()->NewSubString(replacement, from, to), zone());
3675       parts_[i].tag = REPLACEMENT_SUBSTRING;
3676       parts_[i].data = substring_index;
3677       substring_index++;
3678     } else if (tag == REPLACEMENT_STRING) {
3679       replacement_substrings_.Add(replacement, zone());
3680       parts_[i].data = substring_index;
3681       substring_index++;
3682     }
3683   }
3684   return false;
3685 }
3686 
3687 
Apply(ReplacementStringBuilder * builder,int match_from,int match_to,int32_t * match)3688 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
3689                                 int match_from,
3690                                 int match_to,
3691                                 int32_t* match) {
3692   ASSERT_LT(0, parts_.length());
3693   for (int i = 0, n = parts_.length(); i < n; i++) {
3694     ReplacementPart part = parts_[i];
3695     switch (part.tag) {
3696       case SUBJECT_PREFIX:
3697         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3698         break;
3699       case SUBJECT_SUFFIX: {
3700         int subject_length = part.data;
3701         if (match_to < subject_length) {
3702           builder->AddSubjectSlice(match_to, subject_length);
3703         }
3704         break;
3705       }
3706       case SUBJECT_CAPTURE: {
3707         int capture = part.data;
3708         int from = match[capture * 2];
3709         int to = match[capture * 2 + 1];
3710         if (from >= 0 && to > from) {
3711           builder->AddSubjectSlice(from, to);
3712         }
3713         break;
3714       }
3715       case REPLACEMENT_SUBSTRING:
3716       case REPLACEMENT_STRING:
3717         builder->AddString(replacement_substrings_[part.data]);
3718         break;
3719       default:
3720         UNREACHABLE();
3721     }
3722   }
3723 }
3724 
3725 
FindAsciiStringIndices(Vector<const uint8_t> subject,char pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3726 void FindAsciiStringIndices(Vector<const uint8_t> subject,
3727                             char pattern,
3728                             ZoneList<int>* indices,
3729                             unsigned int limit,
3730                             Zone* zone) {
3731   ASSERT(limit > 0);
3732   // Collect indices of pattern in subject using memchr.
3733   // Stop after finding at most limit values.
3734   const uint8_t* subject_start = subject.start();
3735   const uint8_t* subject_end = subject_start + subject.length();
3736   const uint8_t* pos = subject_start;
3737   while (limit > 0) {
3738     pos = reinterpret_cast<const uint8_t*>(
3739         memchr(pos, pattern, subject_end - pos));
3740     if (pos == NULL) return;
3741     indices->Add(static_cast<int>(pos - subject_start), zone);
3742     pos++;
3743     limit--;
3744   }
3745 }
3746 
3747 
FindTwoByteStringIndices(const Vector<const uc16> subject,uc16 pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3748 void FindTwoByteStringIndices(const Vector<const uc16> subject,
3749                               uc16 pattern,
3750                               ZoneList<int>* indices,
3751                               unsigned int limit,
3752                               Zone* zone) {
3753   ASSERT(limit > 0);
3754   const uc16* subject_start = subject.start();
3755   const uc16* subject_end = subject_start + subject.length();
3756   for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3757     if (*pos == pattern) {
3758       indices->Add(static_cast<int>(pos - subject_start), zone);
3759       limit--;
3760     }
3761   }
3762 }
3763 
3764 
3765 template <typename SubjectChar, typename PatternChar>
FindStringIndices(Isolate * isolate,Vector<const SubjectChar> subject,Vector<const PatternChar> pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3766 void FindStringIndices(Isolate* isolate,
3767                        Vector<const SubjectChar> subject,
3768                        Vector<const PatternChar> pattern,
3769                        ZoneList<int>* indices,
3770                        unsigned int limit,
3771                        Zone* zone) {
3772   ASSERT(limit > 0);
3773   // Collect indices of pattern in subject.
3774   // Stop after finding at most limit values.
3775   int pattern_length = pattern.length();
3776   int index = 0;
3777   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3778   while (limit > 0) {
3779     index = search.Search(subject, index);
3780     if (index < 0) return;
3781     indices->Add(index, zone);
3782     index += pattern_length;
3783     limit--;
3784   }
3785 }
3786 
3787 
FindStringIndicesDispatch(Isolate * isolate,String * subject,String * pattern,ZoneList<int> * indices,unsigned int limit,Zone * zone)3788 void FindStringIndicesDispatch(Isolate* isolate,
3789                                String* subject,
3790                                String* pattern,
3791                                ZoneList<int>* indices,
3792                                unsigned int limit,
3793                                Zone* zone) {
3794   {
3795     DisallowHeapAllocation no_gc;
3796     String::FlatContent subject_content = subject->GetFlatContent();
3797     String::FlatContent pattern_content = pattern->GetFlatContent();
3798     ASSERT(subject_content.IsFlat());
3799     ASSERT(pattern_content.IsFlat());
3800     if (subject_content.IsAscii()) {
3801       Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3802       if (pattern_content.IsAscii()) {
3803         Vector<const uint8_t> pattern_vector =
3804             pattern_content.ToOneByteVector();
3805         if (pattern_vector.length() == 1) {
3806           FindAsciiStringIndices(subject_vector,
3807                                  pattern_vector[0],
3808                                  indices,
3809                                  limit,
3810                                  zone);
3811         } else {
3812           FindStringIndices(isolate,
3813                             subject_vector,
3814                             pattern_vector,
3815                             indices,
3816                             limit,
3817                             zone);
3818         }
3819       } else {
3820         FindStringIndices(isolate,
3821                           subject_vector,
3822                           pattern_content.ToUC16Vector(),
3823                           indices,
3824                           limit,
3825                           zone);
3826       }
3827     } else {
3828       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3829       if (pattern_content.IsAscii()) {
3830         Vector<const uint8_t> pattern_vector =
3831             pattern_content.ToOneByteVector();
3832         if (pattern_vector.length() == 1) {
3833           FindTwoByteStringIndices(subject_vector,
3834                                    pattern_vector[0],
3835                                    indices,
3836                                    limit,
3837                                    zone);
3838         } else {
3839           FindStringIndices(isolate,
3840                             subject_vector,
3841                             pattern_vector,
3842                             indices,
3843                             limit,
3844                             zone);
3845         }
3846       } else {
3847         Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3848         if (pattern_vector.length() == 1) {
3849           FindTwoByteStringIndices(subject_vector,
3850                                    pattern_vector[0],
3851                                    indices,
3852                                    limit,
3853                                    zone);
3854         } else {
3855           FindStringIndices(isolate,
3856                             subject_vector,
3857                             pattern_vector,
3858                             indices,
3859                             limit,
3860                             zone);
3861         }
3862       }
3863     }
3864   }
3865 }
3866 
3867 
3868 template<typename ResultSeqString>
StringReplaceGlobalAtomRegExpWithString(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> pattern_regexp,Handle<String> replacement,Handle<JSArray> last_match_info)3869 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
3870     Isolate* isolate,
3871     Handle<String> subject,
3872     Handle<JSRegExp> pattern_regexp,
3873     Handle<String> replacement,
3874     Handle<JSArray> last_match_info) {
3875   ASSERT(subject->IsFlat());
3876   ASSERT(replacement->IsFlat());
3877 
3878   ZoneScope zone_scope(isolate->runtime_zone());
3879   ZoneList<int> indices(8, zone_scope.zone());
3880   ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3881   String* pattern =
3882       String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
3883   int subject_len = subject->length();
3884   int pattern_len = pattern->length();
3885   int replacement_len = replacement->length();
3886 
3887   FindStringIndicesDispatch(
3888       isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3889 
3890   int matches = indices.length();
3891   if (matches == 0) return *subject;
3892 
3893   // Detect integer overflow.
3894   int64_t result_len_64 =
3895       (static_cast<int64_t>(replacement_len) -
3896        static_cast<int64_t>(pattern_len)) *
3897       static_cast<int64_t>(matches) +
3898       static_cast<int64_t>(subject_len);
3899   if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11);
3900   int result_len = static_cast<int>(result_len_64);
3901 
3902   int subject_pos = 0;
3903   int result_pos = 0;
3904 
3905   Handle<ResultSeqString> result;
3906   if (ResultSeqString::kHasAsciiEncoding) {
3907     result = Handle<ResultSeqString>::cast(
3908         isolate->factory()->NewRawOneByteString(result_len));
3909   } else {
3910     result = Handle<ResultSeqString>::cast(
3911         isolate->factory()->NewRawTwoByteString(result_len));
3912   }
3913 
3914   for (int i = 0; i < matches; i++) {
3915     // Copy non-matched subject content.
3916     if (subject_pos < indices.at(i)) {
3917       String::WriteToFlat(*subject,
3918                           result->GetChars() + result_pos,
3919                           subject_pos,
3920                           indices.at(i));
3921       result_pos += indices.at(i) - subject_pos;
3922     }
3923 
3924     // Replace match.
3925     if (replacement_len > 0) {
3926       String::WriteToFlat(*replacement,
3927                           result->GetChars() + result_pos,
3928                           0,
3929                           replacement_len);
3930       result_pos += replacement_len;
3931     }
3932 
3933     subject_pos = indices.at(i) + pattern_len;
3934   }
3935   // Add remaining subject content at the end.
3936   if (subject_pos < subject_len) {
3937     String::WriteToFlat(*subject,
3938                         result->GetChars() + result_pos,
3939                         subject_pos,
3940                         subject_len);
3941   }
3942 
3943   int32_t match_indices[] = { indices.at(matches - 1),
3944                               indices.at(matches - 1) + pattern_len };
3945   RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
3946 
3947   return *result;
3948 }
3949 
3950 
StringReplaceGlobalRegExpWithString(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<String> replacement,Handle<JSArray> last_match_info)3951 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
3952     Isolate* isolate,
3953     Handle<String> subject,
3954     Handle<JSRegExp> regexp,
3955     Handle<String> replacement,
3956     Handle<JSArray> last_match_info) {
3957   ASSERT(subject->IsFlat());
3958   ASSERT(replacement->IsFlat());
3959 
3960   int capture_count = regexp->CaptureCount();
3961   int subject_length = subject->length();
3962 
3963   // CompiledReplacement uses zone allocation.
3964   ZoneScope zone_scope(isolate->runtime_zone());
3965   CompiledReplacement compiled_replacement(zone_scope.zone());
3966   bool simple_replace = compiled_replacement.Compile(replacement,
3967                                                      capture_count,
3968                                                      subject_length);
3969 
3970   // Shortcut for simple non-regexp global replacements
3971   if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
3972     if (subject->HasOnlyOneByteChars() &&
3973         replacement->HasOnlyOneByteChars()) {
3974       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
3975           isolate, subject, regexp, replacement, last_match_info);
3976     } else {
3977       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
3978           isolate, subject, regexp, replacement, last_match_info);
3979     }
3980   }
3981 
3982   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3983   if (global_cache.HasException()) return Failure::Exception();
3984 
3985   int32_t* current_match = global_cache.FetchNext();
3986   if (current_match == NULL) {
3987     if (global_cache.HasException()) return Failure::Exception();
3988     return *subject;
3989   }
3990 
3991   // Guessing the number of parts that the final result string is built
3992   // from. Global regexps can match any number of times, so we guess
3993   // conservatively.
3994   int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
3995   ReplacementStringBuilder builder(isolate->heap(),
3996                                    subject,
3997                                    expected_parts);
3998 
3999   // Number of parts added by compiled replacement plus preceeding
4000   // string and possibly suffix after last match.  It is possible for
4001   // all components to use two elements when encoded as two smis.
4002   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
4003 
4004   int prev = 0;
4005 
4006   do {
4007     builder.EnsureCapacity(parts_added_per_loop);
4008 
4009     int start = current_match[0];
4010     int end = current_match[1];
4011 
4012     if (prev < start) {
4013       builder.AddSubjectSlice(prev, start);
4014     }
4015 
4016     if (simple_replace) {
4017       builder.AddString(replacement);
4018     } else {
4019       compiled_replacement.Apply(&builder,
4020                                  start,
4021                                  end,
4022                                  current_match);
4023     }
4024     prev = end;
4025 
4026     current_match = global_cache.FetchNext();
4027   } while (current_match != NULL);
4028 
4029   if (global_cache.HasException()) return Failure::Exception();
4030 
4031   if (prev < subject_length) {
4032     builder.EnsureCapacity(2);
4033     builder.AddSubjectSlice(prev, subject_length);
4034   }
4035 
4036   RegExpImpl::SetLastMatchInfo(last_match_info,
4037                                subject,
4038                                capture_count,
4039                                global_cache.LastSuccessfulMatch());
4040 
4041   return *(builder.ToString());
4042 }
4043 
4044 
4045 template <typename ResultSeqString>
StringReplaceGlobalRegExpWithEmptyString(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_info)4046 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
4047     Isolate* isolate,
4048     Handle<String> subject,
4049     Handle<JSRegExp> regexp,
4050     Handle<JSArray> last_match_info) {
4051   ASSERT(subject->IsFlat());
4052 
4053   // Shortcut for simple non-regexp global replacements
4054   if (regexp->TypeTag() == JSRegExp::ATOM) {
4055     Handle<String> empty_string = isolate->factory()->empty_string();
4056     if (subject->IsOneByteRepresentation()) {
4057       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4058           isolate, subject, regexp, empty_string, last_match_info);
4059     } else {
4060       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4061           isolate, subject, regexp, empty_string, last_match_info);
4062     }
4063   }
4064 
4065   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4066   if (global_cache.HasException()) return Failure::Exception();
4067 
4068   int32_t* current_match = global_cache.FetchNext();
4069   if (current_match == NULL) {
4070     if (global_cache.HasException()) return Failure::Exception();
4071     return *subject;
4072   }
4073 
4074   int start = current_match[0];
4075   int end = current_match[1];
4076   int capture_count = regexp->CaptureCount();
4077   int subject_length = subject->length();
4078 
4079   int new_length = subject_length - (end - start);
4080   if (new_length == 0) return isolate->heap()->empty_string();
4081 
4082   Handle<ResultSeqString> answer;
4083   if (ResultSeqString::kHasAsciiEncoding) {
4084     answer = Handle<ResultSeqString>::cast(
4085         isolate->factory()->NewRawOneByteString(new_length));
4086   } else {
4087     answer = Handle<ResultSeqString>::cast(
4088         isolate->factory()->NewRawTwoByteString(new_length));
4089   }
4090 
4091   int prev = 0;
4092   int position = 0;
4093 
4094   do {
4095     start = current_match[0];
4096     end = current_match[1];
4097     if (prev < start) {
4098       // Add substring subject[prev;start] to answer string.
4099       String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
4100       position += start - prev;
4101     }
4102     prev = end;
4103 
4104     current_match = global_cache.FetchNext();
4105   } while (current_match != NULL);
4106 
4107   if (global_cache.HasException()) return Failure::Exception();
4108 
4109   RegExpImpl::SetLastMatchInfo(last_match_info,
4110                                subject,
4111                                capture_count,
4112                                global_cache.LastSuccessfulMatch());
4113 
4114   if (prev < subject_length) {
4115     // Add substring subject[prev;length] to answer string.
4116     String::WriteToFlat(
4117         *subject, answer->GetChars() + position, prev, subject_length);
4118     position += subject_length - prev;
4119   }
4120 
4121   if (position == 0) return isolate->heap()->empty_string();
4122 
4123   // Shorten string and fill
4124   int string_size = ResultSeqString::SizeFor(position);
4125   int allocated_string_size = ResultSeqString::SizeFor(new_length);
4126   int delta = allocated_string_size - string_size;
4127 
4128   answer->set_length(position);
4129   if (delta == 0) return *answer;
4130 
4131   Address end_of_string = answer->address() + string_size;
4132   isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
4133   if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
4134     MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
4135   }
4136 
4137   return *answer;
4138 }
4139 
4140 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringReplaceGlobalRegExpWithString)4141 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
4142   HandleScope scope(isolate);
4143   ASSERT(args.length() == 4);
4144 
4145   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4146   CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4147   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4148   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4149 
4150   ASSERT(regexp->GetFlags().is_global());
4151 
4152   if (!subject->IsFlat()) subject = FlattenGetString(subject);
4153 
4154   if (replacement->length() == 0) {
4155     if (subject->HasOnlyOneByteChars()) {
4156       return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4157           isolate, subject, regexp, last_match_info);
4158     } else {
4159       return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4160           isolate, subject, regexp, last_match_info);
4161     }
4162   }
4163 
4164   if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
4165 
4166   return StringReplaceGlobalRegExpWithString(
4167       isolate, subject, regexp, replacement, last_match_info);
4168 }
4169 
4170 
StringReplaceOneCharWithString(Isolate * isolate,Handle<String> subject,Handle<String> search,Handle<String> replace,bool * found,int recursion_limit)4171 Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
4172                                               Handle<String> subject,
4173                                               Handle<String> search,
4174                                               Handle<String> replace,
4175                                               bool* found,
4176                                               int recursion_limit) {
4177   if (recursion_limit == 0) return Handle<String>::null();
4178   if (subject->IsConsString()) {
4179     ConsString* cons = ConsString::cast(*subject);
4180     Handle<String> first = Handle<String>(cons->first());
4181     Handle<String> second = Handle<String>(cons->second());
4182     Handle<String> new_first =
4183         StringReplaceOneCharWithString(isolate,
4184                                        first,
4185                                        search,
4186                                        replace,
4187                                        found,
4188                                        recursion_limit - 1);
4189     if (*found) return isolate->factory()->NewConsString(new_first, second);
4190     if (new_first.is_null()) return new_first;
4191 
4192     Handle<String> new_second =
4193         StringReplaceOneCharWithString(isolate,
4194                                        second,
4195                                        search,
4196                                        replace,
4197                                        found,
4198                                        recursion_limit - 1);
4199     if (*found) return isolate->factory()->NewConsString(first, new_second);
4200     if (new_second.is_null()) return new_second;
4201 
4202     return subject;
4203   } else {
4204     int index = Runtime::StringMatch(isolate, subject, search, 0);
4205     if (index == -1) return subject;
4206     *found = true;
4207     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4208     Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
4209     Handle<String> second =
4210         isolate->factory()->NewSubString(subject, index + 1, subject->length());
4211     return isolate->factory()->NewConsString(cons1, second);
4212   }
4213 }
4214 
4215 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringReplaceOneCharWithString)4216 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
4217   HandleScope scope(isolate);
4218   ASSERT(args.length() == 3);
4219   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4220   CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4221   CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4222 
4223   // If the cons string tree is too deep, we simply abort the recursion and
4224   // retry with a flattened subject string.
4225   const int kRecursionLimit = 0x1000;
4226   bool found = false;
4227   Handle<String> result = StringReplaceOneCharWithString(isolate,
4228                                                          subject,
4229                                                          search,
4230                                                          replace,
4231                                                          &found,
4232                                                          kRecursionLimit);
4233   if (!result.is_null()) return *result;
4234   return *StringReplaceOneCharWithString(isolate,
4235                                          FlattenGetString(subject),
4236                                          search,
4237                                          replace,
4238                                          &found,
4239                                          kRecursionLimit);
4240 }
4241 
4242 
4243 // Perform string match of pattern on subject, starting at start index.
4244 // Caller must ensure that 0 <= start_index <= sub->length(),
4245 // and should check that pat->length() + start_index <= sub->length().
StringMatch(Isolate * isolate,Handle<String> sub,Handle<String> pat,int start_index)4246 int Runtime::StringMatch(Isolate* isolate,
4247                          Handle<String> sub,
4248                          Handle<String> pat,
4249                          int start_index) {
4250   ASSERT(0 <= start_index);
4251   ASSERT(start_index <= sub->length());
4252 
4253   int pattern_length = pat->length();
4254   if (pattern_length == 0) return start_index;
4255 
4256   int subject_length = sub->length();
4257   if (start_index + pattern_length > subject_length) return -1;
4258 
4259   if (!sub->IsFlat()) FlattenString(sub);
4260   if (!pat->IsFlat()) FlattenString(pat);
4261 
4262   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4263   // Extract flattened substrings of cons strings before determining asciiness.
4264   String::FlatContent seq_sub = sub->GetFlatContent();
4265   String::FlatContent seq_pat = pat->GetFlatContent();
4266 
4267   // dispatch on type of strings
4268   if (seq_pat.IsAscii()) {
4269     Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4270     if (seq_sub.IsAscii()) {
4271       return SearchString(isolate,
4272                           seq_sub.ToOneByteVector(),
4273                           pat_vector,
4274                           start_index);
4275     }
4276     return SearchString(isolate,
4277                         seq_sub.ToUC16Vector(),
4278                         pat_vector,
4279                         start_index);
4280   }
4281   Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4282   if (seq_sub.IsAscii()) {
4283     return SearchString(isolate,
4284                         seq_sub.ToOneByteVector(),
4285                         pat_vector,
4286                         start_index);
4287   }
4288   return SearchString(isolate,
4289                       seq_sub.ToUC16Vector(),
4290                       pat_vector,
4291                       start_index);
4292 }
4293 
4294 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringIndexOf)4295 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
4296   HandleScope scope(isolate);
4297   ASSERT(args.length() == 3);
4298 
4299   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4300   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4301 
4302   Object* index = args[2];
4303   uint32_t start_index;
4304   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4305 
4306   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4307   int position =
4308       Runtime::StringMatch(isolate, sub, pat, start_index);
4309   return Smi::FromInt(position);
4310 }
4311 
4312 
4313 template <typename schar, typename pchar>
StringMatchBackwards(Vector<const schar> subject,Vector<const pchar> pattern,int idx)4314 static int StringMatchBackwards(Vector<const schar> subject,
4315                                 Vector<const pchar> pattern,
4316                                 int idx) {
4317   int pattern_length = pattern.length();
4318   ASSERT(pattern_length >= 1);
4319   ASSERT(idx + pattern_length <= subject.length());
4320 
4321   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4322     for (int i = 0; i < pattern_length; i++) {
4323       uc16 c = pattern[i];
4324       if (c > String::kMaxOneByteCharCode) {
4325         return -1;
4326       }
4327     }
4328   }
4329 
4330   pchar pattern_first_char = pattern[0];
4331   for (int i = idx; i >= 0; i--) {
4332     if (subject[i] != pattern_first_char) continue;
4333     int j = 1;
4334     while (j < pattern_length) {
4335       if (pattern[j] != subject[i+j]) {
4336         break;
4337       }
4338       j++;
4339     }
4340     if (j == pattern_length) {
4341       return i;
4342     }
4343   }
4344   return -1;
4345 }
4346 
4347 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringLastIndexOf)4348 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
4349   HandleScope scope(isolate);
4350   ASSERT(args.length() == 3);
4351 
4352   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4353   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4354 
4355   Object* index = args[2];
4356   uint32_t start_index;
4357   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4358 
4359   uint32_t pat_length = pat->length();
4360   uint32_t sub_length = sub->length();
4361 
4362   if (start_index + pat_length > sub_length) {
4363     start_index = sub_length - pat_length;
4364   }
4365 
4366   if (pat_length == 0) {
4367     return Smi::FromInt(start_index);
4368   }
4369 
4370   if (!sub->IsFlat()) FlattenString(sub);
4371   if (!pat->IsFlat()) FlattenString(pat);
4372 
4373   int position = -1;
4374   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4375 
4376   String::FlatContent sub_content = sub->GetFlatContent();
4377   String::FlatContent pat_content = pat->GetFlatContent();
4378 
4379   if (pat_content.IsAscii()) {
4380     Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4381     if (sub_content.IsAscii()) {
4382       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4383                                       pat_vector,
4384                                       start_index);
4385     } else {
4386       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4387                                       pat_vector,
4388                                       start_index);
4389     }
4390   } else {
4391     Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4392     if (sub_content.IsAscii()) {
4393       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4394                                       pat_vector,
4395                                       start_index);
4396     } else {
4397       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4398                                       pat_vector,
4399                                       start_index);
4400     }
4401   }
4402 
4403   return Smi::FromInt(position);
4404 }
4405 
4406 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringLocaleCompare)4407 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
4408   SealHandleScope shs(isolate);
4409   ASSERT(args.length() == 2);
4410 
4411   CONVERT_ARG_CHECKED(String, str1, 0);
4412   CONVERT_ARG_CHECKED(String, str2, 1);
4413 
4414   if (str1 == str2) return Smi::FromInt(0);  // Equal.
4415   int str1_length = str1->length();
4416   int str2_length = str2->length();
4417 
4418   // Decide trivial cases without flattening.
4419   if (str1_length == 0) {
4420     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
4421     return Smi::FromInt(-str2_length);
4422   } else {
4423     if (str2_length == 0) return Smi::FromInt(str1_length);
4424   }
4425 
4426   int end = str1_length < str2_length ? str1_length : str2_length;
4427 
4428   // No need to flatten if we are going to find the answer on the first
4429   // character.  At this point we know there is at least one character
4430   // in each string, due to the trivial case handling above.
4431   int d = str1->Get(0) - str2->Get(0);
4432   if (d != 0) return Smi::FromInt(d);
4433 
4434   str1->TryFlatten();
4435   str2->TryFlatten();
4436 
4437   ConsStringIteratorOp* op1 =
4438       isolate->runtime_state()->string_locale_compare_it1();
4439   ConsStringIteratorOp* op2 =
4440       isolate->runtime_state()->string_locale_compare_it2();
4441   // TODO(dcarney) Can do array compares here more efficiently.
4442   StringCharacterStream stream1(str1, op1);
4443   StringCharacterStream stream2(str2, op2);
4444 
4445   for (int i = 0; i < end; i++) {
4446     uint16_t char1 = stream1.GetNext();
4447     uint16_t char2 = stream2.GetNext();
4448     if (char1 != char2) return Smi::FromInt(char1 - char2);
4449   }
4450 
4451   return Smi::FromInt(str1_length - str2_length);
4452 }
4453 
4454 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SubString)4455 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
4456   SealHandleScope shs(isolate);
4457   ASSERT(args.length() == 3);
4458 
4459   CONVERT_ARG_CHECKED(String, value, 0);
4460   int start, end;
4461   // We have a fast integer-only case here to avoid a conversion to double in
4462   // the common case where from and to are Smis.
4463   if (args[1]->IsSmi() && args[2]->IsSmi()) {
4464     CONVERT_SMI_ARG_CHECKED(from_number, 1);
4465     CONVERT_SMI_ARG_CHECKED(to_number, 2);
4466     start = from_number;
4467     end = to_number;
4468   } else {
4469     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4470     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4471     start = FastD2IChecked(from_number);
4472     end = FastD2IChecked(to_number);
4473   }
4474   RUNTIME_ASSERT(end >= start);
4475   RUNTIME_ASSERT(start >= 0);
4476   RUNTIME_ASSERT(end <= value->length());
4477   isolate->counters()->sub_string_runtime()->Increment();
4478   return value->SubString(start, end);
4479 }
4480 
4481 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringMatch)4482 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
4483   HandleScope handles(isolate);
4484   ASSERT_EQ(3, args.length());
4485 
4486   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4487   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4488   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4489 
4490   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4491   if (global_cache.HasException()) return Failure::Exception();
4492 
4493   int capture_count = regexp->CaptureCount();
4494 
4495   ZoneScope zone_scope(isolate->runtime_zone());
4496   ZoneList<int> offsets(8, zone_scope.zone());
4497 
4498   while (true) {
4499     int32_t* match = global_cache.FetchNext();
4500     if (match == NULL) break;
4501     offsets.Add(match[0], zone_scope.zone());  // start
4502     offsets.Add(match[1], zone_scope.zone());  // end
4503   }
4504 
4505   if (global_cache.HasException()) return Failure::Exception();
4506 
4507   if (offsets.length() == 0) {
4508     // Not a single match.
4509     return isolate->heap()->null_value();
4510   }
4511 
4512   RegExpImpl::SetLastMatchInfo(regexp_info,
4513                                subject,
4514                                capture_count,
4515                                global_cache.LastSuccessfulMatch());
4516 
4517   int matches = offsets.length() / 2;
4518   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4519   Handle<String> substring =
4520       isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4521   elements->set(0, *substring);
4522   for (int i = 1; i < matches; i++) {
4523     HandleScope temp_scope(isolate);
4524     int from = offsets.at(i * 2);
4525     int to = offsets.at(i * 2 + 1);
4526     Handle<String> substring =
4527         isolate->factory()->NewProperSubString(subject, from, to);
4528     elements->set(i, *substring);
4529   }
4530   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4531   result->set_length(Smi::FromInt(matches));
4532   return *result;
4533 }
4534 
4535 
4536 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4537 // separate last match info.  See comment on that function.
4538 template<bool has_capture>
SearchRegExpMultiple(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_array,Handle<JSArray> result_array)4539 static MaybeObject* SearchRegExpMultiple(
4540     Isolate* isolate,
4541     Handle<String> subject,
4542     Handle<JSRegExp> regexp,
4543     Handle<JSArray> last_match_array,
4544     Handle<JSArray> result_array) {
4545   ASSERT(subject->IsFlat());
4546   ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
4547 
4548   int capture_count = regexp->CaptureCount();
4549   int subject_length = subject->length();
4550 
4551   static const int kMinLengthToCache = 0x1000;
4552 
4553   if (subject_length > kMinLengthToCache) {
4554     Handle<Object> cached_answer(RegExpResultsCache::Lookup(
4555         isolate->heap(),
4556         *subject,
4557         regexp->data(),
4558         RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
4559     if (*cached_answer != Smi::FromInt(0)) {
4560       Handle<FixedArray> cached_fixed_array =
4561           Handle<FixedArray>(FixedArray::cast(*cached_answer));
4562       // The cache FixedArray is a COW-array and can therefore be reused.
4563       isolate->factory()->SetContent(result_array, cached_fixed_array);
4564       // The actual length of the result array is stored in the last element of
4565       // the backing store (the backing FixedArray may have a larger capacity).
4566       Object* cached_fixed_array_last_element =
4567           cached_fixed_array->get(cached_fixed_array->length() - 1);
4568       Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4569       result_array->set_length(js_array_length);
4570       RegExpImpl::SetLastMatchInfo(
4571           last_match_array, subject, capture_count, NULL);
4572       return *result_array;
4573     }
4574   }
4575 
4576   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4577   if (global_cache.HasException()) return Failure::Exception();
4578 
4579   Handle<FixedArray> result_elements;
4580   if (result_array->HasFastObjectElements()) {
4581     result_elements =
4582         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4583   }
4584   if (result_elements.is_null() || result_elements->length() < 16) {
4585     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4586   }
4587 
4588   FixedArrayBuilder builder(result_elements);
4589 
4590   // Position to search from.
4591   int match_start = -1;
4592   int match_end = 0;
4593   bool first = true;
4594 
4595   // Two smis before and after the match, for very long strings.
4596   static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4597 
4598   while (true) {
4599     int32_t* current_match = global_cache.FetchNext();
4600     if (current_match == NULL) break;
4601     match_start = current_match[0];
4602     builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4603     if (match_end < match_start) {
4604       ReplacementStringBuilder::AddSubjectSlice(&builder,
4605                                                 match_end,
4606                                                 match_start);
4607     }
4608     match_end = current_match[1];
4609     {
4610       // Avoid accumulating new handles inside loop.
4611       HandleScope temp_scope(isolate);
4612       Handle<String> match;
4613       if (!first) {
4614         match = isolate->factory()->NewProperSubString(subject,
4615                                                        match_start,
4616                                                        match_end);
4617       } else {
4618         match = isolate->factory()->NewSubString(subject,
4619                                                  match_start,
4620                                                  match_end);
4621         first = false;
4622       }
4623 
4624       if (has_capture) {
4625         // Arguments array to replace function is match, captures, index and
4626         // subject, i.e., 3 + capture count in total.
4627         Handle<FixedArray> elements =
4628             isolate->factory()->NewFixedArray(3 + capture_count);
4629 
4630         elements->set(0, *match);
4631         for (int i = 1; i <= capture_count; i++) {
4632           int start = current_match[i * 2];
4633           if (start >= 0) {
4634             int end = current_match[i * 2 + 1];
4635             ASSERT(start <= end);
4636             Handle<String> substring =
4637                 isolate->factory()->NewSubString(subject, start, end);
4638             elements->set(i, *substring);
4639           } else {
4640             ASSERT(current_match[i * 2 + 1] < 0);
4641             elements->set(i, isolate->heap()->undefined_value());
4642           }
4643         }
4644         elements->set(capture_count + 1, Smi::FromInt(match_start));
4645         elements->set(capture_count + 2, *subject);
4646         builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4647       } else {
4648         builder.Add(*match);
4649       }
4650     }
4651   }
4652 
4653   if (global_cache.HasException()) return Failure::Exception();
4654 
4655   if (match_start >= 0) {
4656     // Finished matching, with at least one match.
4657     if (match_end < subject_length) {
4658       ReplacementStringBuilder::AddSubjectSlice(&builder,
4659                                                 match_end,
4660                                                 subject_length);
4661     }
4662 
4663     RegExpImpl::SetLastMatchInfo(
4664         last_match_array, subject, capture_count, NULL);
4665 
4666     if (subject_length > kMinLengthToCache) {
4667       // Store the length of the result array into the last element of the
4668       // backing FixedArray.
4669       builder.EnsureCapacity(1);
4670       Handle<FixedArray> fixed_array = builder.array();
4671       fixed_array->set(fixed_array->length() - 1,
4672                        Smi::FromInt(builder.length()));
4673       // Cache the result and turn the FixedArray into a COW array.
4674       RegExpResultsCache::Enter(isolate->heap(),
4675                                 *subject,
4676                                 regexp->data(),
4677                                 *fixed_array,
4678                                 RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
4679     }
4680     return *builder.ToJSArray(result_array);
4681   } else {
4682     return isolate->heap()->null_value();  // No matches at all.
4683   }
4684 }
4685 
4686 
4687 // This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4688 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4689 // set any other last match array info.
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpExecMultiple)4690 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4691   HandleScope handles(isolate);
4692   ASSERT(args.length() == 4);
4693 
4694   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4695   if (!subject->IsFlat()) FlattenString(subject);
4696   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4697   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4698   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4699 
4700   ASSERT(regexp->GetFlags().is_global());
4701 
4702   if (regexp->CaptureCount() == 0) {
4703     return SearchRegExpMultiple<false>(
4704         isolate, subject, regexp, last_match_info, result_array);
4705   } else {
4706     return SearchRegExpMultiple<true>(
4707         isolate, subject, regexp, last_match_info, result_array);
4708   }
4709 }
4710 
4711 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToRadixString)4712 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4713   SealHandleScope shs(isolate);
4714   ASSERT(args.length() == 2);
4715   CONVERT_SMI_ARG_CHECKED(radix, 1);
4716   RUNTIME_ASSERT(2 <= radix && radix <= 36);
4717 
4718   // Fast case where the result is a one character string.
4719   if (args[0]->IsSmi()) {
4720     int value = args.smi_at(0);
4721     if (value >= 0 && value < radix) {
4722       // Character array used for conversion.
4723       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4724       return isolate->heap()->
4725           LookupSingleCharacterStringFromCode(kCharTable[value]);
4726     }
4727   }
4728 
4729   // Slow case.
4730   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4731   if (std::isnan(value)) {
4732     return *isolate->factory()->nan_string();
4733   }
4734   if (std::isinf(value)) {
4735     if (value < 0) {
4736       return *isolate->factory()->minus_infinity_string();
4737     }
4738     return *isolate->factory()->infinity_string();
4739   }
4740   char* str = DoubleToRadixCString(value, radix);
4741   MaybeObject* result =
4742       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4743   DeleteArray(str);
4744   return result;
4745 }
4746 
4747 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToFixed)4748 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4749   SealHandleScope shs(isolate);
4750   ASSERT(args.length() == 2);
4751 
4752   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4753   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4754   int f = FastD2IChecked(f_number);
4755   RUNTIME_ASSERT(f >= 0);
4756   char* str = DoubleToFixedCString(value, f);
4757   MaybeObject* res =
4758       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4759   DeleteArray(str);
4760   return res;
4761 }
4762 
4763 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToExponential)4764 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4765   SealHandleScope shs(isolate);
4766   ASSERT(args.length() == 2);
4767 
4768   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4769   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4770   int f = FastD2IChecked(f_number);
4771   RUNTIME_ASSERT(f >= -1 && f <= 20);
4772   char* str = DoubleToExponentialCString(value, f);
4773   MaybeObject* res =
4774       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4775   DeleteArray(str);
4776   return res;
4777 }
4778 
4779 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToPrecision)4780 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4781   SealHandleScope shs(isolate);
4782   ASSERT(args.length() == 2);
4783 
4784   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4785   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4786   int f = FastD2IChecked(f_number);
4787   RUNTIME_ASSERT(f >= 1 && f <= 21);
4788   char* str = DoubleToPrecisionCString(value, f);
4789   MaybeObject* res =
4790       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4791   DeleteArray(str);
4792   return res;
4793 }
4794 
4795 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsValidSmi)4796 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) {
4797   HandleScope shs(isolate);
4798   ASSERT(args.length() == 1);
4799 
4800   CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
4801   if (Smi::IsValid(number)) {
4802     return isolate->heap()->true_value();
4803   } else {
4804     return isolate->heap()->false_value();
4805   }
4806 }
4807 
4808 
4809 // Returns a single character string where first character equals
4810 // string->Get(index).
GetCharAt(Handle<String> string,uint32_t index)4811 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4812   if (index < static_cast<uint32_t>(string->length())) {
4813     string->TryFlatten();
4814     return LookupSingleCharacterStringFromCode(
4815         string->GetIsolate(),
4816         string->Get(index));
4817   }
4818   return Execution::CharAt(string, index);
4819 }
4820 
4821 
GetElementOrCharAtOrFail(Isolate * isolate,Handle<Object> object,uint32_t index)4822 MaybeObject* Runtime::GetElementOrCharAtOrFail(Isolate* isolate,
4823                                                Handle<Object> object,
4824                                                uint32_t index) {
4825   CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4826       GetElementOrCharAt(isolate, object, index));
4827 }
4828 
4829 
GetElementOrCharAt(Isolate * isolate,Handle<Object> object,uint32_t index)4830 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4831                                          Handle<Object> object,
4832                                          uint32_t index) {
4833   // Handle [] indexing on Strings
4834   if (object->IsString()) {
4835     Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4836     if (!result->IsUndefined()) return *result;
4837   }
4838 
4839   // Handle [] indexing on String objects
4840   if (object->IsStringObjectWithCharacterAt(index)) {
4841     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4842     Handle<Object> result =
4843         GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4844     if (!result->IsUndefined()) return *result;
4845   }
4846 
4847   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4848     return object->GetPrototype(isolate)->GetElement(isolate, index);
4849   }
4850 
4851   return object->GetElement(isolate, index);
4852 }
4853 
4854 
ToName(Isolate * isolate,Handle<Object> key)4855 static Handle<Name> ToName(Isolate* isolate, Handle<Object> key) {
4856   if (key->IsName()) {
4857     return Handle<Name>::cast(key);
4858   } else {
4859     bool has_pending_exception = false;
4860     Handle<Object> converted =
4861         Execution::ToString(isolate, key, &has_pending_exception);
4862     if (has_pending_exception) return Handle<Name>();
4863     return Handle<Name>::cast(converted);
4864   }
4865 }
4866 
4867 
HasObjectProperty(Isolate * isolate,Handle<JSReceiver> object,Handle<Object> key)4868 MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
4869                                         Handle<JSReceiver> object,
4870                                         Handle<Object> key) {
4871   HandleScope scope(isolate);
4872 
4873   // Check if the given key is an array index.
4874   uint32_t index;
4875   if (key->ToArrayIndex(&index)) {
4876     return isolate->heap()->ToBoolean(JSReceiver::HasElement(object, index));
4877   }
4878 
4879   // Convert the key to a name - possibly by calling back into JavaScript.
4880   Handle<Name> name = ToName(isolate, key);
4881   RETURN_IF_EMPTY_HANDLE(isolate, name);
4882 
4883   return isolate->heap()->ToBoolean(JSReceiver::HasProperty(object, name));
4884 }
4885 
GetObjectPropertyOrFail(Isolate * isolate,Handle<Object> object,Handle<Object> key)4886 MaybeObject* Runtime::GetObjectPropertyOrFail(
4887     Isolate* isolate,
4888     Handle<Object> object,
4889     Handle<Object> key) {
4890   CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4891       GetObjectProperty(isolate, object, key));
4892 }
4893 
GetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key)4894 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4895                                         Handle<Object> object,
4896                                         Handle<Object> key) {
4897   HandleScope scope(isolate);
4898 
4899   if (object->IsUndefined() || object->IsNull()) {
4900     Handle<Object> args[2] = { key, object };
4901     Handle<Object> error =
4902         isolate->factory()->NewTypeError("non_object_property_load",
4903                                          HandleVector(args, 2));
4904     return isolate->Throw(*error);
4905   }
4906 
4907   // Check if the given key is an array index.
4908   uint32_t index;
4909   if (key->ToArrayIndex(&index)) {
4910     return GetElementOrCharAt(isolate, object, index);
4911   }
4912 
4913   // Convert the key to a name - possibly by calling back into JavaScript.
4914   Handle<Name> name = ToName(isolate, key);
4915   RETURN_IF_EMPTY_HANDLE(isolate, name);
4916 
4917   // Check if the name is trivially convertible to an index and get
4918   // the element if so.
4919   if (name->AsArrayIndex(&index)) {
4920     return GetElementOrCharAt(isolate, object, index);
4921   } else {
4922     return object->GetProperty(*name);
4923   }
4924 }
4925 
4926 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetProperty)4927 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4928   SealHandleScope shs(isolate);
4929   ASSERT(args.length() == 2);
4930 
4931   Handle<Object> object = args.at<Object>(0);
4932   Handle<Object> key = args.at<Object>(1);
4933 
4934   return Runtime::GetObjectProperty(isolate, object, key);
4935 }
4936 
4937 
4938 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(MaybeObject *,Runtime_KeyedGetProperty)4939 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4940   SealHandleScope shs(isolate);
4941   ASSERT(args.length() == 2);
4942 
4943   // Fast cases for getting named properties of the receiver JSObject
4944   // itself.
4945   //
4946   // The global proxy objects has to be excluded since LocalLookup on
4947   // the global proxy object can return a valid result even though the
4948   // global proxy object never has properties.  This is the case
4949   // because the global proxy object forwards everything to its hidden
4950   // prototype including local lookups.
4951   //
4952   // Additionally, we need to make sure that we do not cache results
4953   // for objects that require access checks.
4954   if (args[0]->IsJSObject()) {
4955     if (!args[0]->IsJSGlobalProxy() &&
4956         !args[0]->IsAccessCheckNeeded() &&
4957         args[1]->IsName()) {
4958       JSObject* receiver = JSObject::cast(args[0]);
4959       Name* key = Name::cast(args[1]);
4960       if (receiver->HasFastProperties()) {
4961         // Attempt to use lookup cache.
4962         Map* receiver_map = receiver->map();
4963         KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4964         int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4965         if (offset != -1) {
4966           // Doubles are not cached, so raw read the value.
4967           Object* value = receiver->RawFastPropertyAt(offset);
4968           return value->IsTheHole()
4969               ? isolate->heap()->undefined_value()
4970               : value;
4971         }
4972         // Lookup cache miss.  Perform lookup and update the cache if
4973         // appropriate.
4974         LookupResult result(isolate);
4975         receiver->LocalLookup(key, &result);
4976         if (result.IsField()) {
4977           int offset = result.GetFieldIndex().field_index();
4978           // Do not track double fields in the keyed lookup cache. Reading
4979           // double values requires boxing.
4980           if (!FLAG_track_double_fields ||
4981               !result.representation().IsDouble()) {
4982             keyed_lookup_cache->Update(receiver_map, key, offset);
4983           }
4984           return receiver->FastPropertyAt(result.representation(), offset);
4985         }
4986       } else {
4987         // Attempt dictionary lookup.
4988         NameDictionary* dictionary = receiver->property_dictionary();
4989         int entry = dictionary->FindEntry(key);
4990         if ((entry != NameDictionary::kNotFound) &&
4991             (dictionary->DetailsAt(entry).type() == NORMAL)) {
4992           Object* value = dictionary->ValueAt(entry);
4993           if (!receiver->IsGlobalObject()) return value;
4994           value = PropertyCell::cast(value)->value();
4995           if (!value->IsTheHole()) return value;
4996           // If value is the hole do the general lookup.
4997         }
4998       }
4999     } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
5000       // JSObject without a name key. If the key is a Smi, check for a
5001       // definite out-of-bounds access to elements, which is a strong indicator
5002       // that subsequent accesses will also call the runtime. Proactively
5003       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
5004       // doubles for those future calls in the case that the elements would
5005       // become FAST_DOUBLE_ELEMENTS.
5006       Handle<JSObject> js_object(args.at<JSObject>(0));
5007       ElementsKind elements_kind = js_object->GetElementsKind();
5008       if (IsFastDoubleElementsKind(elements_kind)) {
5009         FixedArrayBase* elements = js_object->elements();
5010         if (args.at<Smi>(1)->value() >= elements->length()) {
5011           if (IsFastHoleyElementsKind(elements_kind)) {
5012             elements_kind = FAST_HOLEY_ELEMENTS;
5013           } else {
5014             elements_kind = FAST_ELEMENTS;
5015           }
5016           MaybeObject* maybe_object = TransitionElements(js_object,
5017                                                          elements_kind,
5018                                                          isolate);
5019           if (maybe_object->IsFailure()) return maybe_object;
5020         }
5021       } else {
5022         ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
5023                !IsFastElementsKind(elements_kind));
5024       }
5025     }
5026   } else if (args[0]->IsString() && args[1]->IsSmi()) {
5027     // Fast case for string indexing using [] with a smi index.
5028     HandleScope scope(isolate);
5029     Handle<String> str = args.at<String>(0);
5030     int index = args.smi_at(1);
5031     if (index >= 0 && index < str->length()) {
5032       Handle<Object> result = GetCharAt(str, index);
5033       return *result;
5034     }
5035   }
5036 
5037   // Fall back to GetObjectProperty.
5038   return Runtime::GetObjectProperty(isolate,
5039                                     args.at<Object>(0),
5040                                     args.at<Object>(1));
5041 }
5042 
5043 
IsValidAccessor(Handle<Object> obj)5044 static bool IsValidAccessor(Handle<Object> obj) {
5045   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
5046 }
5047 
5048 
5049 // Implements part of 8.12.9 DefineOwnProperty.
5050 // There are 3 cases that lead here:
5051 // Step 4b - define a new accessor property.
5052 // Steps 9c & 12 - replace an existing data property with an accessor property.
5053 // Step 12 - update an existing accessor property with an accessor or generic
5054 //           descriptor.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DefineOrRedefineAccessorProperty)5055 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
5056   HandleScope scope(isolate);
5057   ASSERT(args.length() == 5);
5058   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5059   RUNTIME_ASSERT(!obj->IsNull());
5060   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5061   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
5062   RUNTIME_ASSERT(IsValidAccessor(getter));
5063   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
5064   RUNTIME_ASSERT(IsValidAccessor(setter));
5065   CONVERT_SMI_ARG_CHECKED(unchecked, 4);
5066   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5067   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5068 
5069   bool fast = obj->HasFastProperties();
5070   JSObject::DefineAccessor(obj, name, getter, setter, attr);
5071   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5072   if (fast) JSObject::TransformToFastProperties(obj, 0);
5073   return isolate->heap()->undefined_value();
5074 }
5075 
5076 
5077 // Implements part of 8.12.9 DefineOwnProperty.
5078 // There are 3 cases that lead here:
5079 // Step 4a - define a new data property.
5080 // Steps 9b & 12 - replace an existing accessor property with a data property.
5081 // Step 12 - update an existing data property with a data or generic
5082 //           descriptor.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DefineOrRedefineDataProperty)5083 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
5084   HandleScope scope(isolate);
5085   ASSERT(args.length() == 4);
5086   CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
5087   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5088   CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
5089   CONVERT_SMI_ARG_CHECKED(unchecked, 3);
5090   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5091   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5092 
5093   LookupResult lookup(isolate);
5094   js_object->LocalLookupRealNamedProperty(*name, &lookup);
5095 
5096   // Special case for callback properties.
5097   if (lookup.IsPropertyCallbacks()) {
5098     Handle<Object> callback(lookup.GetCallbackObject(), isolate);
5099     // To be compatible with Safari we do not change the value on API objects
5100     // in Object.defineProperty(). Firefox disagrees here, and actually changes
5101     // the value.
5102     if (callback->IsAccessorInfo()) {
5103       return isolate->heap()->undefined_value();
5104     }
5105     // Avoid redefining foreign callback as data property, just use the stored
5106     // setter to update the value instead.
5107     // TODO(mstarzinger): So far this only works if property attributes don't
5108     // change, this should be fixed once we cleanup the underlying code.
5109     if (callback->IsForeign() && lookup.GetAttributes() == attr) {
5110       Handle<Object> result_object =
5111           JSObject::SetPropertyWithCallback(js_object,
5112                                             callback,
5113                                             name,
5114                                             obj_value,
5115                                             handle(lookup.holder()),
5116                                             kStrictMode);
5117       RETURN_IF_EMPTY_HANDLE(isolate, result_object);
5118       return *result_object;
5119     }
5120   }
5121 
5122   // Take special care when attributes are different and there is already
5123   // a property. For simplicity we normalize the property which enables us
5124   // to not worry about changing the instance_descriptor and creating a new
5125   // map. The current version of SetObjectProperty does not handle attributes
5126   // correctly in the case where a property is a field and is reset with
5127   // new attributes.
5128   if (lookup.IsFound() &&
5129       (attr != lookup.GetAttributes() || lookup.IsPropertyCallbacks())) {
5130     // New attributes - normalize to avoid writing to instance descriptor
5131     if (js_object->IsJSGlobalProxy()) {
5132       // Since the result is a property, the prototype will exist so
5133       // we don't have to check for null.
5134       js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5135     }
5136     JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
5137     // Use IgnoreAttributes version since a readonly property may be
5138     // overridden and SetProperty does not allow this.
5139     Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5140         js_object, name, obj_value, attr);
5141     RETURN_IF_EMPTY_HANDLE(isolate, result);
5142     return *result;
5143   }
5144 
5145   Handle<Object> result = Runtime::ForceSetObjectProperty(isolate, js_object,
5146                                                           name,
5147                                                           obj_value,
5148                                                           attr);
5149   RETURN_IF_EMPTY_HANDLE(isolate, result);
5150   return *result;
5151 }
5152 
5153 
5154 // Return property without being observable by accessors or interceptors.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetDataProperty)5155 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
5156   SealHandleScope shs(isolate);
5157   ASSERT(args.length() == 2);
5158   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5159   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5160   LookupResult lookup(isolate);
5161   object->LookupRealNamedProperty(*key, &lookup);
5162   if (!lookup.IsFound()) return isolate->heap()->undefined_value();
5163   switch (lookup.type()) {
5164     case NORMAL:
5165       return lookup.holder()->GetNormalizedProperty(&lookup);
5166     case FIELD:
5167       return lookup.holder()->FastPropertyAt(
5168           lookup.representation(),
5169           lookup.GetFieldIndex().field_index());
5170     case CONSTANT:
5171       return lookup.GetConstant();
5172     case CALLBACKS:
5173     case HANDLER:
5174     case INTERCEPTOR:
5175     case TRANSITION:
5176       return isolate->heap()->undefined_value();
5177     case NONEXISTENT:
5178       UNREACHABLE();
5179   }
5180   return isolate->heap()->undefined_value();
5181 }
5182 
5183 
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr,StrictModeFlag strict_mode)5184 Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
5185                                           Handle<Object> object,
5186                                           Handle<Object> key,
5187                                           Handle<Object> value,
5188                                           PropertyAttributes attr,
5189                                           StrictModeFlag strict_mode) {
5190   SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5191 
5192   if (object->IsUndefined() || object->IsNull()) {
5193     Handle<Object> args[2] = { key, object };
5194     Handle<Object> error =
5195         isolate->factory()->NewTypeError("non_object_property_store",
5196                                          HandleVector(args, 2));
5197     isolate->Throw(*error);
5198     return Handle<Object>();
5199   }
5200 
5201   if (object->IsJSProxy()) {
5202     bool has_pending_exception = false;
5203     Handle<Object> name_object = key->IsSymbol()
5204         ? key : Execution::ToString(isolate, key, &has_pending_exception);
5205     if (has_pending_exception) return Handle<Object>();  // exception
5206     Handle<Name> name = Handle<Name>::cast(name_object);
5207     return JSReceiver::SetProperty(Handle<JSProxy>::cast(object), name, value,
5208                                    attr,
5209                                    strict_mode);
5210   }
5211 
5212   // If the object isn't a JavaScript object, we ignore the store.
5213   if (!object->IsJSObject()) return value;
5214 
5215   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5216 
5217   // Check if the given key is an array index.
5218   uint32_t index;
5219   if (key->ToArrayIndex(&index)) {
5220     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5221     // of a string using [] notation.  We need to support this too in
5222     // JavaScript.
5223     // In the case of a String object we just need to redirect the assignment to
5224     // the underlying string if the index is in range.  Since the underlying
5225     // string does nothing with the assignment then we can ignore such
5226     // assignments.
5227     if (js_object->IsStringObjectWithCharacterAt(index)) {
5228       return value;
5229     }
5230 
5231     js_object->ValidateElements();
5232     if (js_object->HasExternalArrayElements()) {
5233       if (!value->IsNumber() && !value->IsUndefined()) {
5234         bool has_exception;
5235         Handle<Object> number =
5236             Execution::ToNumber(isolate, value, &has_exception);
5237         if (has_exception) return Handle<Object>();  // exception
5238         value = number;
5239       }
5240     }
5241     Handle<Object> result = JSObject::SetElement(js_object, index, value, attr,
5242                                                  strict_mode,
5243                                                  true,
5244                                                  set_mode);
5245     js_object->ValidateElements();
5246     return result.is_null() ? result : value;
5247   }
5248 
5249   if (key->IsName()) {
5250     Handle<Name> name = Handle<Name>::cast(key);
5251     if (name->AsArrayIndex(&index)) {
5252       if (js_object->HasExternalArrayElements()) {
5253         if (!value->IsNumber() && !value->IsUndefined()) {
5254           bool has_exception;
5255           Handle<Object> number =
5256               Execution::ToNumber(isolate, value, &has_exception);
5257           if (has_exception) return Handle<Object>();  // exception
5258           value = number;
5259         }
5260       }
5261       return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5262                                   true,
5263                                   set_mode);
5264     } else {
5265       if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5266       return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5267     }
5268   }
5269 
5270   // Call-back into JavaScript to convert the key to a string.
5271   bool has_pending_exception = false;
5272   Handle<Object> converted =
5273       Execution::ToString(isolate, key, &has_pending_exception);
5274   if (has_pending_exception) return Handle<Object>();  // exception
5275   Handle<String> name = Handle<String>::cast(converted);
5276 
5277   if (name->AsArrayIndex(&index)) {
5278     return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5279                                 true,
5280                                 set_mode);
5281   } else {
5282     return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5283   }
5284 }
5285 
5286 
ForceSetObjectProperty(Isolate * isolate,Handle<JSObject> js_object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr)5287 Handle<Object> Runtime::ForceSetObjectProperty(Isolate* isolate,
5288                                                Handle<JSObject> js_object,
5289                                                Handle<Object> key,
5290                                                Handle<Object> value,
5291                                                PropertyAttributes attr) {
5292   // Check if the given key is an array index.
5293   uint32_t index;
5294   if (key->ToArrayIndex(&index)) {
5295     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5296     // of a string using [] notation.  We need to support this too in
5297     // JavaScript.
5298     // In the case of a String object we just need to redirect the assignment to
5299     // the underlying string if the index is in range.  Since the underlying
5300     // string does nothing with the assignment then we can ignore such
5301     // assignments.
5302     if (js_object->IsStringObjectWithCharacterAt(index)) {
5303       return value;
5304     }
5305 
5306     return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
5307                                 false,
5308                                 DEFINE_PROPERTY);
5309   }
5310 
5311   if (key->IsName()) {
5312     Handle<Name> name = Handle<Name>::cast(key);
5313     if (name->AsArrayIndex(&index)) {
5314       return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
5315                                   false,
5316                                   DEFINE_PROPERTY);
5317     } else {
5318       if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5319       return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name,
5320                                                         value, attr);
5321     }
5322   }
5323 
5324   // Call-back into JavaScript to convert the key to a string.
5325   bool has_pending_exception = false;
5326   Handle<Object> converted =
5327       Execution::ToString(isolate, key, &has_pending_exception);
5328   if (has_pending_exception) return Handle<Object>();  // exception
5329   Handle<String> name = Handle<String>::cast(converted);
5330 
5331   if (name->AsArrayIndex(&index)) {
5332     return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
5333                                 false,
5334                                 DEFINE_PROPERTY);
5335   } else {
5336     return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name, value,
5337                                                       attr);
5338   }
5339 }
5340 
5341 
DeleteObjectProperty(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> key,JSReceiver::DeleteMode mode)5342 MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
5343                                            Handle<JSReceiver> receiver,
5344                                            Handle<Object> key,
5345                                            JSReceiver::DeleteMode mode) {
5346   HandleScope scope(isolate);
5347 
5348   // Check if the given key is an array index.
5349   uint32_t index;
5350   if (key->ToArrayIndex(&index)) {
5351     // In Firefox/SpiderMonkey, Safari and Opera you can access the
5352     // characters of a string using [] notation.  In the case of a
5353     // String object we just need to redirect the deletion to the
5354     // underlying string if the index is in range.  Since the
5355     // underlying string does nothing with the deletion, we can ignore
5356     // such deletions.
5357     if (receiver->IsStringObjectWithCharacterAt(index)) {
5358       return isolate->heap()->true_value();
5359     }
5360 
5361     Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
5362     RETURN_IF_EMPTY_HANDLE(isolate, result);
5363     return *result;
5364   }
5365 
5366   Handle<Name> name;
5367   if (key->IsName()) {
5368     name = Handle<Name>::cast(key);
5369   } else {
5370     // Call-back into JavaScript to convert the key to a string.
5371     bool has_pending_exception = false;
5372     Handle<Object> converted = Execution::ToString(
5373         isolate, key, &has_pending_exception);
5374     if (has_pending_exception) return Failure::Exception();
5375     name = Handle<String>::cast(converted);
5376   }
5377 
5378   if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5379   Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
5380   RETURN_IF_EMPTY_HANDLE(isolate, result);
5381   return *result;
5382 }
5383 
5384 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetProperty)5385 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
5386   HandleScope scope(isolate);
5387   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5388 
5389   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5390   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5391   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5392   CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5393   RUNTIME_ASSERT(
5394       (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5395   // Compute attributes.
5396   PropertyAttributes attributes =
5397       static_cast<PropertyAttributes>(unchecked_attributes);
5398 
5399   StrictModeFlag strict_mode = kNonStrictMode;
5400   if (args.length() == 5) {
5401     CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
5402     strict_mode = strict_mode_flag;
5403   }
5404 
5405   Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
5406                                                      value,
5407                                                      attributes,
5408                                                      strict_mode);
5409   RETURN_IF_EMPTY_HANDLE(isolate, result);
5410   return *result;
5411 }
5412 
5413 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TransitionElementsKind)5414 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
5415   HandleScope scope(isolate);
5416   RUNTIME_ASSERT(args.length() == 2);
5417   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5418   CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5419   JSObject::TransitionElementsKind(array, map->elements_kind());
5420   return *array;
5421 }
5422 
5423 
5424 // Set the native flag on the function.
5425 // This is used to decide if we should transform null and undefined
5426 // into the global object when doing call and apply.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetNativeFlag)5427 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
5428   SealHandleScope shs(isolate);
5429   RUNTIME_ASSERT(args.length() == 1);
5430 
5431   CONVERT_ARG_CHECKED(Object, object, 0);
5432 
5433   if (object->IsJSFunction()) {
5434     JSFunction* func = JSFunction::cast(object);
5435     func->shared()->set_native(true);
5436   }
5437   return isolate->heap()->undefined_value();
5438 }
5439 
5440 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetInlineBuiltinFlag)5441 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInlineBuiltinFlag) {
5442   SealHandleScope shs(isolate);
5443   RUNTIME_ASSERT(args.length() == 1);
5444 
5445   Handle<Object> object = args.at<Object>(0);
5446 
5447   if (object->IsJSFunction()) {
5448     JSFunction* func = JSFunction::cast(*object);
5449     func->shared()->set_inline_builtin(true);
5450   }
5451   return isolate->heap()->undefined_value();
5452 }
5453 
5454 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StoreArrayLiteralElement)5455 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
5456   HandleScope scope(isolate);
5457   RUNTIME_ASSERT(args.length() == 5);
5458   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5459   CONVERT_SMI_ARG_CHECKED(store_index, 1);
5460   Handle<Object> value = args.at<Object>(2);
5461   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5462   CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5463 
5464   Object* raw_literal_cell = literals->get(literal_index);
5465   JSArray* boilerplate = NULL;
5466   if (raw_literal_cell->IsAllocationSite()) {
5467     AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5468     boilerplate = JSArray::cast(site->transition_info());
5469   } else {
5470     boilerplate = JSArray::cast(raw_literal_cell);
5471   }
5472   Handle<JSArray> boilerplate_object(boilerplate);
5473   ElementsKind elements_kind = object->GetElementsKind();
5474   ASSERT(IsFastElementsKind(elements_kind));
5475   // Smis should never trigger transitions.
5476   ASSERT(!value->IsSmi());
5477 
5478   if (value->IsNumber()) {
5479     ASSERT(IsFastSmiElementsKind(elements_kind));
5480     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5481         ? FAST_HOLEY_DOUBLE_ELEMENTS
5482         : FAST_DOUBLE_ELEMENTS;
5483     if (IsMoreGeneralElementsKindTransition(
5484             boilerplate_object->GetElementsKind(),
5485             transitioned_kind)) {
5486       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5487     }
5488     JSObject::TransitionElementsKind(object, transitioned_kind);
5489     ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
5490     FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5491     HeapNumber* number = HeapNumber::cast(*value);
5492     double_array->set(store_index, number->Number());
5493   } else {
5494     ASSERT(IsFastSmiElementsKind(elements_kind) ||
5495            IsFastDoubleElementsKind(elements_kind));
5496     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5497         ? FAST_HOLEY_ELEMENTS
5498         : FAST_ELEMENTS;
5499     JSObject::TransitionElementsKind(object, transitioned_kind);
5500     if (IsMoreGeneralElementsKindTransition(
5501             boilerplate_object->GetElementsKind(),
5502             transitioned_kind)) {
5503       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5504     }
5505     FixedArray* object_array = FixedArray::cast(object->elements());
5506     object_array->set(store_index, *value);
5507   }
5508   return *object;
5509 }
5510 
5511 
5512 // Check whether debugger and is about to step into the callback that is passed
5513 // to a built-in function such as Array.forEach.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugCallbackSupportsStepping)5514 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
5515   SealHandleScope shs(isolate);
5516 #ifdef ENABLE_DEBUGGER_SUPPORT
5517   if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
5518     return isolate->heap()->false_value();
5519   }
5520   CONVERT_ARG_CHECKED(Object, callback, 0);
5521   // We do not step into the callback if it's a builtin or not even a function.
5522   if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
5523     return isolate->heap()->false_value();
5524   }
5525   return isolate->heap()->true_value();
5526 #else
5527   return isolate->heap()->false_value();
5528 #endif  // ENABLE_DEBUGGER_SUPPORT
5529 }
5530 
5531 
5532 // Set one shot breakpoints for the callback function that is passed to a
5533 // built-in function such as Array.forEach to enable stepping into the callback.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPrepareStepInIfStepping)5534 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
5535   SealHandleScope shs(isolate);
5536 #ifdef ENABLE_DEBUGGER_SUPPORT
5537   Debug* debug = isolate->debug();
5538   if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5539   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
5540   HandleScope scope(isolate);
5541   // When leaving the callback, step out has been activated, but not performed
5542   // if we do not leave the builtin.  To be able to step into the callback
5543   // again, we need to clear the step out at this point.
5544   debug->ClearStepOut();
5545   debug->FloodWithOneShot(callback);
5546 #endif  // ENABLE_DEBUGGER_SUPPORT
5547   return isolate->heap()->undefined_value();
5548 }
5549 
5550 
5551 // Set a local property, even if it is READ_ONLY.  If the property does not
5552 // exist, it will be added with attributes NONE.
RUNTIME_FUNCTION(MaybeObject *,Runtime_IgnoreAttributesAndSetProperty)5553 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
5554   HandleScope scope(isolate);
5555   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
5556   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5557   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5558   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5559   // Compute attributes.
5560   PropertyAttributes attributes = NONE;
5561   if (args.length() == 4) {
5562     CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
5563     // Only attribute bits should be set.
5564     RUNTIME_ASSERT(
5565         (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5566     attributes = static_cast<PropertyAttributes>(unchecked_value);
5567   }
5568   Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5569       object, name, value, attributes);
5570   RETURN_IF_EMPTY_HANDLE(isolate, result);
5571   return *result;
5572 }
5573 
5574 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteProperty)5575 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
5576   HandleScope scope(isolate);
5577   ASSERT(args.length() == 3);
5578   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5579   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5580   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5581   JSReceiver::DeleteMode delete_mode = (strict_mode == kStrictMode)
5582       ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
5583   Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
5584   RETURN_IF_EMPTY_HANDLE(isolate, result);
5585   return *result;
5586 }
5587 
5588 
HasLocalPropertyImplementation(Isolate * isolate,Handle<JSObject> object,Handle<Name> key)5589 static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
5590                                                    Handle<JSObject> object,
5591                                                    Handle<Name> key) {
5592   if (JSReceiver::HasLocalProperty(object, key)) {
5593     return isolate->heap()->true_value();
5594   }
5595   // Handle hidden prototypes.  If there's a hidden prototype above this thing
5596   // then we have to check it for properties, because they are supposed to
5597   // look like they are on this object.
5598   Handle<Object> proto(object->GetPrototype(), isolate);
5599   if (proto->IsJSObject() &&
5600       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
5601     return HasLocalPropertyImplementation(isolate,
5602                                           Handle<JSObject>::cast(proto),
5603                                           key);
5604   }
5605   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5606   return isolate->heap()->false_value();
5607 }
5608 
5609 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasLocalProperty)5610 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
5611   HandleScope scope(isolate);
5612   ASSERT(args.length() == 2);
5613   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5614   Handle<Object> object = args.at<Object>(0);
5615 
5616   uint32_t index;
5617   const bool key_is_array_index = key->AsArrayIndex(&index);
5618 
5619   // Only JS objects can have properties.
5620   if (object->IsJSObject()) {
5621     Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
5622     // Fast case: either the key is a real named property or it is not
5623     // an array index and there are no interceptors or hidden
5624     // prototypes.
5625     if (JSObject::HasRealNamedProperty(js_obj, key)) {
5626       ASSERT(!isolate->has_scheduled_exception());
5627       return isolate->heap()->true_value();
5628     } else {
5629       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5630     }
5631     Map* map = js_obj->map();
5632     if (!key_is_array_index &&
5633         !map->has_named_interceptor() &&
5634         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5635       return isolate->heap()->false_value();
5636     }
5637     // Slow case.
5638     return HasLocalPropertyImplementation(isolate,
5639                                           Handle<JSObject>(js_obj),
5640                                           Handle<Name>(key));
5641   } else if (object->IsString() && key_is_array_index) {
5642     // Well, there is one exception:  Handle [] on strings.
5643     Handle<String> string = Handle<String>::cast(object);
5644     if (index < static_cast<uint32_t>(string->length())) {
5645       return isolate->heap()->true_value();
5646     }
5647   }
5648   return isolate->heap()->false_value();
5649 }
5650 
5651 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasProperty)5652 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
5653   HandleScope scope(isolate);
5654   ASSERT(args.length() == 2);
5655   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5656   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5657 
5658   bool result = JSReceiver::HasProperty(receiver, key);
5659   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5660   if (isolate->has_pending_exception()) return Failure::Exception();
5661   return isolate->heap()->ToBoolean(result);
5662 }
5663 
5664 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasElement)5665 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
5666   HandleScope scope(isolate);
5667   ASSERT(args.length() == 2);
5668   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5669   CONVERT_SMI_ARG_CHECKED(index, 1);
5670 
5671   bool result = JSReceiver::HasElement(receiver, index);
5672   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5673   if (isolate->has_pending_exception()) return Failure::Exception();
5674   return isolate->heap()->ToBoolean(result);
5675 }
5676 
5677 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsPropertyEnumerable)5678 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
5679   SealHandleScope shs(isolate);
5680   ASSERT(args.length() == 2);
5681 
5682   CONVERT_ARG_CHECKED(JSObject, object, 0);
5683   CONVERT_ARG_CHECKED(Name, key, 1);
5684 
5685   PropertyAttributes att = object->GetLocalPropertyAttribute(key);
5686   if (att == ABSENT || (att & DONT_ENUM) != 0) {
5687     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5688     return isolate->heap()->false_value();
5689   }
5690   ASSERT(!isolate->has_scheduled_exception());
5691   return isolate->heap()->true_value();
5692 }
5693 
5694 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPropertyNames)5695 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
5696   HandleScope scope(isolate);
5697   ASSERT(args.length() == 1);
5698   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5699   bool threw = false;
5700   Handle<JSArray> result = GetKeysFor(object, &threw);
5701   if (threw) return Failure::Exception();
5702   return *result;
5703 }
5704 
5705 
5706 // Returns either a FixedArray as Runtime_GetPropertyNames,
5707 // or, if the given object has an enum cache that contains
5708 // all enumerable properties of the object and its prototypes
5709 // have none, the map of the object. This is used to speed up
5710 // the check for deletions during a for-in.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPropertyNamesFast)5711 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
5712   SealHandleScope shs(isolate);
5713   ASSERT(args.length() == 1);
5714 
5715   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5716 
5717   if (raw_object->IsSimpleEnum()) return raw_object->map();
5718 
5719   HandleScope scope(isolate);
5720   Handle<JSReceiver> object(raw_object);
5721   bool threw = false;
5722   Handle<FixedArray> content =
5723       GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
5724   if (threw) return Failure::Exception();
5725 
5726   // Test again, since cache may have been built by preceding call.
5727   if (object->IsSimpleEnum()) return object->map();
5728 
5729   return *content;
5730 }
5731 
5732 
5733 // Find the length of the prototype chain that is to to handled as one. If a
5734 // prototype object is hidden it is to be viewed as part of the the object it
5735 // is prototype for.
LocalPrototypeChainLength(JSObject * obj)5736 static int LocalPrototypeChainLength(JSObject* obj) {
5737   int count = 1;
5738   Object* proto = obj->GetPrototype();
5739   while (proto->IsJSObject() &&
5740          JSObject::cast(proto)->map()->is_hidden_prototype()) {
5741     count++;
5742     proto = JSObject::cast(proto)->GetPrototype();
5743   }
5744   return count;
5745 }
5746 
5747 
5748 // Return the names of the local named properties.
5749 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLocalPropertyNames)5750 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
5751   HandleScope scope(isolate);
5752   ASSERT(args.length() == 2);
5753   if (!args[0]->IsJSObject()) {
5754     return isolate->heap()->undefined_value();
5755   }
5756   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5757   CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
5758   PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
5759 
5760   // Skip the global proxy as it has no properties and always delegates to the
5761   // real global object.
5762   if (obj->IsJSGlobalProxy()) {
5763     // Only collect names if access is permitted.
5764     if (obj->IsAccessCheckNeeded() &&
5765         !isolate->MayNamedAccess(*obj,
5766                                  isolate->heap()->undefined_value(),
5767                                  v8::ACCESS_KEYS)) {
5768       isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
5769       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5770       return *isolate->factory()->NewJSArray(0);
5771     }
5772     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5773   }
5774 
5775   // Find the number of objects making up this.
5776   int length = LocalPrototypeChainLength(*obj);
5777 
5778   // Find the number of local properties for each of the objects.
5779   ScopedVector<int> local_property_count(length);
5780   int total_property_count = 0;
5781   Handle<JSObject> jsproto = obj;
5782   for (int i = 0; i < length; i++) {
5783     // Only collect names if access is permitted.
5784     if (jsproto->IsAccessCheckNeeded() &&
5785         !isolate->MayNamedAccess(*jsproto,
5786                                  isolate->heap()->undefined_value(),
5787                                  v8::ACCESS_KEYS)) {
5788       isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
5789       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5790       return *isolate->factory()->NewJSArray(0);
5791     }
5792     int n;
5793     n = jsproto->NumberOfLocalProperties(filter);
5794     local_property_count[i] = n;
5795     total_property_count += n;
5796     if (i < length - 1) {
5797       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5798     }
5799   }
5800 
5801   // Allocate an array with storage for all the property names.
5802   Handle<FixedArray> names =
5803       isolate->factory()->NewFixedArray(total_property_count);
5804 
5805   // Get the property names.
5806   jsproto = obj;
5807   int proto_with_hidden_properties = 0;
5808   int next_copy_index = 0;
5809   for (int i = 0; i < length; i++) {
5810     jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
5811     next_copy_index += local_property_count[i];
5812     if (jsproto->HasHiddenProperties()) {
5813       proto_with_hidden_properties++;
5814     }
5815     if (i < length - 1) {
5816       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5817     }
5818   }
5819 
5820   // Filter out name of hidden properties object.
5821   if (proto_with_hidden_properties > 0) {
5822     Handle<FixedArray> old_names = names;
5823     names = isolate->factory()->NewFixedArray(
5824         names->length() - proto_with_hidden_properties);
5825     int dest_pos = 0;
5826     for (int i = 0; i < total_property_count; i++) {
5827       Object* name = old_names->get(i);
5828       if (name == isolate->heap()->hidden_string()) {
5829         continue;
5830       }
5831       names->set(dest_pos++, name);
5832     }
5833   }
5834 
5835   return *isolate->factory()->NewJSArrayWithElements(names);
5836 }
5837 
5838 
5839 // Return the names of the local indexed properties.
5840 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLocalElementNames)5841 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5842   HandleScope scope(isolate);
5843   ASSERT(args.length() == 1);
5844   if (!args[0]->IsJSObject()) {
5845     return isolate->heap()->undefined_value();
5846   }
5847   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5848 
5849   int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5850   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5851   obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5852   return *isolate->factory()->NewJSArrayWithElements(names);
5853 }
5854 
5855 
5856 // Return information on whether an object has a named or indexed interceptor.
5857 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetInterceptorInfo)5858 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5859   HandleScope scope(isolate);
5860   ASSERT(args.length() == 1);
5861   if (!args[0]->IsJSObject()) {
5862     return Smi::FromInt(0);
5863   }
5864   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5865 
5866   int result = 0;
5867   if (obj->HasNamedInterceptor()) result |= 2;
5868   if (obj->HasIndexedInterceptor()) result |= 1;
5869 
5870   return Smi::FromInt(result);
5871 }
5872 
5873 
5874 // Return property names from named interceptor.
5875 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetNamedInterceptorPropertyNames)5876 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5877   HandleScope scope(isolate);
5878   ASSERT(args.length() == 1);
5879   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5880 
5881   if (obj->HasNamedInterceptor()) {
5882     v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5883     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5884   }
5885   return isolate->heap()->undefined_value();
5886 }
5887 
5888 
5889 // Return element names from indexed interceptor.
5890 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetIndexedInterceptorElementNames)5891 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5892   HandleScope scope(isolate);
5893   ASSERT(args.length() == 1);
5894   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5895 
5896   if (obj->HasIndexedInterceptor()) {
5897     v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5898     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5899   }
5900   return isolate->heap()->undefined_value();
5901 }
5902 
5903 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LocalKeys)5904 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5905   HandleScope scope(isolate);
5906   ASSERT_EQ(args.length(), 1);
5907   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5908   Handle<JSObject> object(raw_object);
5909 
5910   if (object->IsJSGlobalProxy()) {
5911     // Do access checks before going to the global object.
5912     if (object->IsAccessCheckNeeded() &&
5913         !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5914                              v8::ACCESS_KEYS)) {
5915       isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5916       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5917       return *isolate->factory()->NewJSArray(0);
5918     }
5919 
5920     Handle<Object> proto(object->GetPrototype(), isolate);
5921     // If proxy is detached we simply return an empty array.
5922     if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5923     object = Handle<JSObject>::cast(proto);
5924   }
5925 
5926   bool threw = false;
5927   Handle<FixedArray> contents =
5928       GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5929   if (threw) return Failure::Exception();
5930 
5931   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5932   // property array and since the result is mutable we have to create
5933   // a fresh clone on each invocation.
5934   int length = contents->length();
5935   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5936   for (int i = 0; i < length; i++) {
5937     Object* entry = contents->get(i);
5938     if (entry->IsString()) {
5939       copy->set(i, entry);
5940     } else {
5941       ASSERT(entry->IsNumber());
5942       HandleScope scope(isolate);
5943       Handle<Object> entry_handle(entry, isolate);
5944       Handle<Object> entry_str =
5945           isolate->factory()->NumberToString(entry_handle);
5946       copy->set(i, *entry_str);
5947     }
5948   }
5949   return *isolate->factory()->NewJSArrayWithElements(copy);
5950 }
5951 
5952 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetArgumentsProperty)5953 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5954   SealHandleScope shs(isolate);
5955   ASSERT(args.length() == 1);
5956 
5957   // Compute the frame holding the arguments.
5958   JavaScriptFrameIterator it(isolate);
5959   it.AdvanceToArgumentsFrame();
5960   JavaScriptFrame* frame = it.frame();
5961 
5962   // Get the actual number of provided arguments.
5963   const uint32_t n = frame->ComputeParametersCount();
5964 
5965   // Try to convert the key to an index. If successful and within
5966   // index return the the argument from the frame.
5967   uint32_t index;
5968   if (args[0]->ToArrayIndex(&index) && index < n) {
5969     return frame->GetParameter(index);
5970   }
5971 
5972   if (args[0]->IsSymbol()) {
5973     // Lookup in the initial Object.prototype object.
5974     return isolate->initial_object_prototype()->GetProperty(
5975         Symbol::cast(args[0]));
5976   }
5977 
5978   // Convert the key to a string.
5979   HandleScope scope(isolate);
5980   bool exception = false;
5981   Handle<Object> converted =
5982       Execution::ToString(isolate, args.at<Object>(0), &exception);
5983   if (exception) return Failure::Exception();
5984   Handle<String> key = Handle<String>::cast(converted);
5985 
5986   // Try to convert the string key into an array index.
5987   if (key->AsArrayIndex(&index)) {
5988     if (index < n) {
5989       return frame->GetParameter(index);
5990     } else {
5991       return isolate->initial_object_prototype()->GetElement(isolate, index);
5992     }
5993   }
5994 
5995   // Handle special arguments properties.
5996   if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
5997   if (key->Equals(isolate->heap()->callee_string())) {
5998     JSFunction* function = frame->function();
5999     if (!function->shared()->is_classic_mode()) {
6000       return isolate->Throw(*isolate->factory()->NewTypeError(
6001           "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
6002     }
6003     return function;
6004   }
6005 
6006   // Lookup in the initial Object.prototype object.
6007   return isolate->initial_object_prototype()->GetProperty(*key);
6008 }
6009 
6010 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToFastProperties)6011 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
6012   HandleScope scope(isolate);
6013   ASSERT(args.length() == 1);
6014   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
6015   if (object->IsJSObject() && !object->IsGlobalObject()) {
6016     JSObject::TransformToFastProperties(Handle<JSObject>::cast(object), 0);
6017   }
6018   return *object;
6019 }
6020 
6021 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToBool)6022 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
6023   SealHandleScope shs(isolate);
6024   ASSERT(args.length() == 1);
6025 
6026   return isolate->heap()->ToBoolean(args[0]->BooleanValue());
6027 }
6028 
6029 
6030 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
6031 // Possible optimizations: put the type string into the oddballs.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Typeof)6032 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
6033   SealHandleScope shs(isolate);
6034 
6035   Object* obj = args[0];
6036   if (obj->IsNumber()) return isolate->heap()->number_string();
6037   HeapObject* heap_obj = HeapObject::cast(obj);
6038 
6039   // typeof an undetectable object is 'undefined'
6040   if (heap_obj->map()->is_undetectable()) {
6041     return isolate->heap()->undefined_string();
6042   }
6043 
6044   InstanceType instance_type = heap_obj->map()->instance_type();
6045   if (instance_type < FIRST_NONSTRING_TYPE) {
6046     return isolate->heap()->string_string();
6047   }
6048 
6049   switch (instance_type) {
6050     case ODDBALL_TYPE:
6051       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
6052         return isolate->heap()->boolean_string();
6053       }
6054       if (heap_obj->IsNull()) {
6055         return FLAG_harmony_typeof
6056             ? isolate->heap()->null_string()
6057             : isolate->heap()->object_string();
6058       }
6059       ASSERT(heap_obj->IsUndefined());
6060       return isolate->heap()->undefined_string();
6061     case SYMBOL_TYPE:
6062       return isolate->heap()->symbol_string();
6063     case JS_FUNCTION_TYPE:
6064     case JS_FUNCTION_PROXY_TYPE:
6065       return isolate->heap()->function_string();
6066     default:
6067       // For any kind of object not handled above, the spec rule for
6068       // host objects gives that it is okay to return "object"
6069       return isolate->heap()->object_string();
6070   }
6071 }
6072 
6073 
AreDigits(const uint8_t * s,int from,int to)6074 static bool AreDigits(const uint8_t*s, int from, int to) {
6075   for (int i = from; i < to; i++) {
6076     if (s[i] < '0' || s[i] > '9') return false;
6077   }
6078 
6079   return true;
6080 }
6081 
6082 
ParseDecimalInteger(const uint8_t * s,int from,int to)6083 static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
6084   ASSERT(to - from < 10);  // Overflow is not possible.
6085   ASSERT(from < to);
6086   int d = s[from] - '0';
6087 
6088   for (int i = from + 1; i < to; i++) {
6089     d = 10 * d + (s[i] - '0');
6090   }
6091 
6092   return d;
6093 }
6094 
6095 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToNumber)6096 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
6097   SealHandleScope shs(isolate);
6098   ASSERT(args.length() == 1);
6099   CONVERT_ARG_CHECKED(String, subject, 0);
6100   subject->TryFlatten();
6101 
6102   // Fast case: short integer or some sorts of junk values.
6103   int len = subject->length();
6104   if (subject->IsSeqOneByteString()) {
6105     if (len == 0) return Smi::FromInt(0);
6106 
6107     uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
6108     bool minus = (data[0] == '-');
6109     int start_pos = (minus ? 1 : 0);
6110 
6111     if (start_pos == len) {
6112       return isolate->heap()->nan_value();
6113     } else if (data[start_pos] > '9') {
6114       // Fast check for a junk value. A valid string may start from a
6115       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
6116       // the 'I' character ('Infinity'). All of that have codes not greater than
6117       // '9' except 'I' and &nbsp;.
6118       if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
6119         return isolate->heap()->nan_value();
6120       }
6121     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
6122       // The maximal/minimal smi has 10 digits. If the string has less digits we
6123       // know it will fit into the smi-data type.
6124       int d = ParseDecimalInteger(data, start_pos, len);
6125       if (minus) {
6126         if (d == 0) return isolate->heap()->minus_zero_value();
6127         d = -d;
6128       } else if (!subject->HasHashCode() &&
6129                  len <= String::kMaxArrayIndexSize &&
6130                  (len == 1 || data[0] != '0')) {
6131         // String hash is not calculated yet but all the data are present.
6132         // Update the hash field to speed up sequential convertions.
6133         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
6134 #ifdef DEBUG
6135         subject->Hash();  // Force hash calculation.
6136         ASSERT_EQ(static_cast<int>(subject->hash_field()),
6137                   static_cast<int>(hash));
6138 #endif
6139         subject->set_hash_field(hash);
6140       }
6141       return Smi::FromInt(d);
6142     }
6143   }
6144 
6145   // Slower case.
6146   int flags = ALLOW_HEX;
6147   if (FLAG_harmony_numeric_literals) {
6148     // The current spec draft has not updated "ToNumber Applied to the String
6149     // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6150     flags |= ALLOW_OCTAL | ALLOW_BINARY;
6151   }
6152   return isolate->heap()->NumberFromDouble(
6153       StringToDouble(isolate->unicode_cache(), subject, flags));
6154 }
6155 
6156 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewString)6157 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
6158   SealHandleScope shs(isolate);
6159   CONVERT_SMI_ARG_CHECKED(length, 0);
6160   CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6161   if (length == 0) return isolate->heap()->empty_string();
6162   if (is_one_byte) {
6163     return isolate->heap()->AllocateRawOneByteString(length);
6164   } else {
6165     return isolate->heap()->AllocateRawTwoByteString(length);
6166   }
6167 }
6168 
6169 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TruncateString)6170 RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
6171   HandleScope scope(isolate);
6172   CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
6173   CONVERT_SMI_ARG_CHECKED(new_length, 1);
6174   return *SeqString::Truncate(string, new_length);
6175 }
6176 
6177 
RUNTIME_FUNCTION(MaybeObject *,Runtime_URIEscape)6178 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
6179   HandleScope scope(isolate);
6180   ASSERT(args.length() == 1);
6181   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6182   Handle<String> string = FlattenGetString(source);
6183   ASSERT(string->IsFlat());
6184   Handle<String> result = string->IsOneByteRepresentationUnderneath()
6185       ? URIEscape::Escape<uint8_t>(isolate, source)
6186       : URIEscape::Escape<uc16>(isolate, source);
6187   if (result.is_null()) return Failure::OutOfMemoryException(0x12);
6188   return *result;
6189 }
6190 
6191 
RUNTIME_FUNCTION(MaybeObject *,Runtime_URIUnescape)6192 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
6193   HandleScope scope(isolate);
6194   ASSERT(args.length() == 1);
6195   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6196   Handle<String> string = FlattenGetString(source);
6197   ASSERT(string->IsFlat());
6198   return string->IsOneByteRepresentationUnderneath()
6199       ? *URIUnescape::Unescape<uint8_t>(isolate, source)
6200       : *URIUnescape::Unescape<uc16>(isolate, source);
6201 }
6202 
6203 
RUNTIME_FUNCTION(MaybeObject *,Runtime_QuoteJSONString)6204 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
6205   HandleScope scope(isolate);
6206   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6207   ASSERT(args.length() == 1);
6208   return BasicJsonStringifier::StringifyString(isolate, string);
6209 }
6210 
6211 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BasicJSONStringify)6212 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
6213   HandleScope scope(isolate);
6214   ASSERT(args.length() == 1);
6215   BasicJsonStringifier stringifier(isolate);
6216   return stringifier.Stringify(Handle<Object>(args[0], isolate));
6217 }
6218 
6219 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringParseInt)6220 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
6221   SealHandleScope shs(isolate);
6222 
6223   CONVERT_ARG_CHECKED(String, s, 0);
6224   CONVERT_SMI_ARG_CHECKED(radix, 1);
6225 
6226   s->TryFlatten();
6227 
6228   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6229   double value = StringToInt(isolate->unicode_cache(), s, radix);
6230   return isolate->heap()->NumberFromDouble(value);
6231 }
6232 
6233 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringParseFloat)6234 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6235   SealHandleScope shs(isolate);
6236   CONVERT_ARG_CHECKED(String, str, 0);
6237 
6238   // ECMA-262 section 15.1.2.3, empty string is NaN
6239   double value = StringToDouble(isolate->unicode_cache(),
6240                                 str, ALLOW_TRAILING_JUNK, OS::nan_value());
6241 
6242   // Create a number object from the value.
6243   return isolate->heap()->NumberFromDouble(value);
6244 }
6245 
6246 
6247 template <class Converter>
ConvertCaseHelper(Isolate * isolate,String * s,String::Encoding result_encoding,int length,int input_string_length,unibrow::Mapping<Converter,128> * mapping)6248 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6249     Isolate* isolate,
6250     String* s,
6251     String::Encoding result_encoding,
6252     int length,
6253     int input_string_length,
6254     unibrow::Mapping<Converter, 128>* mapping) {
6255   // We try this twice, once with the assumption that the result is no longer
6256   // than the input and, if that assumption breaks, again with the exact
6257   // length.  This may not be pretty, but it is nicer than what was here before
6258   // and I hereby claim my vaffel-is.
6259   //
6260   // Allocate the resulting string.
6261   //
6262   // NOTE: This assumes that the upper/lower case of an ASCII
6263   // character is also ASCII.  This is currently the case, but it
6264   // might break in the future if we implement more context and locale
6265   // dependent upper/lower conversions.
6266   Object* o;
6267   { MaybeObject* maybe_o = result_encoding == String::ONE_BYTE_ENCODING
6268         ? isolate->heap()->AllocateRawOneByteString(length)
6269         : isolate->heap()->AllocateRawTwoByteString(length);
6270     if (!maybe_o->ToObject(&o)) return maybe_o;
6271   }
6272   String* result = String::cast(o);
6273   bool has_changed_character = false;
6274 
6275   DisallowHeapAllocation no_gc;
6276 
6277   // Convert all characters to upper case, assuming that they will fit
6278   // in the buffer
6279   Access<ConsStringIteratorOp> op(
6280       isolate->runtime_state()->string_iterator());
6281   StringCharacterStream stream(s, op.value());
6282   unibrow::uchar chars[Converter::kMaxWidth];
6283   // We can assume that the string is not empty
6284   uc32 current = stream.GetNext();
6285   // y with umlauts is the only character that stops fitting into one-byte
6286   // when converting to uppercase.
6287   static const uc32 yuml_code = 0xff;
6288   bool ignore_yuml = result->IsSeqTwoByteString() || Converter::kIsToLower;
6289   for (int i = 0; i < length;) {
6290     bool has_next = stream.HasMore();
6291     uc32 next = has_next ? stream.GetNext() : 0;
6292     int char_length = mapping->get(current, next, chars);
6293     if (char_length == 0) {
6294       // The case conversion of this character is the character itself.
6295       result->Set(i, current);
6296       i++;
6297     } else if (char_length == 1 && (ignore_yuml || current != yuml_code)) {
6298       // Common case: converting the letter resulted in one character.
6299       ASSERT(static_cast<uc32>(chars[0]) != current);
6300       result->Set(i, chars[0]);
6301       has_changed_character = true;
6302       i++;
6303     } else if (length == input_string_length) {
6304       bool found_yuml = (current == yuml_code);
6305       // We've assumed that the result would be as long as the
6306       // input but here is a character that converts to several
6307       // characters.  No matter, we calculate the exact length
6308       // of the result and try the whole thing again.
6309       //
6310       // Note that this leaves room for optimization.  We could just
6311       // memcpy what we already have to the result string.  Also,
6312       // the result string is the last object allocated we could
6313       // "realloc" it and probably, in the vast majority of cases,
6314       // extend the existing string to be able to hold the full
6315       // result.
6316       int next_length = 0;
6317       if (has_next) {
6318         next_length = mapping->get(next, 0, chars);
6319         if (next_length == 0) next_length = 1;
6320       }
6321       int current_length = i + char_length + next_length;
6322       while (stream.HasMore()) {
6323         current = stream.GetNext();
6324         found_yuml |= (current == yuml_code);
6325         // NOTE: we use 0 as the next character here because, while
6326         // the next character may affect what a character converts to,
6327         // it does not in any case affect the length of what it convert
6328         // to.
6329         int char_length = mapping->get(current, 0, chars);
6330         if (char_length == 0) char_length = 1;
6331         current_length += char_length;
6332         if (current_length > Smi::kMaxValue) {
6333           isolate->context()->mark_out_of_memory();
6334           return Failure::OutOfMemoryException(0x13);
6335         }
6336       }
6337       // Try again with the real length.  Return signed if we need
6338       // to allocate a two-byte string for y-umlaut to uppercase.
6339       return (found_yuml && !ignore_yuml) ? Smi::FromInt(-current_length)
6340                                           : Smi::FromInt(current_length);
6341     } else {
6342       for (int j = 0; j < char_length; j++) {
6343         result->Set(i, chars[j]);
6344         i++;
6345       }
6346       has_changed_character = true;
6347     }
6348     current = next;
6349   }
6350   if (has_changed_character) {
6351     return result;
6352   } else {
6353     // If we didn't actually change anything in doing the conversion
6354     // we simple return the result and let the converted string
6355     // become garbage; there is no reason to keep two identical strings
6356     // alive.
6357     return s;
6358   }
6359 }
6360 
6361 
6362 namespace {
6363 
6364 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6365 static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6366 
6367 // Given a word and two range boundaries returns a word with high bit
6368 // set in every byte iff the corresponding input byte was strictly in
6369 // the range (m, n). All the other bits in the result are cleared.
6370 // This function is only useful when it can be inlined and the
6371 // boundaries are statically known.
6372 // Requires: all bytes in the input word and the boundaries must be
6373 // ASCII (less than 0x7F).
AsciiRangeMask(uintptr_t w,char m,char n)6374 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6375   // Use strict inequalities since in edge cases the function could be
6376   // further simplified.
6377   ASSERT(0 < m && m < n);
6378   // Has high bit set in every w byte less than n.
6379   uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6380   // Has high bit set in every w byte greater than m.
6381   uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6382   return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6383 }
6384 
6385 
6386 #ifdef DEBUG
CheckFastAsciiConvert(char * dst,char * src,int length,bool changed,bool is_to_lower)6387 static bool CheckFastAsciiConvert(char* dst,
6388                                   char* src,
6389                                   int length,
6390                                   bool changed,
6391                                   bool is_to_lower) {
6392   bool expected_changed = false;
6393   for (int i = 0; i < length; i++) {
6394     if (dst[i] == src[i]) continue;
6395     expected_changed = true;
6396     if (is_to_lower) {
6397       ASSERT('A' <= src[i] && src[i] <= 'Z');
6398       ASSERT(dst[i] == src[i] + ('a' - 'A'));
6399     } else {
6400       ASSERT('a' <= src[i] && src[i] <= 'z');
6401       ASSERT(dst[i] == src[i] - ('a' - 'A'));
6402     }
6403   }
6404   return (expected_changed == changed);
6405 }
6406 #endif
6407 
6408 
6409 template<class Converter>
FastAsciiConvert(char * dst,char * src,int length,bool * changed_out)6410 static bool FastAsciiConvert(char* dst,
6411                              char* src,
6412                              int length,
6413                              bool* changed_out) {
6414 #ifdef DEBUG
6415     char* saved_dst = dst;
6416     char* saved_src = src;
6417 #endif
6418   DisallowHeapAllocation no_gc;
6419   // We rely on the distance between upper and lower case letters
6420   // being a known power of 2.
6421   ASSERT('a' - 'A' == (1 << 5));
6422   // Boundaries for the range of input characters than require conversion.
6423   static const char lo = Converter::kIsToLower ? 'A' - 1 : 'a' - 1;
6424   static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
6425   bool changed = false;
6426   uintptr_t or_acc = 0;
6427   char* const limit = src + length;
6428 #ifdef V8_HOST_CAN_READ_UNALIGNED
6429   // Process the prefix of the input that requires no conversion one
6430   // (machine) word at a time.
6431   while (src <= limit - sizeof(uintptr_t)) {
6432     uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6433     or_acc |= w;
6434     if (AsciiRangeMask(w, lo, hi) != 0) {
6435       changed = true;
6436       break;
6437     }
6438     *reinterpret_cast<uintptr_t*>(dst) = w;
6439     src += sizeof(uintptr_t);
6440     dst += sizeof(uintptr_t);
6441   }
6442   // Process the remainder of the input performing conversion when
6443   // required one word at a time.
6444   while (src <= limit - sizeof(uintptr_t)) {
6445     uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6446     or_acc |= w;
6447     uintptr_t m = AsciiRangeMask(w, lo, hi);
6448     // The mask has high (7th) bit set in every byte that needs
6449     // conversion and we know that the distance between cases is
6450     // 1 << 5.
6451     *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6452     src += sizeof(uintptr_t);
6453     dst += sizeof(uintptr_t);
6454   }
6455 #endif
6456   // Process the last few bytes of the input (or the whole input if
6457   // unaligned access is not supported).
6458   while (src < limit) {
6459     char c = *src;
6460     or_acc |= c;
6461     if (lo < c && c < hi) {
6462       c ^= (1 << 5);
6463       changed = true;
6464     }
6465     *dst = c;
6466     ++src;
6467     ++dst;
6468   }
6469   if ((or_acc & kAsciiMask) != 0) {
6470     return false;
6471   }
6472 
6473   ASSERT(CheckFastAsciiConvert(
6474              saved_dst, saved_src, length, changed, Converter::kIsToLower));
6475 
6476   *changed_out = changed;
6477   return true;
6478 }
6479 
6480 }  // namespace
6481 
6482 
6483 template <class Converter>
ConvertCase(Arguments args,Isolate * isolate,unibrow::Mapping<Converter,128> * mapping)6484 MUST_USE_RESULT static MaybeObject* ConvertCase(
6485     Arguments args,
6486     Isolate* isolate,
6487     unibrow::Mapping<Converter, 128>* mapping) {
6488   SealHandleScope shs(isolate);
6489   CONVERT_ARG_CHECKED(String, s, 0);
6490   s = s->TryFlattenGetString();
6491 
6492   const int length = s->length();
6493   // Assume that the string is not empty; we need this assumption later
6494   if (length == 0) return s;
6495 
6496   // Simpler handling of ASCII strings.
6497   //
6498   // NOTE: This assumes that the upper/lower case of an ASCII
6499   // character is also ASCII.  This is currently the case, but it
6500   // might break in the future if we implement more context and locale
6501   // dependent upper/lower conversions.
6502   if (s->IsSeqOneByteString()) {
6503     Object* o;
6504     { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length);
6505       if (!maybe_o->ToObject(&o)) return maybe_o;
6506     }
6507     SeqOneByteString* result = SeqOneByteString::cast(o);
6508     bool has_changed_character;
6509     bool is_ascii = FastAsciiConvert<Converter>(
6510         reinterpret_cast<char*>(result->GetChars()),
6511         reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
6512         length,
6513         &has_changed_character);
6514     // If not ASCII, we discard the result and take the 2 byte path.
6515     if (is_ascii) {
6516       return has_changed_character ? result : s;
6517     }
6518   }
6519 
6520   String::Encoding result_encoding = s->IsOneByteRepresentation()
6521       ? String::ONE_BYTE_ENCODING : String::TWO_BYTE_ENCODING;
6522   Object* answer;
6523   { MaybeObject* maybe_answer = ConvertCaseHelper(
6524         isolate, s, result_encoding, length, length, mapping);
6525     if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6526   }
6527   if (answer->IsSmi()) {
6528     int new_length = Smi::cast(answer)->value();
6529     if (new_length < 0) {
6530       result_encoding = String::TWO_BYTE_ENCODING;
6531       new_length = -new_length;
6532     }
6533     MaybeObject* maybe_answer = ConvertCaseHelper(
6534         isolate, s, result_encoding, new_length, length, mapping);
6535     if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6536   }
6537   return answer;
6538 }
6539 
6540 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToLowerCase)6541 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6542   return ConvertCase(
6543       args, isolate, isolate->runtime_state()->to_lower_mapping());
6544 }
6545 
6546 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToUpperCase)6547 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6548   return ConvertCase(
6549       args, isolate, isolate->runtime_state()->to_upper_mapping());
6550 }
6551 
6552 
IsTrimWhiteSpace(unibrow::uchar c)6553 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6554   return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6555 }
6556 
6557 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringTrim)6558 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6559   SealHandleScope shs(isolate);
6560   ASSERT(args.length() == 3);
6561 
6562   CONVERT_ARG_CHECKED(String, s, 0);
6563   CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6564   CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6565 
6566   s->TryFlatten();
6567   int length = s->length();
6568 
6569   int left = 0;
6570   if (trimLeft) {
6571     while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6572       left++;
6573     }
6574   }
6575 
6576   int right = length;
6577   if (trimRight) {
6578     while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6579       right--;
6580     }
6581   }
6582   return s->SubString(left, right);
6583 }
6584 
6585 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringSplit)6586 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6587   HandleScope handle_scope(isolate);
6588   ASSERT(args.length() == 3);
6589   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6590   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6591   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6592 
6593   int subject_length = subject->length();
6594   int pattern_length = pattern->length();
6595   RUNTIME_ASSERT(pattern_length > 0);
6596 
6597   if (limit == 0xffffffffu) {
6598     Handle<Object> cached_answer(
6599         RegExpResultsCache::Lookup(isolate->heap(),
6600                                    *subject,
6601                                    *pattern,
6602                                    RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
6603         isolate);
6604     if (*cached_answer != Smi::FromInt(0)) {
6605       // The cache FixedArray is a COW-array and can therefore be reused.
6606       Handle<JSArray> result =
6607           isolate->factory()->NewJSArrayWithElements(
6608               Handle<FixedArray>::cast(cached_answer));
6609       return *result;
6610     }
6611   }
6612 
6613   // The limit can be very large (0xffffffffu), but since the pattern
6614   // isn't empty, we can never create more parts than ~half the length
6615   // of the subject.
6616 
6617   if (!subject->IsFlat()) FlattenString(subject);
6618 
6619   static const int kMaxInitialListCapacity = 16;
6620 
6621   ZoneScope zone_scope(isolate->runtime_zone());
6622 
6623   // Find (up to limit) indices of separator and end-of-string in subject
6624   int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6625   ZoneList<int> indices(initial_capacity, zone_scope.zone());
6626   if (!pattern->IsFlat()) FlattenString(pattern);
6627 
6628   FindStringIndicesDispatch(isolate, *subject, *pattern,
6629                             &indices, limit, zone_scope.zone());
6630 
6631   if (static_cast<uint32_t>(indices.length()) < limit) {
6632     indices.Add(subject_length, zone_scope.zone());
6633   }
6634 
6635   // The list indices now contains the end of each part to create.
6636 
6637   // Create JSArray of substrings separated by separator.
6638   int part_count = indices.length();
6639 
6640   Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6641   JSObject::EnsureCanContainHeapObjectElements(result);
6642   result->set_length(Smi::FromInt(part_count));
6643 
6644   ASSERT(result->HasFastObjectElements());
6645 
6646   if (part_count == 1 && indices.at(0) == subject_length) {
6647     FixedArray::cast(result->elements())->set(0, *subject);
6648     return *result;
6649   }
6650 
6651   Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6652   int part_start = 0;
6653   for (int i = 0; i < part_count; i++) {
6654     HandleScope local_loop_handle(isolate);
6655     int part_end = indices.at(i);
6656     Handle<String> substring =
6657         isolate->factory()->NewProperSubString(subject, part_start, part_end);
6658     elements->set(i, *substring);
6659     part_start = part_end + pattern_length;
6660   }
6661 
6662   if (limit == 0xffffffffu) {
6663     if (result->HasFastObjectElements()) {
6664       RegExpResultsCache::Enter(isolate->heap(),
6665                                 *subject,
6666                                 *pattern,
6667                                 *elements,
6668                                 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
6669     }
6670   }
6671 
6672   return *result;
6673 }
6674 
6675 
6676 // Copies ASCII characters to the given fixed array looking up
6677 // one-char strings in the cache. Gives up on the first char that is
6678 // not in the cache and fills the remainder with smi zeros. Returns
6679 // the length of the successfully copied prefix.
CopyCachedAsciiCharsToArray(Heap * heap,const uint8_t * chars,FixedArray * elements,int length)6680 static int CopyCachedAsciiCharsToArray(Heap* heap,
6681                                        const uint8_t* chars,
6682                                        FixedArray* elements,
6683                                        int length) {
6684   DisallowHeapAllocation no_gc;
6685   FixedArray* ascii_cache = heap->single_character_string_cache();
6686   Object* undefined = heap->undefined_value();
6687   int i;
6688   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6689   for (i = 0; i < length; ++i) {
6690     Object* value = ascii_cache->get(chars[i]);
6691     if (value == undefined) break;
6692     elements->set(i, value, mode);
6693   }
6694   if (i < length) {
6695     ASSERT(Smi::FromInt(0) == 0);
6696     memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6697   }
6698 #ifdef DEBUG
6699   for (int j = 0; j < length; ++j) {
6700     Object* element = elements->get(j);
6701     ASSERT(element == Smi::FromInt(0) ||
6702            (element->IsString() && String::cast(element)->LooksValid()));
6703   }
6704 #endif
6705   return i;
6706 }
6707 
6708 
6709 // Converts a String to JSArray.
6710 // For example, "foo" => ["f", "o", "o"].
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToArray)6711 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6712   HandleScope scope(isolate);
6713   ASSERT(args.length() == 2);
6714   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6715   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6716 
6717   s = FlattenGetString(s);
6718   const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6719 
6720   Handle<FixedArray> elements;
6721   int position = 0;
6722   if (s->IsFlat() && s->IsOneByteRepresentation()) {
6723     // Try using cached chars where possible.
6724     Object* obj;
6725     { MaybeObject* maybe_obj =
6726           isolate->heap()->AllocateUninitializedFixedArray(length);
6727       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6728     }
6729     elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6730     DisallowHeapAllocation no_gc;
6731     String::FlatContent content = s->GetFlatContent();
6732     if (content.IsAscii()) {
6733       Vector<const uint8_t> chars = content.ToOneByteVector();
6734       // Note, this will initialize all elements (not only the prefix)
6735       // to prevent GC from seeing partially initialized array.
6736       position = CopyCachedAsciiCharsToArray(isolate->heap(),
6737                                              chars.start(),
6738                                              *elements,
6739                                              length);
6740     } else {
6741       MemsetPointer(elements->data_start(),
6742                     isolate->heap()->undefined_value(),
6743                     length);
6744     }
6745   } else {
6746     elements = isolate->factory()->NewFixedArray(length);
6747   }
6748   for (int i = position; i < length; ++i) {
6749     Handle<Object> str =
6750         LookupSingleCharacterStringFromCode(isolate, s->Get(i));
6751     elements->set(i, *str);
6752   }
6753 
6754 #ifdef DEBUG
6755   for (int i = 0; i < length; ++i) {
6756     ASSERT(String::cast(elements->get(i))->length() == 1);
6757   }
6758 #endif
6759 
6760   return *isolate->factory()->NewJSArrayWithElements(elements);
6761 }
6762 
6763 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewStringWrapper)6764 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6765   SealHandleScope shs(isolate);
6766   ASSERT(args.length() == 1);
6767   CONVERT_ARG_CHECKED(String, value, 0);
6768   return value->ToObject(isolate);
6769 }
6770 
6771 
IsUpperCaseChar(RuntimeState * runtime_state,uint16_t ch)6772 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6773   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6774   int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6775   return char_length == 0;
6776 }
6777 
6778 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToString)6779 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6780   SealHandleScope shs(isolate);
6781   ASSERT(args.length() == 1);
6782 
6783   Object* number = args[0];
6784   RUNTIME_ASSERT(number->IsNumber());
6785 
6786   return isolate->heap()->NumberToString(number);
6787 }
6788 
6789 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToStringSkipCache)6790 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6791   SealHandleScope shs(isolate);
6792   ASSERT(args.length() == 1);
6793 
6794   Object* number = args[0];
6795   RUNTIME_ASSERT(number->IsNumber());
6796 
6797   return isolate->heap()->NumberToString(
6798       number, false, isolate->heap()->GetPretenureMode());
6799 }
6800 
6801 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToInteger)6802 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6803   SealHandleScope shs(isolate);
6804   ASSERT(args.length() == 1);
6805 
6806   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6807 
6808   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6809   if (number > 0 && number <= Smi::kMaxValue) {
6810     return Smi::FromInt(static_cast<int>(number));
6811   }
6812   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6813 }
6814 
6815 
6816 // ES6 draft 9.1.11
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToPositiveInteger)6817 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) {
6818   SealHandleScope shs(isolate);
6819   ASSERT(args.length() == 1);
6820 
6821   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6822 
6823   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6824   if (number > 0 && number <= Smi::kMaxValue) {
6825     return Smi::FromInt(static_cast<int>(number));
6826   }
6827   if (number <= 0) {
6828     return Smi::FromInt(0);
6829   }
6830   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6831 }
6832 
6833 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToIntegerMapMinusZero)6834 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6835   SealHandleScope shs(isolate);
6836   ASSERT(args.length() == 1);
6837 
6838   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6839 
6840   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6841   if (number > 0 && number <= Smi::kMaxValue) {
6842     return Smi::FromInt(static_cast<int>(number));
6843   }
6844 
6845   double double_value = DoubleToInteger(number);
6846   // Map both -0 and +0 to +0.
6847   if (double_value == 0) double_value = 0;
6848 
6849   return isolate->heap()->NumberFromDouble(double_value);
6850 }
6851 
6852 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToJSUint32)6853 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6854   SealHandleScope shs(isolate);
6855   ASSERT(args.length() == 1);
6856 
6857   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6858   return isolate->heap()->NumberFromUint32(number);
6859 }
6860 
6861 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToJSInt32)6862 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6863   SealHandleScope shs(isolate);
6864   ASSERT(args.length() == 1);
6865 
6866   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6867 
6868   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6869   if (number > 0 && number <= Smi::kMaxValue) {
6870     return Smi::FromInt(static_cast<int>(number));
6871   }
6872   return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6873 }
6874 
6875 
6876 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
6877 // a small integer.
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToSmi)6878 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6879   SealHandleScope shs(isolate);
6880   ASSERT(args.length() == 1);
6881 
6882   Object* obj = args[0];
6883   if (obj->IsSmi()) {
6884     return obj;
6885   }
6886   if (obj->IsHeapNumber()) {
6887     double value = HeapNumber::cast(obj)->value();
6888     int int_value = FastD2I(value);
6889     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6890       return Smi::FromInt(int_value);
6891     }
6892   }
6893   return isolate->heap()->nan_value();
6894 }
6895 
6896 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AllocateHeapNumber)6897 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6898   SealHandleScope shs(isolate);
6899   ASSERT(args.length() == 0);
6900   return isolate->heap()->AllocateHeapNumber(0);
6901 }
6902 
6903 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAdd)6904 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6905   SealHandleScope shs(isolate);
6906   ASSERT(args.length() == 2);
6907 
6908   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6909   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6910   return isolate->heap()->NumberFromDouble(x + y);
6911 }
6912 
6913 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberSub)6914 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6915   SealHandleScope shs(isolate);
6916   ASSERT(args.length() == 2);
6917 
6918   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6919   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6920   return isolate->heap()->NumberFromDouble(x - y);
6921 }
6922 
6923 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberMul)6924 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6925   SealHandleScope shs(isolate);
6926   ASSERT(args.length() == 2);
6927 
6928   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6929   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6930   return isolate->heap()->NumberFromDouble(x * y);
6931 }
6932 
6933 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberUnaryMinus)6934 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6935   SealHandleScope shs(isolate);
6936   ASSERT(args.length() == 1);
6937 
6938   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6939   return isolate->heap()->NumberFromDouble(-x);
6940 }
6941 
6942 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAlloc)6943 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6944   SealHandleScope shs(isolate);
6945   ASSERT(args.length() == 0);
6946 
6947   return isolate->heap()->NumberFromDouble(9876543210.0);
6948 }
6949 
6950 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberDiv)6951 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6952   SealHandleScope shs(isolate);
6953   ASSERT(args.length() == 2);
6954 
6955   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6956   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6957   return isolate->heap()->NumberFromDouble(x / y);
6958 }
6959 
6960 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberMod)6961 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6962   SealHandleScope shs(isolate);
6963   ASSERT(args.length() == 2);
6964 
6965   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6966   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6967 
6968   x = modulo(x, y);
6969   // NumberFromDouble may return a Smi instead of a Number object
6970   return isolate->heap()->NumberFromDouble(x);
6971 }
6972 
6973 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberImul)6974 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
6975   SealHandleScope shs(isolate);
6976   ASSERT(args.length() == 2);
6977 
6978   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6979   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6980   return isolate->heap()->NumberFromInt32(x * y);
6981 }
6982 
6983 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringAdd)6984 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6985   SealHandleScope shs(isolate);
6986   ASSERT(args.length() == 2);
6987   CONVERT_ARG_CHECKED(String, str1, 0);
6988   CONVERT_ARG_CHECKED(String, str2, 1);
6989   isolate->counters()->string_add_runtime()->Increment();
6990   return isolate->heap()->AllocateConsString(str1, str2);
6991 }
6992 
6993 
6994 template <typename sinkchar>
StringBuilderConcatHelper(String * special,sinkchar * sink,FixedArray * fixed_array,int array_length)6995 static inline void StringBuilderConcatHelper(String* special,
6996                                              sinkchar* sink,
6997                                              FixedArray* fixed_array,
6998                                              int array_length) {
6999   int position = 0;
7000   for (int i = 0; i < array_length; i++) {
7001     Object* element = fixed_array->get(i);
7002     if (element->IsSmi()) {
7003       // Smi encoding of position and length.
7004       int encoded_slice = Smi::cast(element)->value();
7005       int pos;
7006       int len;
7007       if (encoded_slice > 0) {
7008         // Position and length encoded in one smi.
7009         pos = StringBuilderSubstringPosition::decode(encoded_slice);
7010         len = StringBuilderSubstringLength::decode(encoded_slice);
7011       } else {
7012         // Position and length encoded in two smis.
7013         Object* obj = fixed_array->get(++i);
7014         ASSERT(obj->IsSmi());
7015         pos = Smi::cast(obj)->value();
7016         len = -encoded_slice;
7017       }
7018       String::WriteToFlat(special,
7019                           sink + position,
7020                           pos,
7021                           pos + len);
7022       position += len;
7023     } else {
7024       String* string = String::cast(element);
7025       int element_length = string->length();
7026       String::WriteToFlat(string, sink + position, 0, element_length);
7027       position += element_length;
7028     }
7029   }
7030 }
7031 
7032 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringBuilderConcat)7033 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
7034   HandleScope scope(isolate);
7035   ASSERT(args.length() == 3);
7036   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7037   if (!args[1]->IsSmi()) {
7038     isolate->context()->mark_out_of_memory();
7039     return Failure::OutOfMemoryException(0x14);
7040   }
7041   int array_length = args.smi_at(1);
7042   CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
7043 
7044   // This assumption is used by the slice encoding in one or two smis.
7045   ASSERT(Smi::kMaxValue >= String::kMaxLength);
7046 
7047   JSObject::EnsureCanContainHeapObjectElements(array);
7048 
7049   int special_length = special->length();
7050   if (!array->HasFastObjectElements()) {
7051     return isolate->Throw(isolate->heap()->illegal_argument_string());
7052   }
7053   FixedArray* fixed_array = FixedArray::cast(array->elements());
7054   if (fixed_array->length() < array_length) {
7055     array_length = fixed_array->length();
7056   }
7057 
7058   if (array_length == 0) {
7059     return isolate->heap()->empty_string();
7060   } else if (array_length == 1) {
7061     Object* first = fixed_array->get(0);
7062     if (first->IsString()) return first;
7063   }
7064 
7065   bool one_byte = special->HasOnlyOneByteChars();
7066   int position = 0;
7067   for (int i = 0; i < array_length; i++) {
7068     int increment = 0;
7069     Object* elt = fixed_array->get(i);
7070     if (elt->IsSmi()) {
7071       // Smi encoding of position and length.
7072       int smi_value = Smi::cast(elt)->value();
7073       int pos;
7074       int len;
7075       if (smi_value > 0) {
7076         // Position and length encoded in one smi.
7077         pos = StringBuilderSubstringPosition::decode(smi_value);
7078         len = StringBuilderSubstringLength::decode(smi_value);
7079       } else {
7080         // Position and length encoded in two smis.
7081         len = -smi_value;
7082         // Get the position and check that it is a positive smi.
7083         i++;
7084         if (i >= array_length) {
7085           return isolate->Throw(isolate->heap()->illegal_argument_string());
7086         }
7087         Object* next_smi = fixed_array->get(i);
7088         if (!next_smi->IsSmi()) {
7089           return isolate->Throw(isolate->heap()->illegal_argument_string());
7090         }
7091         pos = Smi::cast(next_smi)->value();
7092         if (pos < 0) {
7093           return isolate->Throw(isolate->heap()->illegal_argument_string());
7094         }
7095       }
7096       ASSERT(pos >= 0);
7097       ASSERT(len >= 0);
7098       if (pos > special_length || len > special_length - pos) {
7099         return isolate->Throw(isolate->heap()->illegal_argument_string());
7100       }
7101       increment = len;
7102     } else if (elt->IsString()) {
7103       String* element = String::cast(elt);
7104       int element_length = element->length();
7105       increment = element_length;
7106       if (one_byte && !element->HasOnlyOneByteChars()) {
7107         one_byte = false;
7108       }
7109     } else {
7110       ASSERT(!elt->IsTheHole());
7111       return isolate->Throw(isolate->heap()->illegal_argument_string());
7112     }
7113     if (increment > String::kMaxLength - position) {
7114       isolate->context()->mark_out_of_memory();
7115       return Failure::OutOfMemoryException(0x15);
7116     }
7117     position += increment;
7118   }
7119 
7120   int length = position;
7121   Object* object;
7122 
7123   if (one_byte) {
7124     { MaybeObject* maybe_object =
7125           isolate->heap()->AllocateRawOneByteString(length);
7126       if (!maybe_object->ToObject(&object)) return maybe_object;
7127     }
7128     SeqOneByteString* answer = SeqOneByteString::cast(object);
7129     StringBuilderConcatHelper(*special,
7130                               answer->GetChars(),
7131                               fixed_array,
7132                               array_length);
7133     return answer;
7134   } else {
7135     { MaybeObject* maybe_object =
7136           isolate->heap()->AllocateRawTwoByteString(length);
7137       if (!maybe_object->ToObject(&object)) return maybe_object;
7138     }
7139     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7140     StringBuilderConcatHelper(*special,
7141                               answer->GetChars(),
7142                               fixed_array,
7143                               array_length);
7144     return answer;
7145   }
7146 }
7147 
7148 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringBuilderJoin)7149 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
7150   SealHandleScope shs(isolate);
7151   ASSERT(args.length() == 3);
7152   CONVERT_ARG_CHECKED(JSArray, array, 0);
7153   if (!args[1]->IsSmi()) {
7154     isolate->context()->mark_out_of_memory();
7155     return Failure::OutOfMemoryException(0x16);
7156   }
7157   int array_length = args.smi_at(1);
7158   CONVERT_ARG_CHECKED(String, separator, 2);
7159 
7160   if (!array->HasFastObjectElements()) {
7161     return isolate->Throw(isolate->heap()->illegal_argument_string());
7162   }
7163   FixedArray* fixed_array = FixedArray::cast(array->elements());
7164   if (fixed_array->length() < array_length) {
7165     array_length = fixed_array->length();
7166   }
7167 
7168   if (array_length == 0) {
7169     return isolate->heap()->empty_string();
7170   } else if (array_length == 1) {
7171     Object* first = fixed_array->get(0);
7172     if (first->IsString()) return first;
7173   }
7174 
7175   int separator_length = separator->length();
7176   int max_nof_separators =
7177       (String::kMaxLength + separator_length - 1) / separator_length;
7178   if (max_nof_separators < (array_length - 1)) {
7179       isolate->context()->mark_out_of_memory();
7180       return Failure::OutOfMemoryException(0x17);
7181   }
7182   int length = (array_length - 1) * separator_length;
7183   for (int i = 0; i < array_length; i++) {
7184     Object* element_obj = fixed_array->get(i);
7185     if (!element_obj->IsString()) {
7186       // TODO(1161): handle this case.
7187       return isolate->Throw(isolate->heap()->illegal_argument_string());
7188     }
7189     String* element = String::cast(element_obj);
7190     int increment = element->length();
7191     if (increment > String::kMaxLength - length) {
7192       isolate->context()->mark_out_of_memory();
7193       return Failure::OutOfMemoryException(0x18);
7194     }
7195     length += increment;
7196   }
7197 
7198   Object* object;
7199   { MaybeObject* maybe_object =
7200         isolate->heap()->AllocateRawTwoByteString(length);
7201     if (!maybe_object->ToObject(&object)) return maybe_object;
7202   }
7203   SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7204 
7205   uc16* sink = answer->GetChars();
7206 #ifdef DEBUG
7207   uc16* end = sink + length;
7208 #endif
7209 
7210   String* first = String::cast(fixed_array->get(0));
7211   int first_length = first->length();
7212   String::WriteToFlat(first, sink, 0, first_length);
7213   sink += first_length;
7214 
7215   for (int i = 1; i < array_length; i++) {
7216     ASSERT(sink + separator_length <= end);
7217     String::WriteToFlat(separator, sink, 0, separator_length);
7218     sink += separator_length;
7219 
7220     String* element = String::cast(fixed_array->get(i));
7221     int element_length = element->length();
7222     ASSERT(sink + element_length <= end);
7223     String::WriteToFlat(element, sink, 0, element_length);
7224     sink += element_length;
7225   }
7226   ASSERT(sink == end);
7227 
7228   // Use %_FastAsciiArrayJoin instead.
7229   ASSERT(!answer->IsOneByteRepresentation());
7230   return answer;
7231 }
7232 
7233 template <typename Char>
JoinSparseArrayWithSeparator(FixedArray * elements,int elements_length,uint32_t array_length,String * separator,Vector<Char> buffer)7234 static void JoinSparseArrayWithSeparator(FixedArray* elements,
7235                                          int elements_length,
7236                                          uint32_t array_length,
7237                                          String* separator,
7238                                          Vector<Char> buffer) {
7239   int previous_separator_position = 0;
7240   int separator_length = separator->length();
7241   int cursor = 0;
7242   for (int i = 0; i < elements_length; i += 2) {
7243     int position = NumberToInt32(elements->get(i));
7244     String* string = String::cast(elements->get(i + 1));
7245     int string_length = string->length();
7246     if (string->length() > 0) {
7247       while (previous_separator_position < position) {
7248         String::WriteToFlat<Char>(separator, &buffer[cursor],
7249                                   0, separator_length);
7250         cursor += separator_length;
7251         previous_separator_position++;
7252       }
7253       String::WriteToFlat<Char>(string, &buffer[cursor],
7254                                 0, string_length);
7255       cursor += string->length();
7256     }
7257   }
7258   if (separator_length > 0) {
7259     // Array length must be representable as a signed 32-bit number,
7260     // otherwise the total string length would have been too large.
7261     ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
7262     int last_array_index = static_cast<int>(array_length - 1);
7263     while (previous_separator_position < last_array_index) {
7264       String::WriteToFlat<Char>(separator, &buffer[cursor],
7265                                 0, separator_length);
7266       cursor += separator_length;
7267       previous_separator_position++;
7268     }
7269   }
7270   ASSERT(cursor <= buffer.length());
7271 }
7272 
7273 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SparseJoinWithSeparator)7274 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
7275   SealHandleScope shs(isolate);
7276   ASSERT(args.length() == 3);
7277   CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
7278   RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7279   CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7280   CONVERT_ARG_CHECKED(String, separator, 2);
7281   // elements_array is fast-mode JSarray of alternating positions
7282   // (increasing order) and strings.
7283   // array_length is length of original array (used to add separators);
7284   // separator is string to put between elements. Assumed to be non-empty.
7285 
7286   // Find total length of join result.
7287   int string_length = 0;
7288   bool is_ascii = separator->IsOneByteRepresentation();
7289   int max_string_length;
7290   if (is_ascii) {
7291     max_string_length = SeqOneByteString::kMaxLength;
7292   } else {
7293     max_string_length = SeqTwoByteString::kMaxLength;
7294   }
7295   bool overflow = false;
7296   CONVERT_NUMBER_CHECKED(int, elements_length,
7297                          Int32, elements_array->length());
7298   RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7299   FixedArray* elements = FixedArray::cast(elements_array->elements());
7300   for (int i = 0; i < elements_length; i += 2) {
7301     RUNTIME_ASSERT(elements->get(i)->IsNumber());
7302     RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7303     String* string = String::cast(elements->get(i + 1));
7304     int length = string->length();
7305     if (is_ascii && !string->IsOneByteRepresentation()) {
7306       is_ascii = false;
7307       max_string_length = SeqTwoByteString::kMaxLength;
7308     }
7309     if (length > max_string_length ||
7310         max_string_length - length < string_length) {
7311       overflow = true;
7312       break;
7313     }
7314     string_length += length;
7315   }
7316   int separator_length = separator->length();
7317   if (!overflow && separator_length > 0) {
7318     if (array_length <= 0x7fffffffu) {
7319       int separator_count = static_cast<int>(array_length) - 1;
7320       int remaining_length = max_string_length - string_length;
7321       if ((remaining_length / separator_length) >= separator_count) {
7322         string_length += separator_length * (array_length - 1);
7323       } else {
7324         // Not room for the separators within the maximal string length.
7325         overflow = true;
7326       }
7327     } else {
7328       // Nonempty separator and at least 2^31-1 separators necessary
7329       // means that the string is too large to create.
7330       STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7331       overflow = true;
7332     }
7333   }
7334   if (overflow) {
7335     // Throw OutOfMemory exception for creating too large a string.
7336     V8::FatalProcessOutOfMemory("Array join result too large.");
7337   }
7338 
7339   if (is_ascii) {
7340     MaybeObject* result_allocation =
7341         isolate->heap()->AllocateRawOneByteString(string_length);
7342     if (result_allocation->IsFailure()) return result_allocation;
7343     SeqOneByteString* result_string =
7344         SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
7345     JoinSparseArrayWithSeparator<uint8_t>(elements,
7346                                           elements_length,
7347                                           array_length,
7348                                           separator,
7349                                           Vector<uint8_t>(
7350                                               result_string->GetChars(),
7351                                               string_length));
7352     return result_string;
7353   } else {
7354     MaybeObject* result_allocation =
7355         isolate->heap()->AllocateRawTwoByteString(string_length);
7356     if (result_allocation->IsFailure()) return result_allocation;
7357     SeqTwoByteString* result_string =
7358         SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7359     JoinSparseArrayWithSeparator<uc16>(elements,
7360                                        elements_length,
7361                                        array_length,
7362                                        separator,
7363                                        Vector<uc16>(result_string->GetChars(),
7364                                                     string_length));
7365     return result_string;
7366   }
7367 }
7368 
7369 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberOr)7370 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7371   SealHandleScope shs(isolate);
7372   ASSERT(args.length() == 2);
7373 
7374   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7375   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7376   return isolate->heap()->NumberFromInt32(x | y);
7377 }
7378 
7379 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAnd)7380 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7381   SealHandleScope shs(isolate);
7382   ASSERT(args.length() == 2);
7383 
7384   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7385   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7386   return isolate->heap()->NumberFromInt32(x & y);
7387 }
7388 
7389 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberXor)7390 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7391   SealHandleScope shs(isolate);
7392   ASSERT(args.length() == 2);
7393 
7394   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7395   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7396   return isolate->heap()->NumberFromInt32(x ^ y);
7397 }
7398 
7399 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberShl)7400 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7401   SealHandleScope shs(isolate);
7402   ASSERT(args.length() == 2);
7403 
7404   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7405   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7406   return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7407 }
7408 
7409 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberShr)7410 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7411   SealHandleScope shs(isolate);
7412   ASSERT(args.length() == 2);
7413 
7414   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7415   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7416   return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7417 }
7418 
7419 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberSar)7420 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7421   SealHandleScope shs(isolate);
7422   ASSERT(args.length() == 2);
7423 
7424   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7425   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7426   return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7427 }
7428 
7429 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberEquals)7430 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7431   SealHandleScope shs(isolate);
7432   ASSERT(args.length() == 2);
7433 
7434   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7435   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7436   if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7437   if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7438   if (x == y) return Smi::FromInt(EQUAL);
7439   Object* result;
7440   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7441     result = Smi::FromInt(EQUAL);
7442   } else {
7443     result = Smi::FromInt(NOT_EQUAL);
7444   }
7445   return result;
7446 }
7447 
7448 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringEquals)7449 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7450   SealHandleScope shs(isolate);
7451   ASSERT(args.length() == 2);
7452 
7453   CONVERT_ARG_CHECKED(String, x, 0);
7454   CONVERT_ARG_CHECKED(String, y, 1);
7455 
7456   bool not_equal = !x->Equals(y);
7457   // This is slightly convoluted because the value that signifies
7458   // equality is 0 and inequality is 1 so we have to negate the result
7459   // from String::Equals.
7460   ASSERT(not_equal == 0 || not_equal == 1);
7461   STATIC_CHECK(EQUAL == 0);
7462   STATIC_CHECK(NOT_EQUAL == 1);
7463   return Smi::FromInt(not_equal);
7464 }
7465 
7466 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberCompare)7467 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7468   SealHandleScope shs(isolate);
7469   ASSERT(args.length() == 3);
7470 
7471   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7472   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7473   if (std::isnan(x) || std::isnan(y)) return args[2];
7474   if (x == y) return Smi::FromInt(EQUAL);
7475   if (isless(x, y)) return Smi::FromInt(LESS);
7476   return Smi::FromInt(GREATER);
7477 }
7478 
7479 
7480 // Compare two Smis as if they were converted to strings and then
7481 // compared lexicographically.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SmiLexicographicCompare)7482 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7483   SealHandleScope shs(isolate);
7484   ASSERT(args.length() == 2);
7485   CONVERT_SMI_ARG_CHECKED(x_value, 0);
7486   CONVERT_SMI_ARG_CHECKED(y_value, 1);
7487 
7488   // If the integers are equal so are the string representations.
7489   if (x_value == y_value) return Smi::FromInt(EQUAL);
7490 
7491   // If one of the integers is zero the normal integer order is the
7492   // same as the lexicographic order of the string representations.
7493   if (x_value == 0 || y_value == 0)
7494     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7495 
7496   // If only one of the integers is negative the negative number is
7497   // smallest because the char code of '-' is less than the char code
7498   // of any digit.  Otherwise, we make both values positive.
7499 
7500   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7501   // architectures using 32-bit Smis.
7502   uint32_t x_scaled = x_value;
7503   uint32_t y_scaled = y_value;
7504   if (x_value < 0 || y_value < 0) {
7505     if (y_value >= 0) return Smi::FromInt(LESS);
7506     if (x_value >= 0) return Smi::FromInt(GREATER);
7507     x_scaled = -x_value;
7508     y_scaled = -y_value;
7509   }
7510 
7511   static const uint32_t kPowersOf10[] = {
7512     1, 10, 100, 1000, 10*1000, 100*1000,
7513     1000*1000, 10*1000*1000, 100*1000*1000,
7514     1000*1000*1000
7515   };
7516 
7517   // If the integers have the same number of decimal digits they can be
7518   // compared directly as the numeric order is the same as the
7519   // lexicographic order.  If one integer has fewer digits, it is scaled
7520   // by some power of 10 to have the same number of digits as the longer
7521   // integer.  If the scaled integers are equal it means the shorter
7522   // integer comes first in the lexicographic order.
7523 
7524   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7525   int x_log2 = IntegerLog2(x_scaled);
7526   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7527   x_log10 -= x_scaled < kPowersOf10[x_log10];
7528 
7529   int y_log2 = IntegerLog2(y_scaled);
7530   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7531   y_log10 -= y_scaled < kPowersOf10[y_log10];
7532 
7533   int tie = EQUAL;
7534 
7535   if (x_log10 < y_log10) {
7536     // X has fewer digits.  We would like to simply scale up X but that
7537     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7538     // be scaled up to 9_000_000_000. So we scale up by the next
7539     // smallest power and scale down Y to drop one digit. It is OK to
7540     // drop one digit from the longer integer since the final digit is
7541     // past the length of the shorter integer.
7542     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7543     y_scaled /= 10;
7544     tie = LESS;
7545   } else if (y_log10 < x_log10) {
7546     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7547     x_scaled /= 10;
7548     tie = GREATER;
7549   }
7550 
7551   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7552   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7553   return Smi::FromInt(tie);
7554 }
7555 
7556 
StringCharacterStreamCompare(RuntimeState * state,String * x,String * y)7557 static Object* StringCharacterStreamCompare(RuntimeState* state,
7558                                         String* x,
7559                                         String* y) {
7560   StringCharacterStream stream_x(x, state->string_iterator_compare_x());
7561   StringCharacterStream stream_y(y, state->string_iterator_compare_y());
7562   while (stream_x.HasMore() && stream_y.HasMore()) {
7563     int d = stream_x.GetNext() - stream_y.GetNext();
7564     if (d < 0) return Smi::FromInt(LESS);
7565     else if (d > 0) return Smi::FromInt(GREATER);
7566   }
7567 
7568   // x is (non-trivial) prefix of y:
7569   if (stream_y.HasMore()) return Smi::FromInt(LESS);
7570   // y is prefix of x:
7571   return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
7572 }
7573 
7574 
FlatStringCompare(String * x,String * y)7575 static Object* FlatStringCompare(String* x, String* y) {
7576   ASSERT(x->IsFlat());
7577   ASSERT(y->IsFlat());
7578   Object* equal_prefix_result = Smi::FromInt(EQUAL);
7579   int prefix_length = x->length();
7580   if (y->length() < prefix_length) {
7581     prefix_length = y->length();
7582     equal_prefix_result = Smi::FromInt(GREATER);
7583   } else if (y->length() > prefix_length) {
7584     equal_prefix_result = Smi::FromInt(LESS);
7585   }
7586   int r;
7587   DisallowHeapAllocation no_gc;
7588   String::FlatContent x_content = x->GetFlatContent();
7589   String::FlatContent y_content = y->GetFlatContent();
7590   if (x_content.IsAscii()) {
7591     Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7592     if (y_content.IsAscii()) {
7593       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7594       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7595     } else {
7596       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7597       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7598     }
7599   } else {
7600     Vector<const uc16> x_chars = x_content.ToUC16Vector();
7601     if (y_content.IsAscii()) {
7602       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7603       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7604     } else {
7605       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7606       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7607     }
7608   }
7609   Object* result;
7610   if (r == 0) {
7611     result = equal_prefix_result;
7612   } else {
7613     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7614   }
7615   ASSERT(result ==
7616       StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
7617   return result;
7618 }
7619 
7620 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringCompare)7621 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7622   SealHandleScope shs(isolate);
7623   ASSERT(args.length() == 2);
7624 
7625   CONVERT_ARG_CHECKED(String, x, 0);
7626   CONVERT_ARG_CHECKED(String, y, 1);
7627 
7628   isolate->counters()->string_compare_runtime()->Increment();
7629 
7630   // A few fast case tests before we flatten.
7631   if (x == y) return Smi::FromInt(EQUAL);
7632   if (y->length() == 0) {
7633     if (x->length() == 0) return Smi::FromInt(EQUAL);
7634     return Smi::FromInt(GREATER);
7635   } else if (x->length() == 0) {
7636     return Smi::FromInt(LESS);
7637   }
7638 
7639   int d = x->Get(0) - y->Get(0);
7640   if (d < 0) return Smi::FromInt(LESS);
7641   else if (d > 0) return Smi::FromInt(GREATER);
7642 
7643   Object* obj;
7644   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7645     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7646   }
7647   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7648     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7649   }
7650 
7651   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7652       : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
7653 }
7654 
7655 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_acos)7656 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7657   SealHandleScope shs(isolate);
7658   ASSERT(args.length() == 1);
7659   isolate->counters()->math_acos()->Increment();
7660 
7661   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7662   return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7663 }
7664 
7665 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_asin)7666 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7667   SealHandleScope shs(isolate);
7668   ASSERT(args.length() == 1);
7669   isolate->counters()->math_asin()->Increment();
7670 
7671   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7672   return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7673 }
7674 
7675 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_atan)7676 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7677   SealHandleScope shs(isolate);
7678   ASSERT(args.length() == 1);
7679   isolate->counters()->math_atan()->Increment();
7680 
7681   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7682   return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7683 }
7684 
7685 
7686 static const double kPiDividedBy4 = 0.78539816339744830962;
7687 
7688 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_atan2)7689 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7690   SealHandleScope shs(isolate);
7691   ASSERT(args.length() == 2);
7692   isolate->counters()->math_atan2()->Increment();
7693 
7694   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7695   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7696   double result;
7697   if (std::isinf(x) && std::isinf(y)) {
7698     // Make sure that the result in case of two infinite arguments
7699     // is a multiple of Pi / 4. The sign of the result is determined
7700     // by the first argument (x) and the sign of the second argument
7701     // determines the multiplier: one or three.
7702     int multiplier = (x < 0) ? -1 : 1;
7703     if (y < 0) multiplier *= 3;
7704     result = multiplier * kPiDividedBy4;
7705   } else {
7706     result = atan2(x, y);
7707   }
7708   return isolate->heap()->AllocateHeapNumber(result);
7709 }
7710 
7711 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_cos)7712 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7713   SealHandleScope shs(isolate);
7714   ASSERT(args.length() == 1);
7715   isolate->counters()->math_cos()->Increment();
7716 
7717   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7718   return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7719 }
7720 
7721 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_exp)7722 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7723   SealHandleScope shs(isolate);
7724   ASSERT(args.length() == 1);
7725   isolate->counters()->math_exp()->Increment();
7726 
7727   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7728   lazily_initialize_fast_exp();
7729   return isolate->heap()->NumberFromDouble(fast_exp(x));
7730 }
7731 
7732 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_floor)7733 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7734   SealHandleScope shs(isolate);
7735   ASSERT(args.length() == 1);
7736   isolate->counters()->math_floor()->Increment();
7737 
7738   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7739   return isolate->heap()->NumberFromDouble(floor(x));
7740 }
7741 
7742 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_log)7743 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7744   SealHandleScope shs(isolate);
7745   ASSERT(args.length() == 1);
7746   isolate->counters()->math_log()->Increment();
7747 
7748   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7749   return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7750 }
7751 
7752 
7753 // Slow version of Math.pow.  We check for fast paths for special cases.
7754 // Used if SSE2/VFP3 is not available.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_pow)7755 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7756   SealHandleScope shs(isolate);
7757   ASSERT(args.length() == 2);
7758   isolate->counters()->math_pow()->Increment();
7759 
7760   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7761 
7762   // If the second argument is a smi, it is much faster to call the
7763   // custom powi() function than the generic pow().
7764   if (args[1]->IsSmi()) {
7765     int y = args.smi_at(1);
7766     return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7767   }
7768 
7769   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7770   double result = power_helper(x, y);
7771   if (std::isnan(result)) return isolate->heap()->nan_value();
7772   return isolate->heap()->AllocateHeapNumber(result);
7773 }
7774 
7775 
7776 // Fast version of Math.pow if we know that y is not an integer and y is not
7777 // -0.5 or 0.5.  Used as slow case from full codegen.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_pow_cfunction)7778 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7779   SealHandleScope shs(isolate);
7780   ASSERT(args.length() == 2);
7781   isolate->counters()->math_pow()->Increment();
7782 
7783   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7784   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7785   if (y == 0) {
7786     return Smi::FromInt(1);
7787   } else {
7788     double result = power_double_double(x, y);
7789     if (std::isnan(result)) return isolate->heap()->nan_value();
7790     return isolate->heap()->AllocateHeapNumber(result);
7791   }
7792 }
7793 
7794 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RoundNumber)7795 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7796   SealHandleScope shs(isolate);
7797   ASSERT(args.length() == 1);
7798   isolate->counters()->math_round()->Increment();
7799 
7800   if (!args[0]->IsHeapNumber()) {
7801     // Must be smi. Return the argument unchanged for all the other types
7802     // to make fuzz-natives test happy.
7803     return args[0];
7804   }
7805 
7806   HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7807 
7808   double value = number->value();
7809   int exponent = number->get_exponent();
7810   int sign = number->get_sign();
7811 
7812   if (exponent < -1) {
7813     // Number in range ]-0.5..0.5[. These always round to +/-zero.
7814     if (sign) return isolate->heap()->minus_zero_value();
7815     return Smi::FromInt(0);
7816   }
7817 
7818   // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7819   // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7820   // argument holds for 32-bit smis).
7821   if (!sign && exponent < kSmiValueSize - 2) {
7822     return Smi::FromInt(static_cast<int>(value + 0.5));
7823   }
7824 
7825   // If the magnitude is big enough, there's no place for fraction part. If we
7826   // try to add 0.5 to this number, 1.0 will be added instead.
7827   if (exponent >= 52) {
7828     return number;
7829   }
7830 
7831   if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7832 
7833   // Do not call NumberFromDouble() to avoid extra checks.
7834   return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7835 }
7836 
7837 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_sin)7838 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7839   SealHandleScope shs(isolate);
7840   ASSERT(args.length() == 1);
7841   isolate->counters()->math_sin()->Increment();
7842 
7843   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7844   return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7845 }
7846 
7847 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_sqrt)7848 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7849   SealHandleScope shs(isolate);
7850   ASSERT(args.length() == 1);
7851   isolate->counters()->math_sqrt()->Increment();
7852 
7853   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7854   return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7855 }
7856 
7857 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_tan)7858 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7859   SealHandleScope shs(isolate);
7860   ASSERT(args.length() == 1);
7861   isolate->counters()->math_tan()->Increment();
7862 
7863   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7864   return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7865 }
7866 
7867 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateMakeDay)7868 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7869   SealHandleScope shs(isolate);
7870   ASSERT(args.length() == 2);
7871 
7872   CONVERT_SMI_ARG_CHECKED(year, 0);
7873   CONVERT_SMI_ARG_CHECKED(month, 1);
7874 
7875   return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7876 }
7877 
7878 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateSetValue)7879 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7880   HandleScope scope(isolate);
7881   ASSERT(args.length() == 3);
7882 
7883   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7884   CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7885   CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7886 
7887   DateCache* date_cache = isolate->date_cache();
7888 
7889   Object* value = NULL;
7890   bool is_value_nan = false;
7891   if (std::isnan(time)) {
7892     value = isolate->heap()->nan_value();
7893     is_value_nan = true;
7894   } else if (!is_utc &&
7895              (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7896               time > DateCache::kMaxTimeBeforeUTCInMs)) {
7897     value = isolate->heap()->nan_value();
7898     is_value_nan = true;
7899   } else {
7900     time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7901     if (time < -DateCache::kMaxTimeInMs ||
7902         time > DateCache::kMaxTimeInMs) {
7903       value = isolate->heap()->nan_value();
7904       is_value_nan = true;
7905     } else  {
7906       MaybeObject* maybe_result =
7907           isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7908       if (!maybe_result->ToObject(&value)) return maybe_result;
7909     }
7910   }
7911   date->SetValue(value, is_value_nan);
7912   return value;
7913 }
7914 
7915 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewArgumentsFast)7916 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7917   HandleScope scope(isolate);
7918   ASSERT(args.length() == 3);
7919 
7920   Handle<JSFunction> callee = args.at<JSFunction>(0);
7921   Object** parameters = reinterpret_cast<Object**>(args[1]);
7922   const int argument_count = Smi::cast(args[2])->value();
7923 
7924   Handle<JSObject> result =
7925       isolate->factory()->NewArgumentsObject(callee, argument_count);
7926   // Allocate the elements if needed.
7927   int parameter_count = callee->shared()->formal_parameter_count();
7928   if (argument_count > 0) {
7929     if (parameter_count > 0) {
7930       int mapped_count = Min(argument_count, parameter_count);
7931       Handle<FixedArray> parameter_map =
7932           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7933       parameter_map->set_map(
7934           isolate->heap()->non_strict_arguments_elements_map());
7935 
7936       Handle<Map> old_map(result->map());
7937       Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
7938       new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7939 
7940       result->set_map(*new_map);
7941       result->set_elements(*parameter_map);
7942 
7943       // Store the context and the arguments array at the beginning of the
7944       // parameter map.
7945       Handle<Context> context(isolate->context());
7946       Handle<FixedArray> arguments =
7947           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7948       parameter_map->set(0, *context);
7949       parameter_map->set(1, *arguments);
7950 
7951       // Loop over the actual parameters backwards.
7952       int index = argument_count - 1;
7953       while (index >= mapped_count) {
7954         // These go directly in the arguments array and have no
7955         // corresponding slot in the parameter map.
7956         arguments->set(index, *(parameters - index - 1));
7957         --index;
7958       }
7959 
7960       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7961       while (index >= 0) {
7962         // Detect duplicate names to the right in the parameter list.
7963         Handle<String> name(scope_info->ParameterName(index));
7964         int context_local_count = scope_info->ContextLocalCount();
7965         bool duplicate = false;
7966         for (int j = index + 1; j < parameter_count; ++j) {
7967           if (scope_info->ParameterName(j) == *name) {
7968             duplicate = true;
7969             break;
7970           }
7971         }
7972 
7973         if (duplicate) {
7974           // This goes directly in the arguments array with a hole in the
7975           // parameter map.
7976           arguments->set(index, *(parameters - index - 1));
7977           parameter_map->set_the_hole(index + 2);
7978         } else {
7979           // The context index goes in the parameter map with a hole in the
7980           // arguments array.
7981           int context_index = -1;
7982           for (int j = 0; j < context_local_count; ++j) {
7983             if (scope_info->ContextLocalName(j) == *name) {
7984               context_index = j;
7985               break;
7986             }
7987           }
7988           ASSERT(context_index >= 0);
7989           arguments->set_the_hole(index);
7990           parameter_map->set(index + 2, Smi::FromInt(
7991               Context::MIN_CONTEXT_SLOTS + context_index));
7992         }
7993 
7994         --index;
7995       }
7996     } else {
7997       // If there is no aliasing, the arguments object elements are not
7998       // special in any way.
7999       Handle<FixedArray> elements =
8000           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8001       result->set_elements(*elements);
8002       for (int i = 0; i < argument_count; ++i) {
8003         elements->set(i, *(parameters - i - 1));
8004       }
8005     }
8006   }
8007   return *result;
8008 }
8009 
8010 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewStrictArgumentsFast)8011 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
8012   SealHandleScope shs(isolate);
8013   ASSERT(args.length() == 3);
8014 
8015   JSFunction* callee = JSFunction::cast(args[0]);
8016   Object** parameters = reinterpret_cast<Object**>(args[1]);
8017   const int length = args.smi_at(2);
8018 
8019   Object* result;
8020   { MaybeObject* maybe_result =
8021         isolate->heap()->AllocateArgumentsObject(callee, length);
8022     if (!maybe_result->ToObject(&result)) return maybe_result;
8023   }
8024   // Allocate the elements if needed.
8025   if (length > 0) {
8026     // Allocate the fixed array.
8027     FixedArray* array;
8028     { MaybeObject* maybe_obj =
8029           isolate->heap()->AllocateUninitializedFixedArray(length);
8030       if (!maybe_obj->To(&array)) return maybe_obj;
8031     }
8032 
8033     DisallowHeapAllocation no_gc;
8034     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
8035     for (int i = 0; i < length; i++) {
8036       array->set(i, *--parameters, mode);
8037     }
8038     JSObject::cast(result)->set_elements(array);
8039   }
8040   return result;
8041 }
8042 
8043 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewClosureFromStubFailure)8044 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosureFromStubFailure) {
8045   HandleScope scope(isolate);
8046   ASSERT(args.length() == 1);
8047   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
8048   Handle<Context> context(isolate->context());
8049   PretenureFlag pretenure_flag = NOT_TENURED;
8050   Handle<JSFunction> result =
8051       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8052                                                             context,
8053                                                             pretenure_flag);
8054   return *result;
8055 }
8056 
8057 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewClosure)8058 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
8059   HandleScope scope(isolate);
8060   ASSERT(args.length() == 3);
8061   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8062   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
8063   CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
8064 
8065   // The caller ensures that we pretenure closures that are assigned
8066   // directly to properties.
8067   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
8068   Handle<JSFunction> result =
8069       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8070                                                             context,
8071                                                             pretenure_flag);
8072   return *result;
8073 }
8074 
8075 
8076 // Find the arguments of the JavaScript function invocation that called
8077 // into C++ code. Collect these in a newly allocated array of handles (possibly
8078 // prefixed by a number of empty handles).
GetCallerArguments(Isolate * isolate,int prefix_argc,int * total_argc)8079 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
8080     Isolate* isolate,
8081     int prefix_argc,
8082     int* total_argc) {
8083   // Find frame containing arguments passed to the caller.
8084   JavaScriptFrameIterator it(isolate);
8085   JavaScriptFrame* frame = it.frame();
8086   List<JSFunction*> functions(2);
8087   frame->GetFunctions(&functions);
8088   if (functions.length() > 1) {
8089     int inlined_jsframe_index = functions.length() - 1;
8090     JSFunction* inlined_function = functions[inlined_jsframe_index];
8091     Vector<SlotRef> args_slots =
8092         SlotRef::ComputeSlotMappingForArguments(
8093             frame,
8094             inlined_jsframe_index,
8095             inlined_function->shared()->formal_parameter_count());
8096 
8097     int args_count = args_slots.length();
8098 
8099     *total_argc = prefix_argc + args_count;
8100     SmartArrayPointer<Handle<Object> > param_data(
8101         NewArray<Handle<Object> >(*total_argc));
8102     for (int i = 0; i < args_count; i++) {
8103       Handle<Object> val = args_slots[i].GetValue(isolate);
8104       param_data[prefix_argc + i] = val;
8105     }
8106 
8107     args_slots.Dispose();
8108 
8109     return param_data;
8110   } else {
8111     it.AdvanceToArgumentsFrame();
8112     frame = it.frame();
8113     int args_count = frame->ComputeParametersCount();
8114 
8115     *total_argc = prefix_argc + args_count;
8116     SmartArrayPointer<Handle<Object> > param_data(
8117         NewArray<Handle<Object> >(*total_argc));
8118     for (int i = 0; i < args_count; i++) {
8119       Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
8120       param_data[prefix_argc + i] = val;
8121     }
8122     return param_data;
8123   }
8124 }
8125 
8126 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionBindArguments)8127 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
8128   HandleScope scope(isolate);
8129   ASSERT(args.length() == 4);
8130   CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
8131   RUNTIME_ASSERT(args[3]->IsNumber());
8132   Handle<Object> bindee = args.at<Object>(1);
8133 
8134   // TODO(lrn): Create bound function in C++ code from premade shared info.
8135   bound_function->shared()->set_bound(true);
8136   // Get all arguments of calling function (Function.prototype.bind).
8137   int argc = 0;
8138   SmartArrayPointer<Handle<Object> > arguments =
8139       GetCallerArguments(isolate, 0, &argc);
8140   // Don't count the this-arg.
8141   if (argc > 0) {
8142     ASSERT(*arguments[0] == args[2]);
8143     argc--;
8144   } else {
8145     ASSERT(args[2]->IsUndefined());
8146   }
8147   // Initialize array of bindings (function, this, and any existing arguments
8148   // if the function was already bound).
8149   Handle<FixedArray> new_bindings;
8150   int i;
8151   if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8152     Handle<FixedArray> old_bindings(
8153         JSFunction::cast(*bindee)->function_bindings());
8154     new_bindings =
8155         isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8156     bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8157                             isolate);
8158     i = 0;
8159     for (int n = old_bindings->length(); i < n; i++) {
8160       new_bindings->set(i, old_bindings->get(i));
8161     }
8162   } else {
8163     int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8164     new_bindings = isolate->factory()->NewFixedArray(array_size);
8165     new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8166     new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
8167     i = 2;
8168   }
8169   // Copy arguments, skipping the first which is "this_arg".
8170   for (int j = 0; j < argc; j++, i++) {
8171     new_bindings->set(i, *arguments[j + 1]);
8172   }
8173   new_bindings->set_map_no_write_barrier(
8174       isolate->heap()->fixed_cow_array_map());
8175   bound_function->set_function_bindings(*new_bindings);
8176 
8177   // Update length.
8178   Handle<String> length_string = isolate->factory()->length_string();
8179   Handle<Object> new_length(args.at<Object>(3));
8180   PropertyAttributes attr =
8181       static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8182   ForceSetProperty(bound_function, length_string, new_length, attr);
8183   return *bound_function;
8184 }
8185 
8186 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BoundFunctionGetBindings)8187 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
8188   HandleScope handles(isolate);
8189   ASSERT(args.length() == 1);
8190   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8191   if (callable->IsJSFunction()) {
8192     Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8193     if (function->shared()->bound()) {
8194       Handle<FixedArray> bindings(function->function_bindings());
8195       ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8196       return *isolate->factory()->NewJSArrayWithElements(bindings);
8197     }
8198   }
8199   return isolate->heap()->undefined_value();
8200 }
8201 
8202 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewObjectFromBound)8203 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
8204   HandleScope scope(isolate);
8205   ASSERT(args.length() == 1);
8206   // First argument is a function to use as a constructor.
8207   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8208   RUNTIME_ASSERT(function->shared()->bound());
8209 
8210   // The argument is a bound function. Extract its bound arguments
8211   // and callable.
8212   Handle<FixedArray> bound_args =
8213       Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8214   int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8215   Handle<Object> bound_function(
8216       JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
8217       isolate);
8218   ASSERT(!bound_function->IsJSFunction() ||
8219          !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8220 
8221   int total_argc = 0;
8222   SmartArrayPointer<Handle<Object> > param_data =
8223       GetCallerArguments(isolate, bound_argc, &total_argc);
8224   for (int i = 0; i < bound_argc; i++) {
8225     param_data[i] = Handle<Object>(bound_args->get(
8226         JSFunction::kBoundArgumentsStartIndex + i), isolate);
8227   }
8228 
8229   if (!bound_function->IsJSFunction()) {
8230     bool exception_thrown;
8231     bound_function = Execution::TryGetConstructorDelegate(isolate,
8232                                                           bound_function,
8233                                                           &exception_thrown);
8234     if (exception_thrown) return Failure::Exception();
8235   }
8236   ASSERT(bound_function->IsJSFunction());
8237 
8238   bool exception = false;
8239   Handle<Object> result =
8240       Execution::New(Handle<JSFunction>::cast(bound_function),
8241                      total_argc, *param_data, &exception);
8242   if (exception) {
8243     return Failure::Exception();
8244   }
8245   ASSERT(!result.is_null());
8246   return *result;
8247 }
8248 
8249 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewObject)8250 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
8251   HandleScope scope(isolate);
8252   ASSERT(args.length() == 1);
8253 
8254   Handle<Object> constructor = args.at<Object>(0);
8255 
8256   // If the constructor isn't a proper function we throw a type error.
8257   if (!constructor->IsJSFunction()) {
8258     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8259     Handle<Object> type_error =
8260         isolate->factory()->NewTypeError("not_constructor", arguments);
8261     return isolate->Throw(*type_error);
8262   }
8263 
8264   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8265 
8266   // If function should not have prototype, construction is not allowed. In this
8267   // case generated code bailouts here, since function has no initial_map.
8268   if (!function->should_have_prototype() && !function->shared()->bound()) {
8269     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8270     Handle<Object> type_error =
8271         isolate->factory()->NewTypeError("not_constructor", arguments);
8272     return isolate->Throw(*type_error);
8273   }
8274 
8275 #ifdef ENABLE_DEBUGGER_SUPPORT
8276   Debug* debug = isolate->debug();
8277   // Handle stepping into constructors if step into is active.
8278   if (debug->StepInActive()) {
8279     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8280   }
8281 #endif
8282 
8283   if (function->has_initial_map()) {
8284     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8285       // The 'Function' function ignores the receiver object when
8286       // called using 'new' and creates a new JSFunction object that
8287       // is returned.  The receiver object is only used for error
8288       // reporting if an error occurs when constructing the new
8289       // JSFunction. Factory::NewJSObject() should not be used to
8290       // allocate JSFunctions since it does not properly initialize
8291       // the shared part of the function. Since the receiver is
8292       // ignored anyway, we use the global object as the receiver
8293       // instead of a new JSFunction object. This way, errors are
8294       // reported the same way whether or not 'Function' is called
8295       // using 'new'.
8296       return isolate->context()->global_object();
8297     }
8298   }
8299 
8300   // The function should be compiled for the optimization hints to be
8301   // available.
8302   JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
8303 
8304   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8305   if (!function->has_initial_map() &&
8306       shared->IsInobjectSlackTrackingInProgress()) {
8307     // The tracking is already in progress for another function. We can only
8308     // track one initial_map at a time, so we force the completion before the
8309     // function is called as a constructor for the first time.
8310     shared->CompleteInobjectSlackTracking();
8311   }
8312 
8313   Handle<JSObject> result = isolate->factory()->NewJSObject(function);
8314   RETURN_IF_EMPTY_HANDLE(isolate, result);
8315 
8316   isolate->counters()->constructed_objects()->Increment();
8317   isolate->counters()->constructed_objects_runtime()->Increment();
8318 
8319   return *result;
8320 }
8321 
8322 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FinalizeInstanceSize)8323 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8324   HandleScope scope(isolate);
8325   ASSERT(args.length() == 1);
8326 
8327   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8328   function->shared()->CompleteInobjectSlackTracking();
8329 
8330   return isolate->heap()->undefined_value();
8331 }
8332 
8333 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LazyCompile)8334 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8335   HandleScope scope(isolate);
8336   ASSERT(args.length() == 1);
8337 
8338   Handle<JSFunction> function = args.at<JSFunction>(0);
8339 #ifdef DEBUG
8340   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8341     PrintF("[lazy: ");
8342     function->PrintName();
8343     PrintF("]\n");
8344   }
8345 #endif
8346 
8347   // Compile the target function.
8348   ASSERT(!function->is_compiled());
8349   if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8350     return Failure::Exception();
8351   }
8352 
8353   // All done. Return the compiled code.
8354   ASSERT(function->is_compiled());
8355   return function->code();
8356 }
8357 
8358 
AllowOptimization(Isolate * isolate,Handle<JSFunction> function)8359 bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
8360   // If the function is not compiled ignore the lazy
8361   // recompilation. This can happen if the debugger is activated and
8362   // the function is returned to the not compiled state.
8363   if (!function->shared()->is_compiled()) return false;
8364 
8365   // If the function is not optimizable or debugger is active continue using the
8366   // code from the full compiler.
8367   if (!isolate->use_crankshaft() ||
8368       function->shared()->optimization_disabled() ||
8369       isolate->DebuggerHasBreakPoints()) {
8370     if (FLAG_trace_opt) {
8371       PrintF("[failed to optimize ");
8372       function->PrintName();
8373       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8374           function->shared()->optimization_disabled() ? "F" : "T",
8375           isolate->DebuggerHasBreakPoints() ? "T" : "F");
8376     }
8377     return false;
8378   }
8379   return true;
8380 }
8381 
8382 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LazyRecompile)8383 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8384   HandleScope scope(isolate);
8385   ASSERT(args.length() == 1);
8386   Handle<JSFunction> function = args.at<JSFunction>(0);
8387 
8388   if (!AllowOptimization(isolate, function)) {
8389     function->ReplaceCode(function->shared()->code());
8390     return function->code();
8391   }
8392   function->shared()->code()->set_profiler_ticks(0);
8393   if (JSFunction::CompileOptimized(function, CLEAR_EXCEPTION)) {
8394     return function->code();
8395   }
8396   if (FLAG_trace_opt) {
8397     PrintF("[failed to optimize ");
8398     function->PrintName();
8399     PrintF(": optimized compilation failed]\n");
8400   }
8401   function->ReplaceCode(function->shared()->code());
8402   return function->code();
8403 }
8404 
8405 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ConcurrentRecompile)8406 RUNTIME_FUNCTION(MaybeObject*, Runtime_ConcurrentRecompile) {
8407   HandleScope handle_scope(isolate);
8408   ASSERT(args.length() == 1);
8409   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8410   if (!AllowOptimization(isolate, function)) {
8411     function->ReplaceCode(function->shared()->code());
8412     return isolate->heap()->undefined_value();
8413   }
8414   function->shared()->code()->set_profiler_ticks(0);
8415   ASSERT(isolate->concurrent_recompilation_enabled());
8416   if (!Compiler::RecompileConcurrent(function)) {
8417     function->ReplaceCode(function->shared()->code());
8418   }
8419   return isolate->heap()->undefined_value();
8420 }
8421 
8422 
8423 class ActivationsFinder : public ThreadVisitor {
8424  public:
8425   Code* code_;
8426   bool has_code_activations_;
8427 
ActivationsFinder(Code * code)8428   explicit ActivationsFinder(Code* code)
8429     : code_(code),
8430       has_code_activations_(false) { }
8431 
VisitThread(Isolate * isolate,ThreadLocalTop * top)8432   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8433     JavaScriptFrameIterator it(isolate, top);
8434     VisitFrames(&it);
8435   }
8436 
VisitFrames(JavaScriptFrameIterator * it)8437   void VisitFrames(JavaScriptFrameIterator* it) {
8438     for (; !it->done(); it->Advance()) {
8439       JavaScriptFrame* frame = it->frame();
8440       if (code_->contains(frame->pc())) has_code_activations_ = true;
8441     }
8442   }
8443 };
8444 
8445 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NotifyStubFailure)8446 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyStubFailure) {
8447   HandleScope scope(isolate);
8448   ASSERT(args.length() == 0);
8449   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8450   ASSERT(AllowHeapAllocation::IsAllowed());
8451   delete deoptimizer;
8452   return isolate->heap()->undefined_value();
8453 }
8454 
8455 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NotifyDeoptimized)8456 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8457   HandleScope scope(isolate);
8458   ASSERT(args.length() == 1);
8459   RUNTIME_ASSERT(args[0]->IsSmi());
8460   Deoptimizer::BailoutType type =
8461       static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8462   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8463   ASSERT(AllowHeapAllocation::IsAllowed());
8464 
8465   Handle<JSFunction> function = deoptimizer->function();
8466   Handle<Code> optimized_code = deoptimizer->compiled_code();
8467 
8468   ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
8469   ASSERT(type == deoptimizer->bailout_type());
8470 
8471   // Make sure to materialize objects before causing any allocation.
8472   JavaScriptFrameIterator it(isolate);
8473   deoptimizer->MaterializeHeapObjects(&it);
8474   delete deoptimizer;
8475 
8476   JavaScriptFrame* frame = it.frame();
8477   RUNTIME_ASSERT(frame->function()->IsJSFunction());
8478   ASSERT(frame->function() == *function);
8479 
8480   // Avoid doing too much work when running with --always-opt and keep
8481   // the optimized code around.
8482   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8483     return isolate->heap()->undefined_value();
8484   }
8485 
8486   // Search for other activations of the same function and code.
8487   ActivationsFinder activations_finder(*optimized_code);
8488   activations_finder.VisitFrames(&it);
8489   isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8490 
8491   if (!activations_finder.has_code_activations_) {
8492     if (function->code() == *optimized_code) {
8493       if (FLAG_trace_deopt) {
8494         PrintF("[removing optimized code for: ");
8495         function->PrintName();
8496         PrintF("]\n");
8497       }
8498       function->ReplaceCode(function->shared()->code());
8499     }
8500   } else {
8501     // TODO(titzer): we should probably do DeoptimizeCodeList(code)
8502     // unconditionally if the code is not already marked for deoptimization.
8503     // If there is an index by shared function info, all the better.
8504     Deoptimizer::DeoptimizeFunction(*function);
8505   }
8506   // Evict optimized code for this function from the cache so that it doesn't
8507   // get used for new closures.
8508   function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8509                                                 "notify deoptimized");
8510 
8511   return isolate->heap()->undefined_value();
8512 }
8513 
8514 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeoptimizeFunction)8515 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8516   HandleScope scope(isolate);
8517   ASSERT(args.length() == 1);
8518   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8519   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8520 
8521   Deoptimizer::DeoptimizeFunction(*function);
8522 
8523   return isolate->heap()->undefined_value();
8524 }
8525 
8526 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClearFunctionTypeFeedback)8527 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8528   HandleScope scope(isolate);
8529   ASSERT(args.length() == 1);
8530   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8531   Code* unoptimized = function->shared()->code();
8532   if (unoptimized->kind() == Code::FUNCTION) {
8533     unoptimized->ClearInlineCaches();
8534     unoptimized->ClearTypeFeedbackCells(isolate->heap());
8535   }
8536   return isolate->heap()->undefined_value();
8537 }
8538 
8539 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RunningInSimulator)8540 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8541   SealHandleScope shs(isolate);
8542 #if defined(USE_SIMULATOR)
8543   return isolate->heap()->true_value();
8544 #else
8545   return isolate->heap()->false_value();
8546 #endif
8547 }
8548 
8549 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsConcurrentRecompilationSupported)8550 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) {
8551   HandleScope scope(isolate);
8552   return isolate->concurrent_recompilation_enabled()
8553       ? isolate->heap()->true_value() : isolate->heap()->false_value();
8554 }
8555 
8556 
RUNTIME_FUNCTION(MaybeObject *,Runtime_OptimizeFunctionOnNextCall)8557 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8558   HandleScope scope(isolate);
8559   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8560   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8561 
8562   if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8563   function->MarkForLazyRecompilation();
8564 
8565   Code* unoptimized = function->shared()->code();
8566   if (args.length() == 2 &&
8567       unoptimized->kind() == Code::FUNCTION) {
8568     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8569     if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
8570       // Start patching from the currently patched loop nesting level.
8571       int current_level = unoptimized->allow_osr_at_loop_nesting_level();
8572       ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
8573       for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
8574         unoptimized->set_allow_osr_at_loop_nesting_level(i);
8575         isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8576       }
8577     } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent"))) {
8578       function->MarkForConcurrentRecompilation();
8579     }
8580   }
8581 
8582   return isolate->heap()->undefined_value();
8583 }
8584 
8585 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NeverOptimizeFunction)8586 RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
8587   HandleScope scope(isolate);
8588   ASSERT(args.length() == 1);
8589   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8590   ASSERT(!function->IsOptimized());
8591   function->shared()->set_optimization_disabled(true);
8592   return isolate->heap()->undefined_value();
8593 }
8594 
8595 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetOptimizationStatus)8596 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8597   HandleScope scope(isolate);
8598   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8599   if (!isolate->use_crankshaft()) {
8600     return Smi::FromInt(4);  // 4 == "never".
8601   }
8602   bool sync_with_compiler_thread = true;
8603   if (args.length() == 2) {
8604     CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
8605     if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
8606       sync_with_compiler_thread = false;
8607     }
8608   }
8609   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8610   if (isolate->concurrent_recompilation_enabled() &&
8611       sync_with_compiler_thread) {
8612     while (function->IsInRecompileQueue()) {
8613       isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8614       OS::Sleep(50);
8615     }
8616   }
8617   if (FLAG_always_opt) {
8618     // We may have always opt, but that is more best-effort than a real
8619     // promise, so we still say "no" if it is not optimized.
8620     return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8621                                    : Smi::FromInt(2);  // 2 == "no".
8622   }
8623   if (FLAG_deopt_every_n_times) {
8624     return Smi::FromInt(6);  // 6 == "maybe deopted".
8625   }
8626   return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8627                                  : Smi::FromInt(2);  // 2 == "no".
8628 }
8629 
8630 
RUNTIME_FUNCTION(MaybeObject *,Runtime_UnblockConcurrentRecompilation)8631 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
8632   RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
8633   isolate->optimizing_compiler_thread()->Unblock();
8634   return isolate->heap()->undefined_value();
8635 }
8636 
8637 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetOptimizationCount)8638 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8639   HandleScope scope(isolate);
8640   ASSERT(args.length() == 1);
8641   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8642   return Smi::FromInt(function->shared()->opt_count());
8643 }
8644 
8645 
IsSuitableForOnStackReplacement(Isolate * isolate,Handle<JSFunction> function,Handle<Code> unoptimized)8646 static bool IsSuitableForOnStackReplacement(Isolate* isolate,
8647                                             Handle<JSFunction> function,
8648                                             Handle<Code> unoptimized) {
8649   // Keep track of whether we've succeeded in optimizing.
8650   if (!isolate->use_crankshaft() || !unoptimized->optimizable()) return false;
8651   // If we are trying to do OSR when there are already optimized
8652   // activations of the function, it means (a) the function is directly or
8653   // indirectly recursive and (b) an optimized invocation has been
8654   // deoptimized so that we are currently in an unoptimized activation.
8655   // Check for optimized activations of this function.
8656   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
8657     JavaScriptFrame* frame = it.frame();
8658     if (frame->is_optimized() && frame->function() == *function) return false;
8659   }
8660 
8661   return true;
8662 }
8663 
8664 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CompileForOnStackReplacement)8665 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8666   HandleScope scope(isolate);
8667   ASSERT(args.length() == 2);
8668   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8669   CONVERT_NUMBER_CHECKED(uint32_t, pc_offset, Uint32, args[1]);
8670   Handle<Code> unoptimized(function->shared()->code(), isolate);
8671 
8672 #ifdef DEBUG
8673   JavaScriptFrameIterator it(isolate);
8674   JavaScriptFrame* frame = it.frame();
8675   ASSERT_EQ(frame->function(), *function);
8676   ASSERT_EQ(frame->LookupCode(), *unoptimized);
8677   ASSERT(unoptimized->contains(frame->pc()));
8678 
8679   ASSERT(pc_offset ==
8680          static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start()));
8681 #endif  // DEBUG
8682 
8683   // We're not prepared to handle a function with arguments object.
8684   ASSERT(!function->shared()->uses_arguments());
8685 
8686   Handle<Code> result = Handle<Code>::null();
8687   BailoutId ast_id = BailoutId::None();
8688 
8689   if (isolate->concurrent_osr_enabled()) {
8690     if (isolate->optimizing_compiler_thread()->
8691             IsQueuedForOSR(function, pc_offset)) {
8692       // Still waiting for the optimizing compiler thread to finish.  Carry on.
8693       if (FLAG_trace_osr) {
8694         PrintF("[COSR - polling recompile tasks for ");
8695         function->PrintName();
8696         PrintF("]\n");
8697       }
8698       return NULL;
8699     }
8700 
8701     RecompileJob* job = isolate->optimizing_compiler_thread()->
8702         FindReadyOSRCandidate(function, pc_offset);
8703 
8704     if (job == NULL) {
8705       if (IsSuitableForOnStackReplacement(isolate, function, unoptimized) &&
8706           Compiler::RecompileConcurrent(function, pc_offset)) {
8707         if (function->IsMarkedForLazyRecompilation() ||
8708             function->IsMarkedForConcurrentRecompilation()) {
8709           // Prevent regular recompilation if we queue this for OSR.
8710           // TODO(yangguo): remove this as soon as OSR becomes one-shot.
8711           function->ReplaceCode(*unoptimized);
8712         }
8713         return NULL;
8714       }
8715       // Fall through to the end in case of failure.
8716     } else {
8717       // TODO(titzer): don't install the OSR code into the function.
8718       ast_id = job->info()->osr_ast_id();
8719       result = Compiler::InstallOptimizedCode(job);
8720     }
8721   } else if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
8722     ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset);
8723     ASSERT(!ast_id.IsNone());
8724     if (FLAG_trace_osr) {
8725       PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt());
8726       function->PrintName();
8727       PrintF("]\n");
8728     }
8729     // Attempt OSR compilation.
8730     result = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION);
8731   }
8732 
8733   // Revert the patched back edge table, regardless of whether OSR succeeds.
8734   BackEdgeTable::Revert(isolate, *unoptimized);
8735 
8736   // Check whether we ended up with usable optimized code.
8737   if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
8738     DeoptimizationInputData* data =
8739         DeoptimizationInputData::cast(result->deoptimization_data());
8740 
8741     if (data->OsrPcOffset()->value() >= 0) {
8742       ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8743       if (FLAG_trace_osr) {
8744         PrintF("[OSR - entry at AST id %d, offset %d in optimized code]\n",
8745                ast_id.ToInt(), data->OsrPcOffset()->value());
8746       }
8747       // TODO(titzer): this is a massive hack to make the deopt counts
8748       // match. Fix heuristics for reenabling optimizations!
8749       function->shared()->increment_deopt_count();
8750       return *result;
8751     }
8752   }
8753 
8754   if (FLAG_trace_osr) {
8755     PrintF("[OSR - optimization failed for ");
8756     function->PrintName();
8757     PrintF("]\n");
8758   }
8759 
8760   if (function->IsMarkedForLazyRecompilation() ||
8761       function->IsMarkedForConcurrentRecompilation()) {
8762     function->ReplaceCode(function->shared()->code());
8763   }
8764   return NULL;
8765 }
8766 
8767 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetAllocationTimeout)8768 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
8769   SealHandleScope shs(isolate);
8770   ASSERT(args.length() == 2);
8771 #ifdef DEBUG
8772   CONVERT_SMI_ARG_CHECKED(interval, 0);
8773   CONVERT_SMI_ARG_CHECKED(timeout, 1);
8774   isolate->heap()->set_allocation_timeout(timeout);
8775   FLAG_gc_interval = interval;
8776 #endif
8777   return isolate->heap()->undefined_value();
8778 }
8779 
8780 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CheckIsBootstrapping)8781 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8782   SealHandleScope shs(isolate);
8783   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8784   return isolate->heap()->undefined_value();
8785 }
8786 
8787 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetRootNaN)8788 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8789   SealHandleScope shs(isolate);
8790   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8791   return isolate->heap()->nan_value();
8792 }
8793 
8794 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Call)8795 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8796   HandleScope scope(isolate);
8797   ASSERT(args.length() >= 2);
8798   int argc = args.length() - 2;
8799   CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8800   Object* receiver = args[0];
8801 
8802   // If there are too many arguments, allocate argv via malloc.
8803   const int argv_small_size = 10;
8804   Handle<Object> argv_small_buffer[argv_small_size];
8805   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8806   Handle<Object>* argv = argv_small_buffer;
8807   if (argc > argv_small_size) {
8808     argv = new Handle<Object>[argc];
8809     if (argv == NULL) return isolate->StackOverflow();
8810     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8811   }
8812 
8813   for (int i = 0; i < argc; ++i) {
8814      MaybeObject* maybe = args[1 + i];
8815      Object* object;
8816      if (!maybe->To<Object>(&object)) return maybe;
8817      argv[i] = Handle<Object>(object, isolate);
8818   }
8819 
8820   bool threw;
8821   Handle<JSReceiver> hfun(fun);
8822   Handle<Object> hreceiver(receiver, isolate);
8823   Handle<Object> result = Execution::Call(
8824       isolate, hfun, hreceiver, argc, argv, &threw, true);
8825 
8826   if (threw) return Failure::Exception();
8827   return *result;
8828 }
8829 
8830 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Apply)8831 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8832   HandleScope scope(isolate);
8833   ASSERT(args.length() == 5);
8834   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8835   Handle<Object> receiver = args.at<Object>(1);
8836   CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8837   CONVERT_SMI_ARG_CHECKED(offset, 3);
8838   CONVERT_SMI_ARG_CHECKED(argc, 4);
8839   RUNTIME_ASSERT(offset >= 0);
8840   RUNTIME_ASSERT(argc >= 0);
8841 
8842   // If there are too many arguments, allocate argv via malloc.
8843   const int argv_small_size = 10;
8844   Handle<Object> argv_small_buffer[argv_small_size];
8845   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8846   Handle<Object>* argv = argv_small_buffer;
8847   if (argc > argv_small_size) {
8848     argv = new Handle<Object>[argc];
8849     if (argv == NULL) return isolate->StackOverflow();
8850     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8851   }
8852 
8853   for (int i = 0; i < argc; ++i) {
8854     argv[i] = Object::GetElement(isolate, arguments, offset + i);
8855   }
8856 
8857   bool threw;
8858   Handle<Object> result = Execution::Call(
8859       isolate, fun, receiver, argc, argv, &threw, true);
8860 
8861   if (threw) return Failure::Exception();
8862   return *result;
8863 }
8864 
8865 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionDelegate)8866 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8867   HandleScope scope(isolate);
8868   ASSERT(args.length() == 1);
8869   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8870   return *Execution::GetFunctionDelegate(isolate, args.at<Object>(0));
8871 }
8872 
8873 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetConstructorDelegate)8874 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8875   HandleScope scope(isolate);
8876   ASSERT(args.length() == 1);
8877   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8878   return *Execution::GetConstructorDelegate(isolate, args.at<Object>(0));
8879 }
8880 
8881 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewGlobalContext)8882 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
8883   SealHandleScope shs(isolate);
8884   ASSERT(args.length() == 2);
8885 
8886   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8887   CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
8888   Context* result;
8889   MaybeObject* maybe_result =
8890       isolate->heap()->AllocateGlobalContext(function, scope_info);
8891   if (!maybe_result->To(&result)) return maybe_result;
8892 
8893   ASSERT(function->context() == isolate->context());
8894   ASSERT(function->context()->global_object() == result->global_object());
8895   isolate->set_context(result);
8896   result->global_object()->set_global_context(result);
8897 
8898   return result;  // non-failure
8899 }
8900 
8901 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewFunctionContext)8902 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8903   SealHandleScope shs(isolate);
8904   ASSERT(args.length() == 1);
8905 
8906   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8907   int length = function->shared()->scope_info()->ContextLength();
8908   Context* result;
8909   MaybeObject* maybe_result =
8910       isolate->heap()->AllocateFunctionContext(length, function);
8911   if (!maybe_result->To(&result)) return maybe_result;
8912 
8913   isolate->set_context(result);
8914 
8915   return result;  // non-failure
8916 }
8917 
8918 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushWithContext)8919 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8920   SealHandleScope shs(isolate);
8921   ASSERT(args.length() == 2);
8922   JSReceiver* extension_object;
8923   if (args[0]->IsJSReceiver()) {
8924     extension_object = JSReceiver::cast(args[0]);
8925   } else {
8926     // Convert the object to a proper JavaScript object.
8927     MaybeObject* maybe_js_object = args[0]->ToObject(isolate);
8928     if (!maybe_js_object->To(&extension_object)) {
8929       if (Failure::cast(maybe_js_object)->IsInternalError()) {
8930         HandleScope scope(isolate);
8931         Handle<Object> handle = args.at<Object>(0);
8932         Handle<Object> result =
8933             isolate->factory()->NewTypeError("with_expression",
8934                                              HandleVector(&handle, 1));
8935         return isolate->Throw(*result);
8936       } else {
8937         return maybe_js_object;
8938       }
8939     }
8940   }
8941 
8942   JSFunction* function;
8943   if (args[1]->IsSmi()) {
8944     // A smi sentinel indicates a context nested inside global code rather
8945     // than some function.  There is a canonical empty function that can be
8946     // gotten from the native context.
8947     function = isolate->context()->native_context()->closure();
8948   } else {
8949     function = JSFunction::cast(args[1]);
8950   }
8951 
8952   Context* context;
8953   MaybeObject* maybe_context =
8954       isolate->heap()->AllocateWithContext(function,
8955                                            isolate->context(),
8956                                            extension_object);
8957   if (!maybe_context->To(&context)) return maybe_context;
8958   isolate->set_context(context);
8959   return context;
8960 }
8961 
8962 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushCatchContext)8963 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8964   SealHandleScope shs(isolate);
8965   ASSERT(args.length() == 3);
8966   String* name = String::cast(args[0]);
8967   Object* thrown_object = args[1];
8968   JSFunction* function;
8969   if (args[2]->IsSmi()) {
8970     // A smi sentinel indicates a context nested inside global code rather
8971     // than some function.  There is a canonical empty function that can be
8972     // gotten from the native context.
8973     function = isolate->context()->native_context()->closure();
8974   } else {
8975     function = JSFunction::cast(args[2]);
8976   }
8977   Context* context;
8978   MaybeObject* maybe_context =
8979       isolate->heap()->AllocateCatchContext(function,
8980                                             isolate->context(),
8981                                             name,
8982                                             thrown_object);
8983   if (!maybe_context->To(&context)) return maybe_context;
8984   isolate->set_context(context);
8985   return context;
8986 }
8987 
8988 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushBlockContext)8989 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8990   SealHandleScope shs(isolate);
8991   ASSERT(args.length() == 2);
8992   ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8993   JSFunction* function;
8994   if (args[1]->IsSmi()) {
8995     // A smi sentinel indicates a context nested inside global code rather
8996     // than some function.  There is a canonical empty function that can be
8997     // gotten from the native context.
8998     function = isolate->context()->native_context()->closure();
8999   } else {
9000     function = JSFunction::cast(args[1]);
9001   }
9002   Context* context;
9003   MaybeObject* maybe_context =
9004       isolate->heap()->AllocateBlockContext(function,
9005                                             isolate->context(),
9006                                             scope_info);
9007   if (!maybe_context->To(&context)) return maybe_context;
9008   isolate->set_context(context);
9009   return context;
9010 }
9011 
9012 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsJSModule)9013 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
9014   SealHandleScope shs(isolate);
9015   ASSERT(args.length() == 1);
9016   Object* obj = args[0];
9017   return isolate->heap()->ToBoolean(obj->IsJSModule());
9018 }
9019 
9020 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushModuleContext)9021 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
9022   SealHandleScope shs(isolate);
9023   ASSERT(args.length() == 2);
9024   CONVERT_SMI_ARG_CHECKED(index, 0);
9025 
9026   if (!args[1]->IsScopeInfo()) {
9027     // Module already initialized. Find hosting context and retrieve context.
9028     Context* host = Context::cast(isolate->context())->global_context();
9029     Context* context = Context::cast(host->get(index));
9030     ASSERT(context->previous() == isolate->context());
9031     isolate->set_context(context);
9032     return context;
9033   }
9034 
9035   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
9036 
9037   // Allocate module context.
9038   HandleScope scope(isolate);
9039   Factory* factory = isolate->factory();
9040   Handle<Context> context = factory->NewModuleContext(scope_info);
9041   Handle<JSModule> module = factory->NewJSModule(context, scope_info);
9042   context->set_module(*module);
9043   Context* previous = isolate->context();
9044   context->set_previous(previous);
9045   context->set_closure(previous->closure());
9046   context->set_global_object(previous->global_object());
9047   isolate->set_context(*context);
9048 
9049   // Find hosting scope and initialize internal variable holding module there.
9050   previous->global_context()->set(index, *context);
9051 
9052   return *context;
9053 }
9054 
9055 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeclareModules)9056 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
9057   HandleScope scope(isolate);
9058   ASSERT(args.length() == 1);
9059   CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
9060   Context* host_context = isolate->context();
9061 
9062   for (int i = 0; i < descriptions->length(); ++i) {
9063     Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
9064     int host_index = description->host_index();
9065     Handle<Context> context(Context::cast(host_context->get(host_index)));
9066     Handle<JSModule> module(context->module());
9067 
9068     for (int j = 0; j < description->length(); ++j) {
9069       Handle<String> name(description->name(j));
9070       VariableMode mode = description->mode(j);
9071       int index = description->index(j);
9072       switch (mode) {
9073         case VAR:
9074         case LET:
9075         case CONST:
9076         case CONST_HARMONY: {
9077           PropertyAttributes attr =
9078               IsImmutableVariableMode(mode) ? FROZEN : SEALED;
9079           Handle<AccessorInfo> info =
9080               Accessors::MakeModuleExport(name, index, attr);
9081           Handle<Object> result = JSObject::SetAccessor(module, info);
9082           ASSERT(!(result.is_null() || result->IsUndefined()));
9083           USE(result);
9084           break;
9085         }
9086         case MODULE: {
9087           Object* referenced_context = Context::cast(host_context)->get(index);
9088           Handle<JSModule> value(Context::cast(referenced_context)->module());
9089           JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode);
9090           break;
9091         }
9092         case INTERNAL:
9093         case TEMPORARY:
9094         case DYNAMIC:
9095         case DYNAMIC_GLOBAL:
9096         case DYNAMIC_LOCAL:
9097           UNREACHABLE();
9098       }
9099     }
9100 
9101     JSObject::PreventExtensions(module);
9102   }
9103 
9104   ASSERT(!isolate->has_pending_exception());
9105   return isolate->heap()->undefined_value();
9106 }
9107 
9108 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteContextSlot)9109 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
9110   HandleScope scope(isolate);
9111   ASSERT(args.length() == 2);
9112 
9113   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
9114   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
9115 
9116   int index;
9117   PropertyAttributes attributes;
9118   ContextLookupFlags flags = FOLLOW_CHAINS;
9119   BindingFlags binding_flags;
9120   Handle<Object> holder = context->Lookup(name,
9121                                           flags,
9122                                           &index,
9123                                           &attributes,
9124                                           &binding_flags);
9125 
9126   // If the slot was not found the result is true.
9127   if (holder.is_null()) {
9128     return isolate->heap()->true_value();
9129   }
9130 
9131   // If the slot was found in a context, it should be DONT_DELETE.
9132   if (holder->IsContext()) {
9133     return isolate->heap()->false_value();
9134   }
9135 
9136   // The slot was found in a JSObject, either a context extension object,
9137   // the global object, or the subject of a with.  Try to delete it
9138   // (respecting DONT_DELETE).
9139   Handle<JSObject> object = Handle<JSObject>::cast(holder);
9140   Handle<Object> result = JSReceiver::DeleteProperty(object, name);
9141   RETURN_IF_EMPTY_HANDLE(isolate, result);
9142   return *result;
9143 }
9144 
9145 
9146 // A mechanism to return a pair of Object pointers in registers (if possible).
9147 // How this is achieved is calling convention-dependent.
9148 // All currently supported x86 compiles uses calling conventions that are cdecl
9149 // variants where a 64-bit value is returned in two 32-bit registers
9150 // (edx:eax on ia32, r1:r0 on ARM).
9151 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9152 // In Win64 calling convention, a struct of two pointers is returned in memory,
9153 // allocated by the caller, and passed as a pointer in a hidden first parameter.
9154 #ifdef V8_HOST_ARCH_64_BIT
9155 struct ObjectPair {
9156   MaybeObject* x;
9157   MaybeObject* y;
9158 };
9159 
9160 
MakePair(MaybeObject * x,MaybeObject * y)9161 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9162   ObjectPair result = {x, y};
9163   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9164   // In Win64 they are assigned to a hidden first argument.
9165   return result;
9166 }
9167 #else
9168 typedef uint64_t ObjectPair;
MakePair(MaybeObject * x,MaybeObject * y)9169 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9170   return reinterpret_cast<uint32_t>(x) |
9171       (reinterpret_cast<ObjectPair>(y) << 32);
9172 }
9173 #endif
9174 
9175 
Unhole(Heap * heap,MaybeObject * x,PropertyAttributes attributes)9176 static inline MaybeObject* Unhole(Heap* heap,
9177                                   MaybeObject* x,
9178                                   PropertyAttributes attributes) {
9179   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
9180   USE(attributes);
9181   return x->IsTheHole() ? heap->undefined_value() : x;
9182 }
9183 
9184 
ComputeReceiverForNonGlobal(Isolate * isolate,JSObject * holder)9185 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9186                                            JSObject* holder) {
9187   ASSERT(!holder->IsGlobalObject());
9188   Context* top = isolate->context();
9189   // Get the context extension function.
9190   JSFunction* context_extension_function =
9191       top->native_context()->context_extension_function();
9192   // If the holder isn't a context extension object, we just return it
9193   // as the receiver. This allows arguments objects to be used as
9194   // receivers, but only if they are put in the context scope chain
9195   // explicitly via a with-statement.
9196   Object* constructor = holder->map()->constructor();
9197   if (constructor != context_extension_function) return holder;
9198   // Fall back to using the global object as the implicit receiver if
9199   // the property turns out to be a local variable allocated in a
9200   // context extension object - introduced via eval. Implicit global
9201   // receivers are indicated with the hole value.
9202   return isolate->heap()->the_hole_value();
9203 }
9204 
9205 
LoadContextSlotHelper(Arguments args,Isolate * isolate,bool throw_error)9206 static ObjectPair LoadContextSlotHelper(Arguments args,
9207                                         Isolate* isolate,
9208                                         bool throw_error) {
9209   HandleScope scope(isolate);
9210   ASSERT_EQ(2, args.length());
9211 
9212   if (!args[0]->IsContext() || !args[1]->IsString()) {
9213     return MakePair(isolate->ThrowIllegalOperation(), NULL);
9214   }
9215   Handle<Context> context = args.at<Context>(0);
9216   Handle<String> name = args.at<String>(1);
9217 
9218   int index;
9219   PropertyAttributes attributes;
9220   ContextLookupFlags flags = FOLLOW_CHAINS;
9221   BindingFlags binding_flags;
9222   Handle<Object> holder = context->Lookup(name,
9223                                           flags,
9224                                           &index,
9225                                           &attributes,
9226                                           &binding_flags);
9227   if (isolate->has_pending_exception()) {
9228     return MakePair(Failure::Exception(), NULL);
9229   }
9230 
9231   // If the index is non-negative, the slot has been found in a context.
9232   if (index >= 0) {
9233     ASSERT(holder->IsContext());
9234     // If the "property" we were looking for is a local variable, the
9235     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9236     //
9237     // Use the hole as the receiver to signal that the receiver is implicit
9238     // and that the global receiver should be used (as distinguished from an
9239     // explicit receiver that happens to be a global object).
9240     Handle<Object> receiver = isolate->factory()->the_hole_value();
9241     Object* value = Context::cast(*holder)->get(index);
9242     // Check for uninitialized bindings.
9243     switch (binding_flags) {
9244       case MUTABLE_CHECK_INITIALIZED:
9245       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
9246         if (value->IsTheHole()) {
9247           Handle<Object> reference_error =
9248               isolate->factory()->NewReferenceError("not_defined",
9249                                                     HandleVector(&name, 1));
9250           return MakePair(isolate->Throw(*reference_error), NULL);
9251         }
9252         // FALLTHROUGH
9253       case MUTABLE_IS_INITIALIZED:
9254       case IMMUTABLE_IS_INITIALIZED:
9255       case IMMUTABLE_IS_INITIALIZED_HARMONY:
9256         ASSERT(!value->IsTheHole());
9257         return MakePair(value, *receiver);
9258       case IMMUTABLE_CHECK_INITIALIZED:
9259         return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
9260       case MISSING_BINDING:
9261         UNREACHABLE();
9262         return MakePair(NULL, NULL);
9263     }
9264   }
9265 
9266   // Otherwise, if the slot was found the holder is a context extension
9267   // object, subject of a with, or a global object.  We read the named
9268   // property from it.
9269   if (!holder.is_null()) {
9270     Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9271     ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name));
9272     // GetProperty below can cause GC.
9273     Handle<Object> receiver_handle(
9274         object->IsGlobalObject()
9275             ? GlobalObject::cast(*object)->global_receiver()
9276             : object->IsJSProxy() ? static_cast<Object*>(*object)
9277                 : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9278         isolate);
9279 
9280     // No need to unhole the value here.  This is taken care of by the
9281     // GetProperty function.
9282     MaybeObject* value = object->GetProperty(*name);
9283     return MakePair(value, *receiver_handle);
9284   }
9285 
9286   if (throw_error) {
9287     // The property doesn't exist - throw exception.
9288     Handle<Object> reference_error =
9289         isolate->factory()->NewReferenceError("not_defined",
9290                                               HandleVector(&name, 1));
9291     return MakePair(isolate->Throw(*reference_error), NULL);
9292   } else {
9293     // The property doesn't exist - return undefined.
9294     return MakePair(isolate->heap()->undefined_value(),
9295                     isolate->heap()->undefined_value());
9296   }
9297 }
9298 
9299 
RUNTIME_FUNCTION(ObjectPair,Runtime_LoadContextSlot)9300 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
9301   return LoadContextSlotHelper(args, isolate, true);
9302 }
9303 
9304 
RUNTIME_FUNCTION(ObjectPair,Runtime_LoadContextSlotNoReferenceError)9305 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
9306   return LoadContextSlotHelper(args, isolate, false);
9307 }
9308 
9309 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StoreContextSlot)9310 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
9311   HandleScope scope(isolate);
9312   ASSERT(args.length() == 4);
9313 
9314   Handle<Object> value(args[0], isolate);
9315   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9316   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9317   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9318   StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
9319       ? kNonStrictMode : kStrictMode;
9320 
9321   int index;
9322   PropertyAttributes attributes;
9323   ContextLookupFlags flags = FOLLOW_CHAINS;
9324   BindingFlags binding_flags;
9325   Handle<Object> holder = context->Lookup(name,
9326                                           flags,
9327                                           &index,
9328                                           &attributes,
9329                                           &binding_flags);
9330   if (isolate->has_pending_exception()) return Failure::Exception();
9331 
9332   if (index >= 0) {
9333     // The property was found in a context slot.
9334     Handle<Context> context = Handle<Context>::cast(holder);
9335     if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9336         context->get(index)->IsTheHole()) {
9337       Handle<Object> error =
9338           isolate->factory()->NewReferenceError("not_defined",
9339                                                 HandleVector(&name, 1));
9340       return isolate->Throw(*error);
9341     }
9342     // Ignore if read_only variable.
9343     if ((attributes & READ_ONLY) == 0) {
9344       // Context is a fixed array and set cannot fail.
9345       context->set(index, *value);
9346     } else if (strict_mode == kStrictMode) {
9347       // Setting read only property in strict mode.
9348       Handle<Object> error =
9349           isolate->factory()->NewTypeError("strict_cannot_assign",
9350                                            HandleVector(&name, 1));
9351       return isolate->Throw(*error);
9352     }
9353     return *value;
9354   }
9355 
9356   // Slow case: The property is not in a context slot.  It is either in a
9357   // context extension object, a property of the subject of a with, or a
9358   // property of the global object.
9359   Handle<JSReceiver> object;
9360 
9361   if (!holder.is_null()) {
9362     // The property exists on the holder.
9363     object = Handle<JSReceiver>::cast(holder);
9364   } else {
9365     // The property was not found.
9366     ASSERT(attributes == ABSENT);
9367 
9368     if (strict_mode == kStrictMode) {
9369       // Throw in strict mode (assignment to undefined variable).
9370       Handle<Object> error =
9371           isolate->factory()->NewReferenceError(
9372               "not_defined", HandleVector(&name, 1));
9373       return isolate->Throw(*error);
9374     }
9375     // In non-strict mode, the property is added to the global object.
9376     attributes = NONE;
9377     object = Handle<JSReceiver>(isolate->context()->global_object());
9378   }
9379 
9380   // Set the property if it's not read only or doesn't yet exist.
9381   if ((attributes & READ_ONLY) == 0 ||
9382       (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
9383     RETURN_IF_EMPTY_HANDLE(
9384         isolate,
9385         JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9386   } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
9387     // Setting read only property in strict mode.
9388     Handle<Object> error =
9389       isolate->factory()->NewTypeError(
9390           "strict_cannot_assign", HandleVector(&name, 1));
9391     return isolate->Throw(*error);
9392   }
9393   return *value;
9394 }
9395 
9396 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Throw)9397 RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
9398   HandleScope scope(isolate);
9399   ASSERT(args.length() == 1);
9400 
9401   return isolate->Throw(args[0]);
9402 }
9403 
9404 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ReThrow)9405 RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
9406   HandleScope scope(isolate);
9407   ASSERT(args.length() == 1);
9408 
9409   return isolate->ReThrow(args[0]);
9410 }
9411 
9412 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PromoteScheduledException)9413 RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
9414   SealHandleScope shs(isolate);
9415   ASSERT_EQ(0, args.length());
9416   return isolate->PromoteScheduledException();
9417 }
9418 
9419 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ThrowReferenceError)9420 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
9421   HandleScope scope(isolate);
9422   ASSERT(args.length() == 1);
9423 
9424   Handle<Object> name(args[0], isolate);
9425   Handle<Object> reference_error =
9426     isolate->factory()->NewReferenceError("not_defined",
9427                                           HandleVector(&name, 1));
9428   return isolate->Throw(*reference_error);
9429 }
9430 
9431 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ThrowNotDateError)9432 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
9433   HandleScope scope(isolate);
9434   ASSERT(args.length() == 0);
9435   return isolate->Throw(*isolate->factory()->NewTypeError(
9436       "not_date_object", HandleVector<Object>(NULL, 0)));
9437 }
9438 
9439 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ThrowMessage)9440 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) {
9441   HandleScope scope(isolate);
9442   ASSERT(args.length() == 1);
9443   CONVERT_SMI_ARG_CHECKED(message_id, 0);
9444   const char* message = GetBailoutReason(
9445       static_cast<BailoutReason>(message_id));
9446   Handle<Name> message_handle =
9447       isolate->factory()->NewStringFromAscii(CStrVector(message));
9448   return isolate->Throw(*message_handle);
9449 }
9450 
9451 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StackGuard)9452 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9453   SealHandleScope shs(isolate);
9454   ASSERT(args.length() == 0);
9455 
9456   // First check if this is a real stack overflow.
9457   if (isolate->stack_guard()->IsStackOverflow()) {
9458     return isolate->StackOverflow();
9459   }
9460 
9461   return Execution::HandleStackGuardInterrupt(isolate);
9462 }
9463 
9464 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TryInstallRecompiledCode)9465 RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallRecompiledCode) {
9466   HandleScope scope(isolate);
9467   ASSERT(args.length() == 1);
9468   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9469 
9470   // First check if this is a real stack overflow.
9471   if (isolate->stack_guard()->IsStackOverflow()) {
9472     SealHandleScope shs(isolate);
9473     return isolate->StackOverflow();
9474   }
9475 
9476   isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
9477   return (function->IsOptimized()) ? function->code()
9478                                    : function->shared()->code();
9479 }
9480 
9481 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Interrupt)9482 RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
9483   SealHandleScope shs(isolate);
9484   ASSERT(args.length() == 0);
9485   return Execution::HandleStackGuardInterrupt(isolate);
9486 }
9487 
9488 
StackSize(Isolate * isolate)9489 static int StackSize(Isolate* isolate) {
9490   int n = 0;
9491   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9492   return n;
9493 }
9494 
9495 
PrintTransition(Isolate * isolate,Object * result)9496 static void PrintTransition(Isolate* isolate, Object* result) {
9497   // indentation
9498   { const int nmax = 80;
9499     int n = StackSize(isolate);
9500     if (n <= nmax)
9501       PrintF("%4d:%*s", n, n, "");
9502     else
9503       PrintF("%4d:%*s", n, nmax, "...");
9504   }
9505 
9506   if (result == NULL) {
9507     JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9508     PrintF(" {\n");
9509   } else {
9510     // function result
9511     PrintF("} -> ");
9512     result->ShortPrint();
9513     PrintF("\n");
9514   }
9515 }
9516 
9517 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TraceEnter)9518 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9519   SealHandleScope shs(isolate);
9520   ASSERT(args.length() == 0);
9521   PrintTransition(isolate, NULL);
9522   return isolate->heap()->undefined_value();
9523 }
9524 
9525 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TraceExit)9526 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9527   SealHandleScope shs(isolate);
9528   PrintTransition(isolate, args[0]);
9529   return args[0];  // return TOS
9530 }
9531 
9532 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPrint)9533 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9534   SealHandleScope shs(isolate);
9535   ASSERT(args.length() == 1);
9536 
9537 #ifdef DEBUG
9538   if (args[0]->IsString()) {
9539     // If we have a string, assume it's a code "marker"
9540     // and print some interesting cpu debugging info.
9541     JavaScriptFrameIterator it(isolate);
9542     JavaScriptFrame* frame = it.frame();
9543     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9544            frame->fp(), frame->sp(), frame->caller_sp());
9545   } else {
9546     PrintF("DebugPrint: ");
9547   }
9548   args[0]->Print();
9549   if (args[0]->IsHeapObject()) {
9550     PrintF("\n");
9551     HeapObject::cast(args[0])->map()->Print();
9552   }
9553 #else
9554   // ShortPrint is available in release mode. Print is not.
9555   args[0]->ShortPrint();
9556 #endif
9557   PrintF("\n");
9558   Flush();
9559 
9560   return args[0];  // return TOS
9561 }
9562 
9563 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugTrace)9564 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9565   SealHandleScope shs(isolate);
9566   ASSERT(args.length() == 0);
9567   isolate->PrintStack(stdout);
9568   return isolate->heap()->undefined_value();
9569 }
9570 
9571 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateCurrentTime)9572 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9573   SealHandleScope shs(isolate);
9574   ASSERT(args.length() == 0);
9575 
9576   // According to ECMA-262, section 15.9.1, page 117, the precision of
9577   // the number in a Date object representing a particular instant in
9578   // time is milliseconds. Therefore, we floor the result of getting
9579   // the OS time.
9580   double millis = floor(OS::TimeCurrentMillis());
9581   return isolate->heap()->NumberFromDouble(millis);
9582 }
9583 
9584 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateParseString)9585 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9586   HandleScope scope(isolate);
9587   ASSERT(args.length() == 2);
9588 
9589   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9590   FlattenString(str);
9591 
9592   CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9593 
9594   JSObject::EnsureCanContainHeapObjectElements(output);
9595   RUNTIME_ASSERT(output->HasFastObjectElements());
9596 
9597   DisallowHeapAllocation no_gc;
9598 
9599   FixedArray* output_array = FixedArray::cast(output->elements());
9600   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9601   bool result;
9602   String::FlatContent str_content = str->GetFlatContent();
9603   if (str_content.IsAscii()) {
9604     result = DateParser::Parse(str_content.ToOneByteVector(),
9605                                output_array,
9606                                isolate->unicode_cache());
9607   } else {
9608     ASSERT(str_content.IsTwoByte());
9609     result = DateParser::Parse(str_content.ToUC16Vector(),
9610                                output_array,
9611                                isolate->unicode_cache());
9612   }
9613 
9614   if (result) {
9615     return *output;
9616   } else {
9617     return isolate->heap()->null_value();
9618   }
9619 }
9620 
9621 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateLocalTimezone)9622 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9623   SealHandleScope shs(isolate);
9624   ASSERT(args.length() == 1);
9625 
9626   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9627   int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9628   const char* zone = OS::LocalTimezone(static_cast<double>(time));
9629   return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9630 }
9631 
9632 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateToUTC)9633 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9634   SealHandleScope shs(isolate);
9635   ASSERT(args.length() == 1);
9636 
9637   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9638   int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9639 
9640   return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9641 }
9642 
9643 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GlobalReceiver)9644 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9645   SealHandleScope shs(isolate);
9646   ASSERT(args.length() == 1);
9647   Object* global = args[0];
9648   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9649   return JSGlobalObject::cast(global)->global_receiver();
9650 }
9651 
9652 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsAttachedGlobal)9653 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAttachedGlobal) {
9654   SealHandleScope shs(isolate);
9655   ASSERT(args.length() == 1);
9656   Object* global = args[0];
9657   if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
9658   return isolate->heap()->ToBoolean(
9659       !JSGlobalObject::cast(global)->IsDetached());
9660 }
9661 
9662 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ParseJson)9663 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9664   HandleScope scope(isolate);
9665   ASSERT_EQ(1, args.length());
9666   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9667 
9668   source = Handle<String>(FlattenGetString(source));
9669   // Optimized fast case where we only have ASCII characters.
9670   Handle<Object> result;
9671   if (source->IsSeqOneByteString()) {
9672     result = JsonParser<true>::Parse(source);
9673   } else {
9674     result = JsonParser<false>::Parse(source);
9675   }
9676   if (result.is_null()) {
9677     // Syntax error or stack overflow in scanner.
9678     ASSERT(isolate->has_pending_exception());
9679     return Failure::Exception();
9680   }
9681   return *result;
9682 }
9683 
9684 
CodeGenerationFromStringsAllowed(Isolate * isolate,Handle<Context> context)9685 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9686                                       Handle<Context> context) {
9687   ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9688   // Check with callback if set.
9689   AllowCodeGenerationFromStringsCallback callback =
9690       isolate->allow_code_gen_callback();
9691   if (callback == NULL) {
9692     // No callback set and code generation disallowed.
9693     return false;
9694   } else {
9695     // Callback set. Let it decide if code generation is allowed.
9696     VMState<EXTERNAL> state(isolate);
9697     return callback(v8::Utils::ToLocal(context));
9698   }
9699 }
9700 
9701 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CompileString)9702 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9703   HandleScope scope(isolate);
9704   ASSERT_EQ(2, args.length());
9705   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9706   CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9707 
9708   // Extract native context.
9709   Handle<Context> context(isolate->context()->native_context());
9710 
9711   // Check if native context allows code generation from
9712   // strings. Throw an exception if it doesn't.
9713   if (context->allow_code_gen_from_strings()->IsFalse() &&
9714       !CodeGenerationFromStringsAllowed(isolate, context)) {
9715     Handle<Object> error_message =
9716         context->ErrorMessageForCodeGenerationFromStrings();
9717     return isolate->Throw(*isolate->factory()->NewEvalError(
9718         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9719   }
9720 
9721   // Compile source string in the native context.
9722   ParseRestriction restriction = function_literal_only
9723       ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
9724   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9725       source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
9726   RETURN_IF_EMPTY_HANDLE(isolate, shared);
9727   Handle<JSFunction> fun =
9728       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9729                                                             context,
9730                                                             NOT_TENURED);
9731   return *fun;
9732 }
9733 
9734 
CompileGlobalEval(Isolate * isolate,Handle<String> source,Handle<Object> receiver,LanguageMode language_mode,int scope_position)9735 static ObjectPair CompileGlobalEval(Isolate* isolate,
9736                                     Handle<String> source,
9737                                     Handle<Object> receiver,
9738                                     LanguageMode language_mode,
9739                                     int scope_position) {
9740   Handle<Context> context = Handle<Context>(isolate->context());
9741   Handle<Context> native_context = Handle<Context>(context->native_context());
9742 
9743   // Check if native context allows code generation from
9744   // strings. Throw an exception if it doesn't.
9745   if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9746       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9747     Handle<Object> error_message =
9748         native_context->ErrorMessageForCodeGenerationFromStrings();
9749     isolate->Throw(*isolate->factory()->NewEvalError(
9750         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9751     return MakePair(Failure::Exception(), NULL);
9752   }
9753 
9754   // Deal with a normal eval call with a string argument. Compile it
9755   // and return the compiled function bound in the local context.
9756   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9757       source,
9758       context,
9759       context->IsNativeContext(),
9760       language_mode,
9761       NO_PARSE_RESTRICTION,
9762       scope_position);
9763   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
9764                                MakePair(Failure::Exception(), NULL));
9765   Handle<JSFunction> compiled =
9766       isolate->factory()->NewFunctionFromSharedFunctionInfo(
9767           shared, context, NOT_TENURED);
9768   return MakePair(*compiled, *receiver);
9769 }
9770 
9771 
RUNTIME_FUNCTION(ObjectPair,Runtime_ResolvePossiblyDirectEval)9772 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9773   HandleScope scope(isolate);
9774   ASSERT(args.length() == 5);
9775 
9776   Handle<Object> callee = args.at<Object>(0);
9777 
9778   // If "eval" didn't refer to the original GlobalEval, it's not a
9779   // direct call to eval.
9780   // (And even if it is, but the first argument isn't a string, just let
9781   // execution default to an indirect call to eval, which will also return
9782   // the first argument without doing anything).
9783   if (*callee != isolate->native_context()->global_eval_fun() ||
9784       !args[1]->IsString()) {
9785     return MakePair(*callee, isolate->heap()->the_hole_value());
9786   }
9787 
9788   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9789   ASSERT(args[4]->IsSmi());
9790   return CompileGlobalEval(isolate,
9791                            args.at<String>(1),
9792                            args.at<Object>(2),
9793                            language_mode,
9794                            args.smi_at(4));
9795 }
9796 
9797 
9798 // Allocate a block of memory in the given space (filled with a filler).
9799 // Used as a fall-back for generated code when the space is full.
Allocate(Isolate * isolate,int size,bool double_align,AllocationSpace space)9800 static MaybeObject* Allocate(Isolate* isolate,
9801                              int size,
9802                              bool double_align,
9803                              AllocationSpace space) {
9804   Heap* heap = isolate->heap();
9805   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9806   RUNTIME_ASSERT(size > 0);
9807   RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize());
9808   HeapObject* allocation;
9809   { MaybeObject* maybe_allocation = heap->AllocateRaw(size, space, space);
9810     if (!maybe_allocation->To(&allocation)) return maybe_allocation;
9811   }
9812 #ifdef DEBUG
9813   MemoryChunk* chunk = MemoryChunk::FromAddress(allocation->address());
9814   ASSERT(chunk->owner()->identity() == space);
9815 #endif
9816   heap->CreateFillerObjectAt(allocation->address(), size);
9817   return allocation;
9818 }
9819 
9820 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AllocateInNewSpace)9821 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9822   SealHandleScope shs(isolate);
9823   ASSERT(args.length() == 1);
9824   CONVERT_SMI_ARG_CHECKED(size, 0);
9825   return Allocate(isolate, size, false, NEW_SPACE);
9826 }
9827 
9828 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AllocateInTargetSpace)9829 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInTargetSpace) {
9830   SealHandleScope shs(isolate);
9831   ASSERT(args.length() == 2);
9832   CONVERT_SMI_ARG_CHECKED(size, 0);
9833   CONVERT_SMI_ARG_CHECKED(flags, 1);
9834   bool double_align = AllocateDoubleAlignFlag::decode(flags);
9835   AllocationSpace space = AllocateTargetSpace::decode(flags);
9836   return Allocate(isolate, size, double_align, space);
9837 }
9838 
9839 
9840 // Push an object unto an array of objects if it is not already in the
9841 // array.  Returns true if the element was pushed on the stack and
9842 // false otherwise.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushIfAbsent)9843 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9844   HandleScope scope(isolate);
9845   ASSERT(args.length() == 2);
9846   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
9847   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, element, 1);
9848   RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9849   int length = Smi::cast(array->length())->value();
9850   FixedArray* elements = FixedArray::cast(array->elements());
9851   for (int i = 0; i < length; i++) {
9852     if (elements->get(i) == *element) return isolate->heap()->false_value();
9853   }
9854 
9855   // Strict not needed. Used for cycle detection in Array join implementation.
9856   RETURN_IF_EMPTY_HANDLE(isolate, JSObject::SetFastElement(array, length,
9857                                                            element,
9858                                                            kNonStrictMode,
9859                                                            true));
9860   return isolate->heap()->true_value();
9861 }
9862 
9863 
9864 /**
9865  * A simple visitor visits every element of Array's.
9866  * The backend storage can be a fixed array for fast elements case,
9867  * or a dictionary for sparse array. Since Dictionary is a subtype
9868  * of FixedArray, the class can be used by both fast and slow cases.
9869  * The second parameter of the constructor, fast_elements, specifies
9870  * whether the storage is a FixedArray or Dictionary.
9871  *
9872  * An index limit is used to deal with the situation that a result array
9873  * length overflows 32-bit non-negative integer.
9874  */
9875 class ArrayConcatVisitor {
9876  public:
ArrayConcatVisitor(Isolate * isolate,Handle<FixedArray> storage,bool fast_elements)9877   ArrayConcatVisitor(Isolate* isolate,
9878                      Handle<FixedArray> storage,
9879                      bool fast_elements) :
9880       isolate_(isolate),
9881       storage_(Handle<FixedArray>::cast(
9882           isolate->global_handles()->Create(*storage))),
9883       index_offset_(0u),
9884       fast_elements_(fast_elements),
9885       exceeds_array_limit_(false) { }
9886 
~ArrayConcatVisitor()9887   ~ArrayConcatVisitor() {
9888     clear_storage();
9889   }
9890 
visit(uint32_t i,Handle<Object> elm)9891   void visit(uint32_t i, Handle<Object> elm) {
9892     if (i > JSObject::kMaxElementCount - index_offset_) {
9893       exceeds_array_limit_ = true;
9894       return;
9895     }
9896     uint32_t index = index_offset_ + i;
9897 
9898     if (fast_elements_) {
9899       if (index < static_cast<uint32_t>(storage_->length())) {
9900         storage_->set(index, *elm);
9901         return;
9902       }
9903       // Our initial estimate of length was foiled, possibly by
9904       // getters on the arrays increasing the length of later arrays
9905       // during iteration.
9906       // This shouldn't happen in anything but pathological cases.
9907       SetDictionaryMode(index);
9908       // Fall-through to dictionary mode.
9909     }
9910     ASSERT(!fast_elements_);
9911     Handle<SeededNumberDictionary> dict(
9912         SeededNumberDictionary::cast(*storage_));
9913     Handle<SeededNumberDictionary> result =
9914         isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9915     if (!result.is_identical_to(dict)) {
9916       // Dictionary needed to grow.
9917       clear_storage();
9918       set_storage(*result);
9919     }
9920   }
9921 
increase_index_offset(uint32_t delta)9922   void increase_index_offset(uint32_t delta) {
9923     if (JSObject::kMaxElementCount - index_offset_ < delta) {
9924       index_offset_ = JSObject::kMaxElementCount;
9925     } else {
9926       index_offset_ += delta;
9927     }
9928   }
9929 
exceeds_array_limit()9930   bool exceeds_array_limit() {
9931     return exceeds_array_limit_;
9932   }
9933 
ToArray()9934   Handle<JSArray> ToArray() {
9935     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9936     Handle<Object> length =
9937         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9938     Handle<Map> map;
9939     if (fast_elements_) {
9940       map = isolate_->factory()->GetElementsTransitionMap(array,
9941                                                           FAST_HOLEY_ELEMENTS);
9942     } else {
9943       map = isolate_->factory()->GetElementsTransitionMap(array,
9944                                                           DICTIONARY_ELEMENTS);
9945     }
9946     array->set_map(*map);
9947     array->set_length(*length);
9948     array->set_elements(*storage_);
9949     return array;
9950   }
9951 
9952  private:
9953   // Convert storage to dictionary mode.
SetDictionaryMode(uint32_t index)9954   void SetDictionaryMode(uint32_t index) {
9955     ASSERT(fast_elements_);
9956     Handle<FixedArray> current_storage(*storage_);
9957     Handle<SeededNumberDictionary> slow_storage(
9958         isolate_->factory()->NewSeededNumberDictionary(
9959             current_storage->length()));
9960     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9961     for (uint32_t i = 0; i < current_length; i++) {
9962       HandleScope loop_scope(isolate_);
9963       Handle<Object> element(current_storage->get(i), isolate_);
9964       if (!element->IsTheHole()) {
9965         Handle<SeededNumberDictionary> new_storage =
9966           isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9967         if (!new_storage.is_identical_to(slow_storage)) {
9968           slow_storage = loop_scope.CloseAndEscape(new_storage);
9969         }
9970       }
9971     }
9972     clear_storage();
9973     set_storage(*slow_storage);
9974     fast_elements_ = false;
9975   }
9976 
clear_storage()9977   inline void clear_storage() {
9978     isolate_->global_handles()->Destroy(
9979         Handle<Object>::cast(storage_).location());
9980   }
9981 
set_storage(FixedArray * storage)9982   inline void set_storage(FixedArray* storage) {
9983     storage_ = Handle<FixedArray>::cast(
9984         isolate_->global_handles()->Create(storage));
9985   }
9986 
9987   Isolate* isolate_;
9988   Handle<FixedArray> storage_;  // Always a global handle.
9989   // Index after last seen index. Always less than or equal to
9990   // JSObject::kMaxElementCount.
9991   uint32_t index_offset_;
9992   bool fast_elements_ : 1;
9993   bool exceeds_array_limit_ : 1;
9994 };
9995 
9996 
EstimateElementCount(Handle<JSArray> array)9997 static uint32_t EstimateElementCount(Handle<JSArray> array) {
9998   uint32_t length = static_cast<uint32_t>(array->length()->Number());
9999   int element_count = 0;
10000   switch (array->GetElementsKind()) {
10001     case FAST_SMI_ELEMENTS:
10002     case FAST_HOLEY_SMI_ELEMENTS:
10003     case FAST_ELEMENTS:
10004     case FAST_HOLEY_ELEMENTS: {
10005       // Fast elements can't have lengths that are not representable by
10006       // a 32-bit signed integer.
10007       ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
10008       int fast_length = static_cast<int>(length);
10009       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
10010       for (int i = 0; i < fast_length; i++) {
10011         if (!elements->get(i)->IsTheHole()) element_count++;
10012       }
10013       break;
10014     }
10015     case FAST_DOUBLE_ELEMENTS:
10016     case FAST_HOLEY_DOUBLE_ELEMENTS: {
10017       // Fast elements can't have lengths that are not representable by
10018       // a 32-bit signed integer.
10019       ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
10020       int fast_length = static_cast<int>(length);
10021       if (array->elements()->IsFixedArray()) {
10022         ASSERT(FixedArray::cast(array->elements())->length() == 0);
10023         break;
10024       }
10025       Handle<FixedDoubleArray> elements(
10026           FixedDoubleArray::cast(array->elements()));
10027       for (int i = 0; i < fast_length; i++) {
10028         if (!elements->is_the_hole(i)) element_count++;
10029       }
10030       break;
10031     }
10032     case DICTIONARY_ELEMENTS: {
10033       Handle<SeededNumberDictionary> dictionary(
10034           SeededNumberDictionary::cast(array->elements()));
10035       int capacity = dictionary->Capacity();
10036       for (int i = 0; i < capacity; i++) {
10037         Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
10038         if (dictionary->IsKey(*key)) {
10039           element_count++;
10040         }
10041       }
10042       break;
10043     }
10044     case NON_STRICT_ARGUMENTS_ELEMENTS:
10045     case EXTERNAL_BYTE_ELEMENTS:
10046     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10047     case EXTERNAL_SHORT_ELEMENTS:
10048     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10049     case EXTERNAL_INT_ELEMENTS:
10050     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10051     case EXTERNAL_FLOAT_ELEMENTS:
10052     case EXTERNAL_DOUBLE_ELEMENTS:
10053     case EXTERNAL_PIXEL_ELEMENTS:
10054       // External arrays are always dense.
10055       return length;
10056   }
10057   // As an estimate, we assume that the prototype doesn't contain any
10058   // inherited elements.
10059   return element_count;
10060 }
10061 
10062 
10063 
10064 template<class ExternalArrayClass, class ElementType>
IterateExternalArrayElements(Isolate * isolate,Handle<JSObject> receiver,bool elements_are_ints,bool elements_are_guaranteed_smis,ArrayConcatVisitor * visitor)10065 static void IterateExternalArrayElements(Isolate* isolate,
10066                                          Handle<JSObject> receiver,
10067                                          bool elements_are_ints,
10068                                          bool elements_are_guaranteed_smis,
10069                                          ArrayConcatVisitor* visitor) {
10070   Handle<ExternalArrayClass> array(
10071       ExternalArrayClass::cast(receiver->elements()));
10072   uint32_t len = static_cast<uint32_t>(array->length());
10073 
10074   ASSERT(visitor != NULL);
10075   if (elements_are_ints) {
10076     if (elements_are_guaranteed_smis) {
10077       for (uint32_t j = 0; j < len; j++) {
10078         HandleScope loop_scope(isolate);
10079         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
10080                       isolate);
10081         visitor->visit(j, e);
10082       }
10083     } else {
10084       for (uint32_t j = 0; j < len; j++) {
10085         HandleScope loop_scope(isolate);
10086         int64_t val = static_cast<int64_t>(array->get_scalar(j));
10087         if (Smi::IsValid(static_cast<intptr_t>(val))) {
10088           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
10089           visitor->visit(j, e);
10090         } else {
10091           Handle<Object> e =
10092               isolate->factory()->NewNumber(static_cast<ElementType>(val));
10093           visitor->visit(j, e);
10094         }
10095       }
10096     }
10097   } else {
10098     for (uint32_t j = 0; j < len; j++) {
10099       HandleScope loop_scope(isolate);
10100       Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
10101       visitor->visit(j, e);
10102     }
10103   }
10104 }
10105 
10106 
10107 // Used for sorting indices in a List<uint32_t>.
compareUInt32(const uint32_t * ap,const uint32_t * bp)10108 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
10109   uint32_t a = *ap;
10110   uint32_t b = *bp;
10111   return (a == b) ? 0 : (a < b) ? -1 : 1;
10112 }
10113 
10114 
CollectElementIndices(Handle<JSObject> object,uint32_t range,List<uint32_t> * indices)10115 static void CollectElementIndices(Handle<JSObject> object,
10116                                   uint32_t range,
10117                                   List<uint32_t>* indices) {
10118   Isolate* isolate = object->GetIsolate();
10119   ElementsKind kind = object->GetElementsKind();
10120   switch (kind) {
10121     case FAST_SMI_ELEMENTS:
10122     case FAST_ELEMENTS:
10123     case FAST_HOLEY_SMI_ELEMENTS:
10124     case FAST_HOLEY_ELEMENTS: {
10125       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
10126       uint32_t length = static_cast<uint32_t>(elements->length());
10127       if (range < length) length = range;
10128       for (uint32_t i = 0; i < length; i++) {
10129         if (!elements->get(i)->IsTheHole()) {
10130           indices->Add(i);
10131         }
10132       }
10133       break;
10134     }
10135     case FAST_HOLEY_DOUBLE_ELEMENTS:
10136     case FAST_DOUBLE_ELEMENTS: {
10137       // TODO(1810): Decide if it's worthwhile to implement this.
10138       UNREACHABLE();
10139       break;
10140     }
10141     case DICTIONARY_ELEMENTS: {
10142       Handle<SeededNumberDictionary> dict(
10143           SeededNumberDictionary::cast(object->elements()));
10144       uint32_t capacity = dict->Capacity();
10145       for (uint32_t j = 0; j < capacity; j++) {
10146         HandleScope loop_scope(isolate);
10147         Handle<Object> k(dict->KeyAt(j), isolate);
10148         if (dict->IsKey(*k)) {
10149           ASSERT(k->IsNumber());
10150           uint32_t index = static_cast<uint32_t>(k->Number());
10151           if (index < range) {
10152             indices->Add(index);
10153           }
10154         }
10155       }
10156       break;
10157     }
10158     default: {
10159       int dense_elements_length;
10160       switch (kind) {
10161         case EXTERNAL_PIXEL_ELEMENTS: {
10162           dense_elements_length =
10163               ExternalPixelArray::cast(object->elements())->length();
10164           break;
10165         }
10166         case EXTERNAL_BYTE_ELEMENTS: {
10167           dense_elements_length =
10168               ExternalByteArray::cast(object->elements())->length();
10169           break;
10170         }
10171         case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10172           dense_elements_length =
10173               ExternalUnsignedByteArray::cast(object->elements())->length();
10174           break;
10175         }
10176         case EXTERNAL_SHORT_ELEMENTS: {
10177           dense_elements_length =
10178               ExternalShortArray::cast(object->elements())->length();
10179           break;
10180         }
10181         case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10182           dense_elements_length =
10183               ExternalUnsignedShortArray::cast(object->elements())->length();
10184           break;
10185         }
10186         case EXTERNAL_INT_ELEMENTS: {
10187           dense_elements_length =
10188               ExternalIntArray::cast(object->elements())->length();
10189           break;
10190         }
10191         case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10192           dense_elements_length =
10193               ExternalUnsignedIntArray::cast(object->elements())->length();
10194           break;
10195         }
10196         case EXTERNAL_FLOAT_ELEMENTS: {
10197           dense_elements_length =
10198               ExternalFloatArray::cast(object->elements())->length();
10199           break;
10200         }
10201         case EXTERNAL_DOUBLE_ELEMENTS: {
10202           dense_elements_length =
10203               ExternalDoubleArray::cast(object->elements())->length();
10204           break;
10205         }
10206         default:
10207           UNREACHABLE();
10208           dense_elements_length = 0;
10209           break;
10210       }
10211       uint32_t length = static_cast<uint32_t>(dense_elements_length);
10212       if (range <= length) {
10213         length = range;
10214         // We will add all indices, so we might as well clear it first
10215         // and avoid duplicates.
10216         indices->Clear();
10217       }
10218       for (uint32_t i = 0; i < length; i++) {
10219         indices->Add(i);
10220       }
10221       if (length == range) return;  // All indices accounted for already.
10222       break;
10223     }
10224   }
10225 
10226   Handle<Object> prototype(object->GetPrototype(), isolate);
10227   if (prototype->IsJSObject()) {
10228     // The prototype will usually have no inherited element indices,
10229     // but we have to check.
10230     CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
10231   }
10232 }
10233 
10234 
10235 /**
10236  * A helper function that visits elements of a JSArray in numerical
10237  * order.
10238  *
10239  * The visitor argument called for each existing element in the array
10240  * with the element index and the element's value.
10241  * Afterwards it increments the base-index of the visitor by the array
10242  * length.
10243  * Returns false if any access threw an exception, otherwise true.
10244  */
IterateElements(Isolate * isolate,Handle<JSArray> receiver,ArrayConcatVisitor * visitor)10245 static bool IterateElements(Isolate* isolate,
10246                             Handle<JSArray> receiver,
10247                             ArrayConcatVisitor* visitor) {
10248   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10249   switch (receiver->GetElementsKind()) {
10250     case FAST_SMI_ELEMENTS:
10251     case FAST_ELEMENTS:
10252     case FAST_HOLEY_SMI_ELEMENTS:
10253     case FAST_HOLEY_ELEMENTS: {
10254       // Run through the elements FixedArray and use HasElement and GetElement
10255       // to check the prototype for missing elements.
10256       Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10257       int fast_length = static_cast<int>(length);
10258       ASSERT(fast_length <= elements->length());
10259       for (int j = 0; j < fast_length; j++) {
10260         HandleScope loop_scope(isolate);
10261         Handle<Object> element_value(elements->get(j), isolate);
10262         if (!element_value->IsTheHole()) {
10263           visitor->visit(j, element_value);
10264         } else if (JSReceiver::HasElement(receiver, j)) {
10265           // Call GetElement on receiver, not its prototype, or getters won't
10266           // have the correct receiver.
10267           element_value = Object::GetElement(isolate, receiver, j);
10268           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10269           visitor->visit(j, element_value);
10270         }
10271       }
10272       break;
10273     }
10274     case FAST_HOLEY_DOUBLE_ELEMENTS:
10275     case FAST_DOUBLE_ELEMENTS: {
10276       // Run through the elements FixedArray and use HasElement and GetElement
10277       // to check the prototype for missing elements.
10278       Handle<FixedDoubleArray> elements(
10279           FixedDoubleArray::cast(receiver->elements()));
10280       int fast_length = static_cast<int>(length);
10281       ASSERT(fast_length <= elements->length());
10282       for (int j = 0; j < fast_length; j++) {
10283         HandleScope loop_scope(isolate);
10284         if (!elements->is_the_hole(j)) {
10285           double double_value = elements->get_scalar(j);
10286           Handle<Object> element_value =
10287               isolate->factory()->NewNumber(double_value);
10288           visitor->visit(j, element_value);
10289         } else if (JSReceiver::HasElement(receiver, j)) {
10290           // Call GetElement on receiver, not its prototype, or getters won't
10291           // have the correct receiver.
10292           Handle<Object> element_value =
10293               Object::GetElement(isolate, receiver, j);
10294           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10295           visitor->visit(j, element_value);
10296         }
10297       }
10298       break;
10299     }
10300     case DICTIONARY_ELEMENTS: {
10301       Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10302       List<uint32_t> indices(dict->Capacity() / 2);
10303       // Collect all indices in the object and the prototypes less
10304       // than length. This might introduce duplicates in the indices list.
10305       CollectElementIndices(receiver, length, &indices);
10306       indices.Sort(&compareUInt32);
10307       int j = 0;
10308       int n = indices.length();
10309       while (j < n) {
10310         HandleScope loop_scope(isolate);
10311         uint32_t index = indices[j];
10312         Handle<Object> element = Object::GetElement(isolate, receiver, index);
10313         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
10314         visitor->visit(index, element);
10315         // Skip to next different index (i.e., omit duplicates).
10316         do {
10317           j++;
10318         } while (j < n && indices[j] == index);
10319       }
10320       break;
10321     }
10322     case EXTERNAL_PIXEL_ELEMENTS: {
10323       Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
10324           receiver->elements()));
10325       for (uint32_t j = 0; j < length; j++) {
10326         Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10327         visitor->visit(j, e);
10328       }
10329       break;
10330     }
10331     case EXTERNAL_BYTE_ELEMENTS: {
10332       IterateExternalArrayElements<ExternalByteArray, int8_t>(
10333           isolate, receiver, true, true, visitor);
10334       break;
10335     }
10336     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10337       IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
10338           isolate, receiver, true, true, visitor);
10339       break;
10340     }
10341     case EXTERNAL_SHORT_ELEMENTS: {
10342       IterateExternalArrayElements<ExternalShortArray, int16_t>(
10343           isolate, receiver, true, true, visitor);
10344       break;
10345     }
10346     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10347       IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
10348           isolate, receiver, true, true, visitor);
10349       break;
10350     }
10351     case EXTERNAL_INT_ELEMENTS: {
10352       IterateExternalArrayElements<ExternalIntArray, int32_t>(
10353           isolate, receiver, true, false, visitor);
10354       break;
10355     }
10356     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10357       IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
10358           isolate, receiver, true, false, visitor);
10359       break;
10360     }
10361     case EXTERNAL_FLOAT_ELEMENTS: {
10362       IterateExternalArrayElements<ExternalFloatArray, float>(
10363           isolate, receiver, false, false, visitor);
10364       break;
10365     }
10366     case EXTERNAL_DOUBLE_ELEMENTS: {
10367       IterateExternalArrayElements<ExternalDoubleArray, double>(
10368           isolate, receiver, false, false, visitor);
10369       break;
10370     }
10371     default:
10372       UNREACHABLE();
10373       break;
10374   }
10375   visitor->increase_index_offset(length);
10376   return true;
10377 }
10378 
10379 
10380 /**
10381  * Array::concat implementation.
10382  * See ECMAScript 262, 15.4.4.4.
10383  * TODO(581): Fix non-compliance for very large concatenations and update to
10384  * following the ECMAScript 5 specification.
10385  */
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayConcat)10386 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
10387   HandleScope handle_scope(isolate);
10388   ASSERT(args.length() == 1);
10389 
10390   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10391   int argument_count = static_cast<int>(arguments->length()->Number());
10392   RUNTIME_ASSERT(arguments->HasFastObjectElements());
10393   Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10394 
10395   // Pass 1: estimate the length and number of elements of the result.
10396   // The actual length can be larger if any of the arguments have getters
10397   // that mutate other arguments (but will otherwise be precise).
10398   // The number of elements is precise if there are no inherited elements.
10399 
10400   ElementsKind kind = FAST_SMI_ELEMENTS;
10401 
10402   uint32_t estimate_result_length = 0;
10403   uint32_t estimate_nof_elements = 0;
10404   for (int i = 0; i < argument_count; i++) {
10405     HandleScope loop_scope(isolate);
10406     Handle<Object> obj(elements->get(i), isolate);
10407     uint32_t length_estimate;
10408     uint32_t element_estimate;
10409     if (obj->IsJSArray()) {
10410       Handle<JSArray> array(Handle<JSArray>::cast(obj));
10411       length_estimate = static_cast<uint32_t>(array->length()->Number());
10412       if (length_estimate != 0) {
10413         ElementsKind array_kind =
10414             GetPackedElementsKind(array->map()->elements_kind());
10415         if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10416           kind = array_kind;
10417         }
10418       }
10419       element_estimate = EstimateElementCount(array);
10420     } else {
10421       if (obj->IsHeapObject()) {
10422         if (obj->IsNumber()) {
10423           if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
10424             kind = FAST_DOUBLE_ELEMENTS;
10425           }
10426         } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
10427           kind = FAST_ELEMENTS;
10428         }
10429       }
10430       length_estimate = 1;
10431       element_estimate = 1;
10432     }
10433     // Avoid overflows by capping at kMaxElementCount.
10434     if (JSObject::kMaxElementCount - estimate_result_length <
10435         length_estimate) {
10436       estimate_result_length = JSObject::kMaxElementCount;
10437     } else {
10438       estimate_result_length += length_estimate;
10439     }
10440     if (JSObject::kMaxElementCount - estimate_nof_elements <
10441         element_estimate) {
10442       estimate_nof_elements = JSObject::kMaxElementCount;
10443     } else {
10444       estimate_nof_elements += element_estimate;
10445     }
10446   }
10447 
10448   // If estimated number of elements is more than half of length, a
10449   // fixed array (fast case) is more time and space-efficient than a
10450   // dictionary.
10451   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10452 
10453   Handle<FixedArray> storage;
10454   if (fast_case) {
10455     if (kind == FAST_DOUBLE_ELEMENTS) {
10456       Handle<FixedDoubleArray> double_storage =
10457           isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10458       int j = 0;
10459       bool failure = false;
10460       for (int i = 0; i < argument_count; i++) {
10461         Handle<Object> obj(elements->get(i), isolate);
10462         if (obj->IsSmi()) {
10463           double_storage->set(j, Smi::cast(*obj)->value());
10464           j++;
10465         } else if (obj->IsNumber()) {
10466           double_storage->set(j, obj->Number());
10467           j++;
10468         } else {
10469           JSArray* array = JSArray::cast(*obj);
10470           uint32_t length = static_cast<uint32_t>(array->length()->Number());
10471           switch (array->map()->elements_kind()) {
10472             case FAST_HOLEY_DOUBLE_ELEMENTS:
10473             case FAST_DOUBLE_ELEMENTS: {
10474               // Empty fixed array indicates that there are no elements.
10475               if (array->elements()->IsFixedArray()) break;
10476               FixedDoubleArray* elements =
10477                   FixedDoubleArray::cast(array->elements());
10478               for (uint32_t i = 0; i < length; i++) {
10479                 if (elements->is_the_hole(i)) {
10480                   failure = true;
10481                   break;
10482                 }
10483                 double double_value = elements->get_scalar(i);
10484                 double_storage->set(j, double_value);
10485                 j++;
10486               }
10487               break;
10488             }
10489             case FAST_HOLEY_SMI_ELEMENTS:
10490             case FAST_SMI_ELEMENTS: {
10491               FixedArray* elements(
10492                   FixedArray::cast(array->elements()));
10493               for (uint32_t i = 0; i < length; i++) {
10494                 Object* element = elements->get(i);
10495                 if (element->IsTheHole()) {
10496                   failure = true;
10497                   break;
10498                 }
10499                 int32_t int_value = Smi::cast(element)->value();
10500                 double_storage->set(j, int_value);
10501                 j++;
10502               }
10503               break;
10504             }
10505             case FAST_HOLEY_ELEMENTS:
10506               ASSERT_EQ(0, length);
10507               break;
10508             default:
10509               UNREACHABLE();
10510           }
10511         }
10512         if (failure) break;
10513       }
10514       Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10515       Smi* length = Smi::FromInt(j);
10516       Handle<Map> map;
10517       map = isolate->factory()->GetElementsTransitionMap(array, kind);
10518       array->set_map(*map);
10519       array->set_length(length);
10520       array->set_elements(*double_storage);
10521       return *array;
10522     }
10523     // The backing storage array must have non-existing elements to preserve
10524     // holes across concat operations.
10525     storage = isolate->factory()->NewFixedArrayWithHoles(
10526         estimate_result_length);
10527   } else {
10528     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10529     uint32_t at_least_space_for = estimate_nof_elements +
10530                                   (estimate_nof_elements >> 2);
10531     storage = Handle<FixedArray>::cast(
10532         isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
10533   }
10534 
10535   ArrayConcatVisitor visitor(isolate, storage, fast_case);
10536 
10537   for (int i = 0; i < argument_count; i++) {
10538     Handle<Object> obj(elements->get(i), isolate);
10539     if (obj->IsJSArray()) {
10540       Handle<JSArray> array = Handle<JSArray>::cast(obj);
10541       if (!IterateElements(isolate, array, &visitor)) {
10542         return Failure::Exception();
10543       }
10544     } else {
10545       visitor.visit(0, obj);
10546       visitor.increase_index_offset(1);
10547     }
10548   }
10549 
10550   if (visitor.exceeds_array_limit()) {
10551     return isolate->Throw(
10552         *isolate->factory()->NewRangeError("invalid_array_length",
10553                                            HandleVector<Object>(NULL, 0)));
10554   }
10555   return *visitor.ToArray();
10556 }
10557 
10558 
10559 // This will not allocate (flatten the string), but it may run
10560 // very slowly for very deeply nested ConsStrings.  For debugging use only.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GlobalPrint)10561 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10562   SealHandleScope shs(isolate);
10563   ASSERT(args.length() == 1);
10564 
10565   CONVERT_ARG_CHECKED(String, string, 0);
10566   ConsStringIteratorOp op;
10567   StringCharacterStream stream(string, &op);
10568   while (stream.HasMore()) {
10569     uint16_t character = stream.GetNext();
10570     PrintF("%c", character);
10571   }
10572   return string;
10573 }
10574 
10575 
10576 // Moves all own elements of an object, that are below a limit, to positions
10577 // starting at zero. All undefined values are placed after non-undefined values,
10578 // and are followed by non-existing element. Does not change the length
10579 // property.
10580 // Returns the number of non-undefined elements collected.
RUNTIME_FUNCTION(MaybeObject *,Runtime_RemoveArrayHoles)10581 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10582   HandleScope scope(isolate);
10583   ASSERT(args.length() == 2);
10584   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
10585   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10586   return *JSObject::PrepareElementsForSort(object, limit);
10587 }
10588 
10589 
10590 // Move contents of argument 0 (an array) to argument 1 (an array)
RUNTIME_FUNCTION(MaybeObject *,Runtime_MoveArrayContents)10591 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10592   SealHandleScope shs(isolate);
10593   ASSERT(args.length() == 2);
10594   CONVERT_ARG_CHECKED(JSArray, from, 0);
10595   CONVERT_ARG_CHECKED(JSArray, to, 1);
10596   from->ValidateElements();
10597   to->ValidateElements();
10598   FixedArrayBase* new_elements = from->elements();
10599   ElementsKind from_kind = from->GetElementsKind();
10600   MaybeObject* maybe_new_map;
10601   maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
10602   Object* new_map;
10603   if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10604   to->set_map_and_elements(Map::cast(new_map), new_elements);
10605   to->set_length(from->length());
10606   Object* obj;
10607   { MaybeObject* maybe_obj = from->ResetElements();
10608     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10609   }
10610   from->set_length(Smi::FromInt(0));
10611   to->ValidateElements();
10612   return to;
10613 }
10614 
10615 
10616 // How many elements does this object/array have?
RUNTIME_FUNCTION(MaybeObject *,Runtime_EstimateNumberOfElements)10617 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10618   SealHandleScope shs(isolate);
10619   ASSERT(args.length() == 1);
10620   CONVERT_ARG_CHECKED(JSObject, object, 0);
10621   HeapObject* elements = object->elements();
10622   if (elements->IsDictionary()) {
10623     int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10624     return Smi::FromInt(result);
10625   } else if (object->IsJSArray()) {
10626     return JSArray::cast(object)->length();
10627   } else {
10628     return Smi::FromInt(FixedArray::cast(elements)->length());
10629   }
10630 }
10631 
10632 
10633 // Returns an array that tells you where in the [0, length) interval an array
10634 // might have elements.  Can either return an array of keys (positive integers
10635 // or undefined) or a number representing the positive length of an interval
10636 // starting at index 0.
10637 // Intervals can span over some keys that are not in the object.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetArrayKeys)10638 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10639   HandleScope scope(isolate);
10640   ASSERT(args.length() == 2);
10641   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10642   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10643   if (array->elements()->IsDictionary()) {
10644     Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10645     for (Handle<Object> p = array;
10646          !p->IsNull();
10647          p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
10648       if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
10649         // Bail out if we find a proxy or interceptor, likely not worth
10650         // collecting keys in that case.
10651         return *isolate->factory()->NewNumberFromUint(length);
10652       }
10653       Handle<JSObject> current = Handle<JSObject>::cast(p);
10654       Handle<FixedArray> current_keys =
10655           isolate->factory()->NewFixedArray(
10656               current->NumberOfLocalElements(NONE));
10657       current->GetLocalElementKeys(*current_keys, NONE);
10658       keys = UnionOfKeys(keys, current_keys);
10659     }
10660     // Erase any keys >= length.
10661     // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10662     // is changed to let this happen on the JS side.
10663     for (int i = 0; i < keys->length(); i++) {
10664       if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10665     }
10666     return *isolate->factory()->NewJSArrayWithElements(keys);
10667   } else {
10668     ASSERT(array->HasFastSmiOrObjectElements() ||
10669            array->HasFastDoubleElements());
10670     uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10671     return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10672   }
10673 }
10674 
10675 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LookupAccessor)10676 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10677   HandleScope scope(isolate);
10678   ASSERT(args.length() == 3);
10679   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
10680   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10681   CONVERT_SMI_ARG_CHECKED(flag, 2);
10682   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10683   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10684   Handle<Object> result =
10685       JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component);
10686   RETURN_IF_EMPTY_HANDLE(isolate, result);
10687   return *result;
10688 }
10689 
10690 
10691 #ifdef ENABLE_DEBUGGER_SUPPORT
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugBreak)10692 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10693   SealHandleScope shs(isolate);
10694   ASSERT(args.length() == 0);
10695   return Execution::DebugBreakHelper(isolate);
10696 }
10697 
10698 
10699 // Helper functions for wrapping and unwrapping stack frame ids.
WrapFrameId(StackFrame::Id id)10700 static Smi* WrapFrameId(StackFrame::Id id) {
10701   ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10702   return Smi::FromInt(id >> 2);
10703 }
10704 
10705 
UnwrapFrameId(int wrapped)10706 static StackFrame::Id UnwrapFrameId(int wrapped) {
10707   return static_cast<StackFrame::Id>(wrapped << 2);
10708 }
10709 
10710 
10711 // Adds a JavaScript function as a debug event listener.
10712 // args[0]: debug event listener function to set or null or undefined for
10713 //          clearing the event listener function
10714 // args[1]: object supplied during callback
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDebugEventListener)10715 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10716   SealHandleScope shs(isolate);
10717   ASSERT(args.length() == 2);
10718   RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10719                  args[0]->IsUndefined() ||
10720                  args[0]->IsNull());
10721   Handle<Object> callback = args.at<Object>(0);
10722   Handle<Object> data = args.at<Object>(1);
10723   isolate->debugger()->SetEventListener(callback, data);
10724 
10725   return isolate->heap()->undefined_value();
10726 }
10727 
10728 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Break)10729 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10730   SealHandleScope shs(isolate);
10731   ASSERT(args.length() == 0);
10732   isolate->stack_guard()->DebugBreak();
10733   return isolate->heap()->undefined_value();
10734 }
10735 
10736 
DebugLookupResultValue(Heap * heap,Object * receiver,Name * name,LookupResult * result,bool * caught_exception)10737 static MaybeObject* DebugLookupResultValue(Heap* heap,
10738                                            Object* receiver,
10739                                            Name* name,
10740                                            LookupResult* result,
10741                                            bool* caught_exception) {
10742   Object* value;
10743   switch (result->type()) {
10744     case NORMAL:
10745       value = result->holder()->GetNormalizedProperty(result);
10746       if (value->IsTheHole()) {
10747         return heap->undefined_value();
10748       }
10749       return value;
10750     case FIELD: {
10751       Object* value;
10752       MaybeObject* maybe_value =
10753           JSObject::cast(result->holder())->FastPropertyAt(
10754               result->representation(),
10755               result->GetFieldIndex().field_index());
10756       if (!maybe_value->To(&value)) return maybe_value;
10757       if (value->IsTheHole()) {
10758         return heap->undefined_value();
10759       }
10760       return value;
10761     }
10762     case CONSTANT:
10763       return result->GetConstant();
10764     case CALLBACKS: {
10765       Object* structure = result->GetCallbackObject();
10766       if (structure->IsForeign() || structure->IsAccessorInfo()) {
10767         Isolate* isolate = heap->isolate();
10768         HandleScope scope(isolate);
10769         Handle<Object> value = JSObject::GetPropertyWithCallback(
10770             handle(result->holder(), isolate),
10771             handle(receiver, isolate),
10772             handle(structure, isolate),
10773             handle(name, isolate));
10774         if (value.is_null()) {
10775           MaybeObject* exception = heap->isolate()->pending_exception();
10776           heap->isolate()->clear_pending_exception();
10777           if (caught_exception != NULL) *caught_exception = true;
10778           return exception;
10779         }
10780         return *value;
10781       } else {
10782         return heap->undefined_value();
10783       }
10784     }
10785     case INTERCEPTOR:
10786     case TRANSITION:
10787       return heap->undefined_value();
10788     case HANDLER:
10789     case NONEXISTENT:
10790       UNREACHABLE();
10791       return heap->undefined_value();
10792   }
10793   UNREACHABLE();  // keep the compiler happy
10794   return heap->undefined_value();
10795 }
10796 
10797 
10798 // Get debugger related details for an object property.
10799 // args[0]: object holding property
10800 // args[1]: name of the property
10801 //
10802 // The array returned contains the following information:
10803 // 0: Property value
10804 // 1: Property details
10805 // 2: Property value is exception
10806 // 3: Getter function if defined
10807 // 4: Setter function if defined
10808 // Items 2-4 are only filled if the property has either a getter or a setter
10809 // defined through __defineGetter__ and/or __defineSetter__.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetPropertyDetails)10810 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10811   HandleScope scope(isolate);
10812 
10813   ASSERT(args.length() == 2);
10814 
10815   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10816   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10817 
10818   // Make sure to set the current context to the context before the debugger was
10819   // entered (if the debugger is entered). The reason for switching context here
10820   // is that for some property lookups (accessors and interceptors) callbacks
10821   // into the embedding application can occour, and the embedding application
10822   // could have the assumption that its own native context is the current
10823   // context and not some internal debugger context.
10824   SaveContext save(isolate);
10825   if (isolate->debug()->InDebugger()) {
10826     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10827   }
10828 
10829   // Skip the global proxy as it has no properties and always delegates to the
10830   // real global object.
10831   if (obj->IsJSGlobalProxy()) {
10832     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10833   }
10834 
10835 
10836   // Check if the name is trivially convertible to an index and get the element
10837   // if so.
10838   uint32_t index;
10839   if (name->AsArrayIndex(&index)) {
10840     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10841     Object* element_or_char;
10842     { MaybeObject* maybe_element_or_char =
10843           Runtime::GetElementOrCharAt(isolate, obj, index);
10844       if (!maybe_element_or_char->ToObject(&element_or_char)) {
10845         return maybe_element_or_char;
10846       }
10847     }
10848     details->set(0, element_or_char);
10849     details->set(
10850         1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
10851     return *isolate->factory()->NewJSArrayWithElements(details);
10852   }
10853 
10854   // Find the number of objects making up this.
10855   int length = LocalPrototypeChainLength(*obj);
10856 
10857   // Try local lookup on each of the objects.
10858   Handle<JSObject> jsproto = obj;
10859   for (int i = 0; i < length; i++) {
10860     LookupResult result(isolate);
10861     jsproto->LocalLookup(*name, &result);
10862     if (result.IsFound()) {
10863       // LookupResult is not GC safe as it holds raw object pointers.
10864       // GC can happen later in this code so put the required fields into
10865       // local variables using handles when required for later use.
10866       Handle<Object> result_callback_obj;
10867       if (result.IsPropertyCallbacks()) {
10868         result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10869                                              isolate);
10870       }
10871       Smi* property_details = result.GetPropertyDetails().AsSmi();
10872       // DebugLookupResultValue can cause GC so details from LookupResult needs
10873       // to be copied to handles before this.
10874       bool caught_exception = false;
10875       Object* raw_value;
10876       { MaybeObject* maybe_raw_value =
10877             DebugLookupResultValue(isolate->heap(), *obj, *name,
10878                                    &result, &caught_exception);
10879         if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10880       }
10881       Handle<Object> value(raw_value, isolate);
10882 
10883       // If the callback object is a fixed array then it contains JavaScript
10884       // getter and/or setter.
10885       bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
10886                                     result_callback_obj->IsAccessorPair();
10887       Handle<FixedArray> details =
10888           isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10889       details->set(0, *value);
10890       details->set(1, property_details);
10891       if (hasJavaScriptAccessors) {
10892         AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10893         details->set(2, isolate->heap()->ToBoolean(caught_exception));
10894         details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10895         details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10896       }
10897 
10898       return *isolate->factory()->NewJSArrayWithElements(details);
10899     }
10900     if (i < length - 1) {
10901       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10902     }
10903   }
10904 
10905   return isolate->heap()->undefined_value();
10906 }
10907 
10908 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetProperty)10909 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10910   HandleScope scope(isolate);
10911 
10912   ASSERT(args.length() == 2);
10913 
10914   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10915   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10916 
10917   LookupResult result(isolate);
10918   obj->Lookup(*name, &result);
10919   if (result.IsFound()) {
10920     return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10921   }
10922   return isolate->heap()->undefined_value();
10923 }
10924 
10925 
10926 // Return the property type calculated from the property details.
10927 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyTypeFromDetails)10928 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10929   SealHandleScope shs(isolate);
10930   ASSERT(args.length() == 1);
10931   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10932   return Smi::FromInt(static_cast<int>(details.type()));
10933 }
10934 
10935 
10936 // Return the property attribute calculated from the property details.
10937 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyAttributesFromDetails)10938 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10939   SealHandleScope shs(isolate);
10940   ASSERT(args.length() == 1);
10941   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10942   return Smi::FromInt(static_cast<int>(details.attributes()));
10943 }
10944 
10945 
10946 // Return the property insertion index calculated from the property details.
10947 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyIndexFromDetails)10948 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10949   SealHandleScope shs(isolate);
10950   ASSERT(args.length() == 1);
10951   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10952   // TODO(verwaest): Depends on the type of details.
10953   return Smi::FromInt(details.dictionary_index());
10954 }
10955 
10956 
10957 // Return property value from named interceptor.
10958 // args[0]: object
10959 // args[1]: property name
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugNamedInterceptorPropertyValue)10960 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10961   HandleScope scope(isolate);
10962   ASSERT(args.length() == 2);
10963   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10964   RUNTIME_ASSERT(obj->HasNamedInterceptor());
10965   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10966 
10967   PropertyAttributes attributes;
10968   Handle<Object> result =
10969       JSObject::GetPropertyWithInterceptor(obj, obj, name, &attributes);
10970   RETURN_IF_EMPTY_HANDLE(isolate, result);
10971   return *result;
10972 }
10973 
10974 
10975 // Return element value from indexed interceptor.
10976 // args[0]: object
10977 // args[1]: index
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugIndexedInterceptorElementValue)10978 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10979   HandleScope scope(isolate);
10980   ASSERT(args.length() == 2);
10981   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10982   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10983   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10984 
10985   return obj->GetElementWithInterceptor(*obj, index);
10986 }
10987 
10988 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CheckExecutionState)10989 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10990   SealHandleScope shs(isolate);
10991   ASSERT(args.length() >= 1);
10992   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10993   // Check that the break id is valid.
10994   if (isolate->debug()->break_id() == 0 ||
10995       break_id != isolate->debug()->break_id()) {
10996     return isolate->Throw(
10997         isolate->heap()->illegal_execution_state_string());
10998   }
10999 
11000   return isolate->heap()->true_value();
11001 }
11002 
11003 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFrameCount)11004 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
11005   HandleScope scope(isolate);
11006   ASSERT(args.length() == 1);
11007 
11008   // Check arguments.
11009   Object* result;
11010   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11011       RUNTIME_ARGUMENTS(isolate, args));
11012     if (!maybe_result->ToObject(&result)) return maybe_result;
11013   }
11014 
11015   // Count all frames which are relevant to debugging stack trace.
11016   int n = 0;
11017   StackFrame::Id id = isolate->debug()->break_frame_id();
11018   if (id == StackFrame::NO_ID) {
11019     // If there is no JavaScript stack frame count is 0.
11020     return Smi::FromInt(0);
11021   }
11022 
11023   for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
11024     n += it.frame()->GetInlineCount();
11025   }
11026   return Smi::FromInt(n);
11027 }
11028 
11029 
11030 class FrameInspector {
11031  public:
FrameInspector(JavaScriptFrame * frame,int inlined_jsframe_index,Isolate * isolate)11032   FrameInspector(JavaScriptFrame* frame,
11033                  int inlined_jsframe_index,
11034                  Isolate* isolate)
11035       : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
11036     // Calculate the deoptimized frame.
11037     if (frame->is_optimized()) {
11038       deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
11039           frame, inlined_jsframe_index, isolate);
11040     }
11041     has_adapted_arguments_ = frame_->has_adapted_arguments();
11042     is_bottommost_ = inlined_jsframe_index == 0;
11043     is_optimized_ = frame_->is_optimized();
11044   }
11045 
~FrameInspector()11046   ~FrameInspector() {
11047     // Get rid of the calculated deoptimized frame if any.
11048     if (deoptimized_frame_ != NULL) {
11049       Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
11050                                                   isolate_);
11051     }
11052   }
11053 
GetParametersCount()11054   int GetParametersCount() {
11055     return is_optimized_
11056         ? deoptimized_frame_->parameters_count()
11057         : frame_->ComputeParametersCount();
11058   }
expression_count()11059   int expression_count() { return deoptimized_frame_->expression_count(); }
GetFunction()11060   Object* GetFunction() {
11061     return is_optimized_
11062         ? deoptimized_frame_->GetFunction()
11063         : frame_->function();
11064   }
GetParameter(int index)11065   Object* GetParameter(int index) {
11066     return is_optimized_
11067         ? deoptimized_frame_->GetParameter(index)
11068         : frame_->GetParameter(index);
11069   }
GetExpression(int index)11070   Object* GetExpression(int index) {
11071     return is_optimized_
11072         ? deoptimized_frame_->GetExpression(index)
11073         : frame_->GetExpression(index);
11074   }
GetSourcePosition()11075   int GetSourcePosition() {
11076     return is_optimized_
11077         ? deoptimized_frame_->GetSourcePosition()
11078         : frame_->LookupCode()->SourcePosition(frame_->pc());
11079   }
IsConstructor()11080   bool IsConstructor() {
11081     return is_optimized_ && !is_bottommost_
11082         ? deoptimized_frame_->HasConstructStub()
11083         : frame_->IsConstructor();
11084   }
11085 
11086   // To inspect all the provided arguments the frame might need to be
11087   // replaced with the arguments frame.
SetArgumentsFrame(JavaScriptFrame * frame)11088   void SetArgumentsFrame(JavaScriptFrame* frame) {
11089     ASSERT(has_adapted_arguments_);
11090     frame_ = frame;
11091     is_optimized_ = frame_->is_optimized();
11092     ASSERT(!is_optimized_);
11093   }
11094 
11095  private:
11096   JavaScriptFrame* frame_;
11097   DeoptimizedFrameInfo* deoptimized_frame_;
11098   Isolate* isolate_;
11099   bool is_optimized_;
11100   bool is_bottommost_;
11101   bool has_adapted_arguments_;
11102 
11103   DISALLOW_COPY_AND_ASSIGN(FrameInspector);
11104 };
11105 
11106 
11107 static const int kFrameDetailsFrameIdIndex = 0;
11108 static const int kFrameDetailsReceiverIndex = 1;
11109 static const int kFrameDetailsFunctionIndex = 2;
11110 static const int kFrameDetailsArgumentCountIndex = 3;
11111 static const int kFrameDetailsLocalCountIndex = 4;
11112 static const int kFrameDetailsSourcePositionIndex = 5;
11113 static const int kFrameDetailsConstructCallIndex = 6;
11114 static const int kFrameDetailsAtReturnIndex = 7;
11115 static const int kFrameDetailsFlagsIndex = 8;
11116 static const int kFrameDetailsFirstDynamicIndex = 9;
11117 
11118 
FindSavedContextForFrame(Isolate * isolate,JavaScriptFrame * frame)11119 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
11120                                              JavaScriptFrame* frame) {
11121   SaveContext* save = isolate->save_context();
11122   while (save != NULL && !save->IsBelowFrame(frame)) {
11123     save = save->prev();
11124   }
11125   ASSERT(save != NULL);
11126   return save;
11127 }
11128 
11129 
11130 // Return an array with frame details
11131 // args[0]: number: break id
11132 // args[1]: number: frame index
11133 //
11134 // The array returned contains the following information:
11135 // 0: Frame id
11136 // 1: Receiver
11137 // 2: Function
11138 // 3: Argument count
11139 // 4: Local count
11140 // 5: Source position
11141 // 6: Constructor call
11142 // 7: Is at return
11143 // 8: Flags
11144 // Arguments name, value
11145 // Locals name, value
11146 // Return value if any
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFrameDetails)11147 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
11148   HandleScope scope(isolate);
11149   ASSERT(args.length() == 2);
11150 
11151   // Check arguments.
11152   Object* check;
11153   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11154       RUNTIME_ARGUMENTS(isolate, args));
11155     if (!maybe_check->ToObject(&check)) return maybe_check;
11156   }
11157   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11158   Heap* heap = isolate->heap();
11159 
11160   // Find the relevant frame with the requested index.
11161   StackFrame::Id id = isolate->debug()->break_frame_id();
11162   if (id == StackFrame::NO_ID) {
11163     // If there are no JavaScript stack frames return undefined.
11164     return heap->undefined_value();
11165   }
11166 
11167   int count = 0;
11168   JavaScriptFrameIterator it(isolate, id);
11169   for (; !it.done(); it.Advance()) {
11170     if (index < count + it.frame()->GetInlineCount()) break;
11171     count += it.frame()->GetInlineCount();
11172   }
11173   if (it.done()) return heap->undefined_value();
11174 
11175   bool is_optimized = it.frame()->is_optimized();
11176 
11177   int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
11178   if (is_optimized) {
11179     inlined_jsframe_index =
11180         it.frame()->GetInlineCount() - (index - count) - 1;
11181   }
11182   FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11183 
11184   // Traverse the saved contexts chain to find the active context for the
11185   // selected frame.
11186   SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11187 
11188   // Get the frame id.
11189   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11190 
11191   // Find source position in unoptimized code.
11192   int position = frame_inspector.GetSourcePosition();
11193 
11194   // Check for constructor frame.
11195   bool constructor = frame_inspector.IsConstructor();
11196 
11197   // Get scope info and read from it for local variable information.
11198   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11199   Handle<SharedFunctionInfo> shared(function->shared());
11200   Handle<ScopeInfo> scope_info(shared->scope_info());
11201   ASSERT(*scope_info != ScopeInfo::Empty(isolate));
11202 
11203   // Get the locals names and values into a temporary array.
11204   //
11205   // TODO(1240907): Hide compiler-introduced stack variables
11206   // (e.g. .result)?  For users of the debugger, they will probably be
11207   // confusing.
11208   Handle<FixedArray> locals =
11209       isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
11210 
11211   // Fill in the values of the locals.
11212   int i = 0;
11213   for (; i < scope_info->StackLocalCount(); ++i) {
11214     // Use the value from the stack.
11215     locals->set(i * 2, scope_info->LocalName(i));
11216     locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
11217   }
11218   if (i < scope_info->LocalCount()) {
11219     // Get the context containing declarations.
11220     Handle<Context> context(
11221         Context::cast(it.frame()->context())->declaration_context());
11222     for (; i < scope_info->LocalCount(); ++i) {
11223       Handle<String> name(scope_info->LocalName(i));
11224       VariableMode mode;
11225       InitializationFlag init_flag;
11226       locals->set(i * 2, *name);
11227       locals->set(i * 2 + 1, context->get(
11228           scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
11229     }
11230   }
11231 
11232   // Check whether this frame is positioned at return. If not top
11233   // frame or if the frame is optimized it cannot be at a return.
11234   bool at_return = false;
11235   if (!is_optimized && index == 0) {
11236     at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11237   }
11238 
11239   // If positioned just before return find the value to be returned and add it
11240   // to the frame information.
11241   Handle<Object> return_value = isolate->factory()->undefined_value();
11242   if (at_return) {
11243     StackFrameIterator it2(isolate);
11244     Address internal_frame_sp = NULL;
11245     while (!it2.done()) {
11246       if (it2.frame()->is_internal()) {
11247         internal_frame_sp = it2.frame()->sp();
11248       } else {
11249         if (it2.frame()->is_java_script()) {
11250           if (it2.frame()->id() == it.frame()->id()) {
11251             // The internal frame just before the JavaScript frame contains the
11252             // value to return on top. A debug break at return will create an
11253             // internal frame to store the return value (eax/rax/r0) before
11254             // entering the debug break exit frame.
11255             if (internal_frame_sp != NULL) {
11256               return_value =
11257                   Handle<Object>(Memory::Object_at(internal_frame_sp),
11258                                  isolate);
11259               break;
11260             }
11261           }
11262         }
11263 
11264         // Indicate that the previous frame was not an internal frame.
11265         internal_frame_sp = NULL;
11266       }
11267       it2.Advance();
11268     }
11269   }
11270 
11271   // Now advance to the arguments adapter frame (if any). It contains all
11272   // the provided parameters whereas the function frame always have the number
11273   // of arguments matching the functions parameters. The rest of the
11274   // information (except for what is collected above) is the same.
11275   if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11276     it.AdvanceToArgumentsFrame();
11277     frame_inspector.SetArgumentsFrame(it.frame());
11278   }
11279 
11280   // Find the number of arguments to fill. At least fill the number of
11281   // parameters for the function and fill more if more parameters are provided.
11282   int argument_count = scope_info->ParameterCount();
11283   if (argument_count < frame_inspector.GetParametersCount()) {
11284     argument_count = frame_inspector.GetParametersCount();
11285   }
11286 
11287   // Calculate the size of the result.
11288   int details_size = kFrameDetailsFirstDynamicIndex +
11289                      2 * (argument_count + scope_info->LocalCount()) +
11290                      (at_return ? 1 : 0);
11291   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11292 
11293   // Add the frame id.
11294   details->set(kFrameDetailsFrameIdIndex, *frame_id);
11295 
11296   // Add the function (same as in function frame).
11297   details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11298 
11299   // Add the arguments count.
11300   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11301 
11302   // Add the locals count
11303   details->set(kFrameDetailsLocalCountIndex,
11304                Smi::FromInt(scope_info->LocalCount()));
11305 
11306   // Add the source position.
11307   if (position != RelocInfo::kNoPosition) {
11308     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11309   } else {
11310     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11311   }
11312 
11313   // Add the constructor information.
11314   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11315 
11316   // Add the at return information.
11317   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11318 
11319   // Add flags to indicate information on whether this frame is
11320   //   bit 0: invoked in the debugger context.
11321   //   bit 1: optimized frame.
11322   //   bit 2: inlined in optimized frame
11323   int flags = 0;
11324   if (*save->context() == *isolate->debug()->debug_context()) {
11325     flags |= 1 << 0;
11326   }
11327   if (is_optimized) {
11328     flags |= 1 << 1;
11329     flags |= inlined_jsframe_index << 2;
11330   }
11331   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11332 
11333   // Fill the dynamic part.
11334   int details_index = kFrameDetailsFirstDynamicIndex;
11335 
11336   // Add arguments name and value.
11337   for (int i = 0; i < argument_count; i++) {
11338     // Name of the argument.
11339     if (i < scope_info->ParameterCount()) {
11340       details->set(details_index++, scope_info->ParameterName(i));
11341     } else {
11342       details->set(details_index++, heap->undefined_value());
11343     }
11344 
11345     // Parameter value.
11346     if (i < frame_inspector.GetParametersCount()) {
11347       // Get the value from the stack.
11348       details->set(details_index++, frame_inspector.GetParameter(i));
11349     } else {
11350       details->set(details_index++, heap->undefined_value());
11351     }
11352   }
11353 
11354   // Add locals name and value from the temporary copy from the function frame.
11355   for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
11356     details->set(details_index++, locals->get(i));
11357   }
11358 
11359   // Add the value being returned.
11360   if (at_return) {
11361     details->set(details_index++, *return_value);
11362   }
11363 
11364   // Add the receiver (same as in function frame).
11365   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11366   // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11367   Handle<Object> receiver(it.frame()->receiver(), isolate);
11368   if (!receiver->IsJSObject() &&
11369       shared->is_classic_mode() &&
11370       !function->IsBuiltin()) {
11371     // If the receiver is not a JSObject and the function is not a
11372     // builtin or strict-mode we have hit an optimization where a
11373     // value object is not converted into a wrapped JS objects. To
11374     // hide this optimization from the debugger, we wrap the receiver
11375     // by creating correct wrapper object based on the calling frame's
11376     // native context.
11377     it.Advance();
11378     Handle<Context> calling_frames_native_context(
11379         Context::cast(Context::cast(it.frame()->context())->native_context()));
11380     ASSERT(!receiver->IsUndefined() && !receiver->IsNull());
11381     receiver =
11382         isolate->factory()->ToObject(receiver, calling_frames_native_context);
11383   }
11384   details->set(kFrameDetailsReceiverIndex, *receiver);
11385 
11386   ASSERT_EQ(details_size, details_index);
11387   return *isolate->factory()->NewJSArrayWithElements(details);
11388 }
11389 
11390 
11391 // Create a plain JSObject which materializes the local scope for the specified
11392 // frame.
MaterializeStackLocalsWithFrameInspector(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function,FrameInspector * frame_inspector)11393 static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
11394     Isolate* isolate,
11395     Handle<JSObject> target,
11396     Handle<JSFunction> function,
11397     FrameInspector* frame_inspector) {
11398   Handle<SharedFunctionInfo> shared(function->shared());
11399   Handle<ScopeInfo> scope_info(shared->scope_info());
11400 
11401   // First fill all parameters.
11402   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11403     Handle<Object> value(i < frame_inspector->GetParametersCount()
11404                              ? frame_inspector->GetParameter(i)
11405                              : isolate->heap()->undefined_value(),
11406                          isolate);
11407     ASSERT(!value->IsTheHole());
11408 
11409     RETURN_IF_EMPTY_HANDLE_VALUE(
11410         isolate,
11411         Runtime::SetObjectProperty(isolate,
11412                                    target,
11413                                    Handle<String>(scope_info->ParameterName(i)),
11414                                    value,
11415                                    NONE,
11416                                    kNonStrictMode),
11417         Handle<JSObject>());
11418   }
11419 
11420   // Second fill all stack locals.
11421   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11422     Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11423     if (value->IsTheHole()) continue;
11424 
11425     RETURN_IF_EMPTY_HANDLE_VALUE(
11426         isolate,
11427         Runtime::SetObjectProperty(
11428             isolate,
11429             target,
11430             Handle<String>(scope_info->StackLocalName(i)),
11431             value,
11432             NONE,
11433             kNonStrictMode),
11434         Handle<JSObject>());
11435   }
11436 
11437   return target;
11438 }
11439 
11440 
UpdateStackLocalsFromMaterializedObject(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function,JavaScriptFrame * frame,int inlined_jsframe_index)11441 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11442                                                     Handle<JSObject> target,
11443                                                     Handle<JSFunction> function,
11444                                                     JavaScriptFrame* frame,
11445                                                     int inlined_jsframe_index) {
11446   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11447     // Optimized frames are not supported.
11448     // TODO(yangguo): make sure all code deoptimized when debugger is active
11449     //                and assert that this cannot happen.
11450     return;
11451   }
11452 
11453   Handle<SharedFunctionInfo> shared(function->shared());
11454   Handle<ScopeInfo> scope_info(shared->scope_info());
11455 
11456   // Parameters.
11457   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11458     ASSERT(!frame->GetParameter(i)->IsTheHole());
11459     HandleScope scope(isolate);
11460     Handle<Object> value = GetProperty(
11461         isolate, target, Handle<String>(scope_info->ParameterName(i)));
11462     frame->SetParameterValue(i, *value);
11463   }
11464 
11465   // Stack locals.
11466   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11467     if (frame->GetExpression(i)->IsTheHole()) continue;
11468     HandleScope scope(isolate);
11469     Handle<Object> value = GetProperty(
11470         isolate, target, Handle<String>(scope_info->StackLocalName(i)));
11471     frame->SetExpression(i, *value);
11472   }
11473 }
11474 
11475 
MaterializeLocalContext(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function,JavaScriptFrame * frame)11476 static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
11477                                                 Handle<JSObject> target,
11478                                                 Handle<JSFunction> function,
11479                                                 JavaScriptFrame* frame) {
11480   HandleScope scope(isolate);
11481   Handle<SharedFunctionInfo> shared(function->shared());
11482   Handle<ScopeInfo> scope_info(shared->scope_info());
11483 
11484   if (!scope_info->HasContext()) return target;
11485 
11486   // Third fill all context locals.
11487   Handle<Context> frame_context(Context::cast(frame->context()));
11488   Handle<Context> function_context(frame_context->declaration_context());
11489   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11490           scope_info, function_context, target)) {
11491     return Handle<JSObject>();
11492   }
11493 
11494   // Finally copy any properties from the function context extension.
11495   // These will be variables introduced by eval.
11496   if (function_context->closure() == *function) {
11497     if (function_context->has_extension() &&
11498         !function_context->IsNativeContext()) {
11499       Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11500       bool threw = false;
11501       Handle<FixedArray> keys =
11502           GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11503       if (threw) return Handle<JSObject>();
11504 
11505       for (int i = 0; i < keys->length(); i++) {
11506         // Names of variables introduced by eval are strings.
11507         ASSERT(keys->get(i)->IsString());
11508         Handle<String> key(String::cast(keys->get(i)));
11509         RETURN_IF_EMPTY_HANDLE_VALUE(
11510             isolate,
11511             Runtime::SetObjectProperty(isolate,
11512                                        target,
11513                                        key,
11514                                        GetProperty(isolate, ext, key),
11515                                        NONE,
11516                                        kNonStrictMode),
11517             Handle<JSObject>());
11518       }
11519     }
11520   }
11521 
11522   return target;
11523 }
11524 
11525 
MaterializeLocalScope(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index)11526 static Handle<JSObject> MaterializeLocalScope(
11527     Isolate* isolate,
11528     JavaScriptFrame* frame,
11529     int inlined_jsframe_index) {
11530   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11531   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11532 
11533   Handle<JSObject> local_scope =
11534       isolate->factory()->NewJSObject(isolate->object_function());
11535   local_scope = MaterializeStackLocalsWithFrameInspector(
11536                     isolate, local_scope, function, &frame_inspector);
11537   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
11538 
11539   return MaterializeLocalContext(isolate, local_scope, function, frame);
11540 }
11541 
11542 
11543 // Set the context local variable value.
SetContextLocalValue(Isolate * isolate,Handle<ScopeInfo> scope_info,Handle<Context> context,Handle<String> variable_name,Handle<Object> new_value)11544 static bool SetContextLocalValue(Isolate* isolate,
11545                                  Handle<ScopeInfo> scope_info,
11546                                  Handle<Context> context,
11547                                  Handle<String> variable_name,
11548                                  Handle<Object> new_value) {
11549   for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11550     Handle<String> next_name(scope_info->ContextLocalName(i));
11551     if (variable_name->Equals(*next_name)) {
11552       VariableMode mode;
11553       InitializationFlag init_flag;
11554       int context_index =
11555           scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
11556       context->set(context_index, *new_value);
11557       return true;
11558     }
11559   }
11560 
11561   return false;
11562 }
11563 
11564 
SetLocalVariableValue(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index,Handle<String> variable_name,Handle<Object> new_value)11565 static bool SetLocalVariableValue(Isolate* isolate,
11566                                   JavaScriptFrame* frame,
11567                                   int inlined_jsframe_index,
11568                                   Handle<String> variable_name,
11569                                   Handle<Object> new_value) {
11570   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11571     // Optimized frames are not supported.
11572     return false;
11573   }
11574 
11575   Handle<JSFunction> function(frame->function());
11576   Handle<SharedFunctionInfo> shared(function->shared());
11577   Handle<ScopeInfo> scope_info(shared->scope_info());
11578 
11579   bool default_result = false;
11580 
11581   // Parameters.
11582   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11583     if (scope_info->ParameterName(i)->Equals(*variable_name)) {
11584       frame->SetParameterValue(i, *new_value);
11585       // Argument might be shadowed in heap context, don't stop here.
11586       default_result = true;
11587     }
11588   }
11589 
11590   // Stack locals.
11591   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11592     if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
11593       frame->SetExpression(i, *new_value);
11594       return true;
11595     }
11596   }
11597 
11598   if (scope_info->HasContext()) {
11599     // Context locals.
11600     Handle<Context> frame_context(Context::cast(frame->context()));
11601     Handle<Context> function_context(frame_context->declaration_context());
11602     if (SetContextLocalValue(
11603         isolate, scope_info, function_context, variable_name, new_value)) {
11604       return true;
11605     }
11606 
11607     // Function context extension. These are variables introduced by eval.
11608     if (function_context->closure() == *function) {
11609       if (function_context->has_extension() &&
11610           !function_context->IsNativeContext()) {
11611         Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11612 
11613         if (JSReceiver::HasProperty(ext, variable_name)) {
11614           // We don't expect this to do anything except replacing
11615           // property value.
11616           Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11617                                      NONE,
11618                                      kNonStrictMode);
11619           return true;
11620         }
11621       }
11622     }
11623   }
11624 
11625   return default_result;
11626 }
11627 
11628 
11629 // Create a plain JSObject which materializes the closure content for the
11630 // context.
MaterializeClosure(Isolate * isolate,Handle<Context> context)11631 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
11632                                            Handle<Context> context) {
11633   ASSERT(context->IsFunctionContext());
11634 
11635   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11636   Handle<ScopeInfo> scope_info(shared->scope_info());
11637 
11638   // Allocate and initialize a JSObject with all the content of this function
11639   // closure.
11640   Handle<JSObject> closure_scope =
11641       isolate->factory()->NewJSObject(isolate->object_function());
11642 
11643   // Fill all context locals to the context extension.
11644   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11645           scope_info, context, closure_scope)) {
11646     return Handle<JSObject>();
11647   }
11648 
11649   // Finally copy any properties from the function context extension. This will
11650   // be variables introduced by eval.
11651   if (context->has_extension()) {
11652     Handle<JSObject> ext(JSObject::cast(context->extension()));
11653     bool threw = false;
11654     Handle<FixedArray> keys =
11655         GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11656     if (threw) return Handle<JSObject>();
11657 
11658     for (int i = 0; i < keys->length(); i++) {
11659       // Names of variables introduced by eval are strings.
11660       ASSERT(keys->get(i)->IsString());
11661       Handle<String> key(String::cast(keys->get(i)));
11662        RETURN_IF_EMPTY_HANDLE_VALUE(
11663           isolate,
11664           Runtime::SetObjectProperty(isolate, closure_scope, key,
11665                                      GetProperty(isolate, ext, key),
11666                                      NONE,
11667                                      kNonStrictMode),
11668           Handle<JSObject>());
11669     }
11670   }
11671 
11672   return closure_scope;
11673 }
11674 
11675 
11676 // This method copies structure of MaterializeClosure method above.
SetClosureVariableValue(Isolate * isolate,Handle<Context> context,Handle<String> variable_name,Handle<Object> new_value)11677 static bool SetClosureVariableValue(Isolate* isolate,
11678                                     Handle<Context> context,
11679                                     Handle<String> variable_name,
11680                                     Handle<Object> new_value) {
11681   ASSERT(context->IsFunctionContext());
11682 
11683   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11684   Handle<ScopeInfo> scope_info(shared->scope_info());
11685 
11686   // Context locals to the context extension.
11687   if (SetContextLocalValue(
11688           isolate, scope_info, context, variable_name, new_value)) {
11689     return true;
11690   }
11691 
11692   // Properties from the function context extension. This will
11693   // be variables introduced by eval.
11694   if (context->has_extension()) {
11695     Handle<JSObject> ext(JSObject::cast(context->extension()));
11696     if (JSReceiver::HasProperty(ext, variable_name)) {
11697       // We don't expect this to do anything except replacing property value.
11698       Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11699                                  NONE,
11700                                  kNonStrictMode);
11701       return true;
11702     }
11703   }
11704 
11705   return false;
11706 }
11707 
11708 
11709 // Create a plain JSObject which materializes the scope for the specified
11710 // catch context.
MaterializeCatchScope(Isolate * isolate,Handle<Context> context)11711 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11712                                               Handle<Context> context) {
11713   ASSERT(context->IsCatchContext());
11714   Handle<String> name(String::cast(context->extension()));
11715   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11716                                isolate);
11717   Handle<JSObject> catch_scope =
11718       isolate->factory()->NewJSObject(isolate->object_function());
11719   RETURN_IF_EMPTY_HANDLE_VALUE(
11720       isolate,
11721       Runtime::SetObjectProperty(isolate, catch_scope, name, thrown_object,
11722                                  NONE,
11723                                  kNonStrictMode),
11724       Handle<JSObject>());
11725   return catch_scope;
11726 }
11727 
11728 
SetCatchVariableValue(Isolate * isolate,Handle<Context> context,Handle<String> variable_name,Handle<Object> new_value)11729 static bool SetCatchVariableValue(Isolate* isolate,
11730                                   Handle<Context> context,
11731                                   Handle<String> variable_name,
11732                                   Handle<Object> new_value) {
11733   ASSERT(context->IsCatchContext());
11734   Handle<String> name(String::cast(context->extension()));
11735   if (!name->Equals(*variable_name)) {
11736     return false;
11737   }
11738   context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11739   return true;
11740 }
11741 
11742 
11743 // Create a plain JSObject which materializes the block scope for the specified
11744 // block context.
MaterializeBlockScope(Isolate * isolate,Handle<Context> context)11745 static Handle<JSObject> MaterializeBlockScope(
11746     Isolate* isolate,
11747     Handle<Context> context) {
11748   ASSERT(context->IsBlockContext());
11749   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11750 
11751   // Allocate and initialize a JSObject with all the arguments, stack locals
11752   // heap locals and extension properties of the debugged function.
11753   Handle<JSObject> block_scope =
11754       isolate->factory()->NewJSObject(isolate->object_function());
11755 
11756   // Fill all context locals.
11757   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11758           scope_info, context, block_scope)) {
11759     return Handle<JSObject>();
11760   }
11761 
11762   return block_scope;
11763 }
11764 
11765 
11766 // Create a plain JSObject which materializes the module scope for the specified
11767 // module context.
MaterializeModuleScope(Isolate * isolate,Handle<Context> context)11768 static Handle<JSObject> MaterializeModuleScope(
11769     Isolate* isolate,
11770     Handle<Context> context) {
11771   ASSERT(context->IsModuleContext());
11772   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11773 
11774   // Allocate and initialize a JSObject with all the members of the debugged
11775   // module.
11776   Handle<JSObject> module_scope =
11777       isolate->factory()->NewJSObject(isolate->object_function());
11778 
11779   // Fill all context locals.
11780   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11781           scope_info, context, module_scope)) {
11782     return Handle<JSObject>();
11783   }
11784 
11785   return module_scope;
11786 }
11787 
11788 
11789 // Iterate over the actual scopes visible from a stack frame or from a closure.
11790 // The iteration proceeds from the innermost visible nested scope outwards.
11791 // All scopes are backed by an actual context except the local scope,
11792 // which is inserted "artificially" in the context chain.
11793 class ScopeIterator {
11794  public:
11795   enum ScopeType {
11796     ScopeTypeGlobal = 0,
11797     ScopeTypeLocal,
11798     ScopeTypeWith,
11799     ScopeTypeClosure,
11800     ScopeTypeCatch,
11801     ScopeTypeBlock,
11802     ScopeTypeModule
11803   };
11804 
ScopeIterator(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index)11805   ScopeIterator(Isolate* isolate,
11806                 JavaScriptFrame* frame,
11807                 int inlined_jsframe_index)
11808     : isolate_(isolate),
11809       frame_(frame),
11810       inlined_jsframe_index_(inlined_jsframe_index),
11811       function_(frame->function()),
11812       context_(Context::cast(frame->context())),
11813       nested_scope_chain_(4),
11814       failed_(false) {
11815 
11816     // Catch the case when the debugger stops in an internal function.
11817     Handle<SharedFunctionInfo> shared_info(function_->shared());
11818     Handle<ScopeInfo> scope_info(shared_info->scope_info());
11819     if (shared_info->script() == isolate->heap()->undefined_value()) {
11820       while (context_->closure() == *function_) {
11821         context_ = Handle<Context>(context_->previous(), isolate_);
11822       }
11823       return;
11824     }
11825 
11826     // Get the debug info (create it if it does not exist).
11827     if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
11828       // Return if ensuring debug info failed.
11829       return;
11830     }
11831     Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11832 
11833     // Find the break point where execution has stopped.
11834     BreakLocationIterator break_location_iterator(debug_info,
11835                                                   ALL_BREAK_LOCATIONS);
11836     // pc points to the instruction after the current one, possibly a break
11837     // location as well. So the "- 1" to exclude it from the search.
11838     break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
11839     if (break_location_iterator.IsExit()) {
11840       // We are within the return sequence. At the momemt it is not possible to
11841       // get a source position which is consistent with the current scope chain.
11842       // Thus all nested with, catch and block contexts are skipped and we only
11843       // provide the function scope.
11844       if (scope_info->HasContext()) {
11845         context_ = Handle<Context>(context_->declaration_context(), isolate_);
11846       } else {
11847         while (context_->closure() == *function_) {
11848           context_ = Handle<Context>(context_->previous(), isolate_);
11849         }
11850       }
11851       if (scope_info->scope_type() != EVAL_SCOPE) {
11852         nested_scope_chain_.Add(scope_info);
11853       }
11854     } else {
11855       // Reparse the code and analyze the scopes.
11856       Handle<Script> script(Script::cast(shared_info->script()));
11857       Scope* scope = NULL;
11858 
11859       // Check whether we are in global, eval or function code.
11860       Handle<ScopeInfo> scope_info(shared_info->scope_info());
11861       if (scope_info->scope_type() != FUNCTION_SCOPE) {
11862         // Global or eval code.
11863         CompilationInfoWithZone info(script);
11864         if (scope_info->scope_type() == GLOBAL_SCOPE) {
11865           info.MarkAsGlobal();
11866         } else {
11867           ASSERT(scope_info->scope_type() == EVAL_SCOPE);
11868           info.MarkAsEval();
11869           info.SetContext(Handle<Context>(function_->context()));
11870         }
11871         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11872           scope = info.function()->scope();
11873         }
11874         RetrieveScopeChain(scope, shared_info);
11875       } else {
11876         // Function code
11877         CompilationInfoWithZone info(shared_info);
11878         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11879           scope = info.function()->scope();
11880         }
11881         RetrieveScopeChain(scope, shared_info);
11882       }
11883     }
11884   }
11885 
ScopeIterator(Isolate * isolate,Handle<JSFunction> function)11886   ScopeIterator(Isolate* isolate,
11887                 Handle<JSFunction> function)
11888     : isolate_(isolate),
11889       frame_(NULL),
11890       inlined_jsframe_index_(0),
11891       function_(function),
11892       context_(function->context()),
11893       failed_(false) {
11894     if (function->IsBuiltin()) {
11895       context_ = Handle<Context>();
11896     }
11897   }
11898 
11899   // More scopes?
Done()11900   bool Done() {
11901     ASSERT(!failed_);
11902     return context_.is_null();
11903   }
11904 
Failed()11905   bool Failed() { return failed_; }
11906 
11907   // Move to the next scope.
Next()11908   void Next() {
11909     ASSERT(!failed_);
11910     ScopeType scope_type = Type();
11911     if (scope_type == ScopeTypeGlobal) {
11912       // The global scope is always the last in the chain.
11913       ASSERT(context_->IsNativeContext());
11914       context_ = Handle<Context>();
11915       return;
11916     }
11917     if (nested_scope_chain_.is_empty()) {
11918       context_ = Handle<Context>(context_->previous(), isolate_);
11919     } else {
11920       if (nested_scope_chain_.last()->HasContext()) {
11921         ASSERT(context_->previous() != NULL);
11922         context_ = Handle<Context>(context_->previous(), isolate_);
11923       }
11924       nested_scope_chain_.RemoveLast();
11925     }
11926   }
11927 
11928   // Return the type of the current scope.
Type()11929   ScopeType Type() {
11930     ASSERT(!failed_);
11931     if (!nested_scope_chain_.is_empty()) {
11932       Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11933       switch (scope_info->scope_type()) {
11934         case FUNCTION_SCOPE:
11935           ASSERT(context_->IsFunctionContext() ||
11936                  !scope_info->HasContext());
11937           return ScopeTypeLocal;
11938         case MODULE_SCOPE:
11939           ASSERT(context_->IsModuleContext());
11940           return ScopeTypeModule;
11941         case GLOBAL_SCOPE:
11942           ASSERT(context_->IsNativeContext());
11943           return ScopeTypeGlobal;
11944         case WITH_SCOPE:
11945           ASSERT(context_->IsWithContext());
11946           return ScopeTypeWith;
11947         case CATCH_SCOPE:
11948           ASSERT(context_->IsCatchContext());
11949           return ScopeTypeCatch;
11950         case BLOCK_SCOPE:
11951           ASSERT(!scope_info->HasContext() ||
11952                  context_->IsBlockContext());
11953           return ScopeTypeBlock;
11954         case EVAL_SCOPE:
11955           UNREACHABLE();
11956       }
11957     }
11958     if (context_->IsNativeContext()) {
11959       ASSERT(context_->global_object()->IsGlobalObject());
11960       return ScopeTypeGlobal;
11961     }
11962     if (context_->IsFunctionContext()) {
11963       return ScopeTypeClosure;
11964     }
11965     if (context_->IsCatchContext()) {
11966       return ScopeTypeCatch;
11967     }
11968     if (context_->IsBlockContext()) {
11969       return ScopeTypeBlock;
11970     }
11971     if (context_->IsModuleContext()) {
11972       return ScopeTypeModule;
11973     }
11974     ASSERT(context_->IsWithContext());
11975     return ScopeTypeWith;
11976   }
11977 
11978   // Return the JavaScript object with the content of the current scope.
ScopeObject()11979   Handle<JSObject> ScopeObject() {
11980     ASSERT(!failed_);
11981     switch (Type()) {
11982       case ScopeIterator::ScopeTypeGlobal:
11983         return Handle<JSObject>(CurrentContext()->global_object());
11984       case ScopeIterator::ScopeTypeLocal:
11985         // Materialize the content of the local scope into a JSObject.
11986         ASSERT(nested_scope_chain_.length() == 1);
11987         return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11988       case ScopeIterator::ScopeTypeWith:
11989         // Return the with object.
11990         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11991       case ScopeIterator::ScopeTypeCatch:
11992         return MaterializeCatchScope(isolate_, CurrentContext());
11993       case ScopeIterator::ScopeTypeClosure:
11994         // Materialize the content of the closure scope into a JSObject.
11995         return MaterializeClosure(isolate_, CurrentContext());
11996       case ScopeIterator::ScopeTypeBlock:
11997         return MaterializeBlockScope(isolate_, CurrentContext());
11998       case ScopeIterator::ScopeTypeModule:
11999         return MaterializeModuleScope(isolate_, CurrentContext());
12000     }
12001     UNREACHABLE();
12002     return Handle<JSObject>();
12003   }
12004 
SetVariableValue(Handle<String> variable_name,Handle<Object> new_value)12005   bool SetVariableValue(Handle<String> variable_name,
12006                         Handle<Object> new_value) {
12007     ASSERT(!failed_);
12008     switch (Type()) {
12009       case ScopeIterator::ScopeTypeGlobal:
12010         break;
12011       case ScopeIterator::ScopeTypeLocal:
12012         return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
12013             variable_name, new_value);
12014       case ScopeIterator::ScopeTypeWith:
12015         break;
12016       case ScopeIterator::ScopeTypeCatch:
12017         return SetCatchVariableValue(isolate_, CurrentContext(),
12018             variable_name, new_value);
12019       case ScopeIterator::ScopeTypeClosure:
12020         return SetClosureVariableValue(isolate_, CurrentContext(),
12021             variable_name, new_value);
12022       case ScopeIterator::ScopeTypeBlock:
12023         // TODO(2399): should we implement it?
12024         break;
12025       case ScopeIterator::ScopeTypeModule:
12026         // TODO(2399): should we implement it?
12027         break;
12028     }
12029     return false;
12030   }
12031 
CurrentScopeInfo()12032   Handle<ScopeInfo> CurrentScopeInfo() {
12033     ASSERT(!failed_);
12034     if (!nested_scope_chain_.is_empty()) {
12035       return nested_scope_chain_.last();
12036     } else if (context_->IsBlockContext()) {
12037       return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
12038     } else if (context_->IsFunctionContext()) {
12039       return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
12040     }
12041     return Handle<ScopeInfo>::null();
12042   }
12043 
12044   // Return the context for this scope. For the local context there might not
12045   // be an actual context.
CurrentContext()12046   Handle<Context> CurrentContext() {
12047     ASSERT(!failed_);
12048     if (Type() == ScopeTypeGlobal ||
12049         nested_scope_chain_.is_empty()) {
12050       return context_;
12051     } else if (nested_scope_chain_.last()->HasContext()) {
12052       return context_;
12053     } else {
12054       return Handle<Context>();
12055     }
12056   }
12057 
12058 #ifdef DEBUG
12059   // Debug print of the content of the current scope.
DebugPrint()12060   void DebugPrint() {
12061     ASSERT(!failed_);
12062     switch (Type()) {
12063       case ScopeIterator::ScopeTypeGlobal:
12064         PrintF("Global:\n");
12065         CurrentContext()->Print();
12066         break;
12067 
12068       case ScopeIterator::ScopeTypeLocal: {
12069         PrintF("Local:\n");
12070         function_->shared()->scope_info()->Print();
12071         if (!CurrentContext().is_null()) {
12072           CurrentContext()->Print();
12073           if (CurrentContext()->has_extension()) {
12074             Handle<Object> extension(CurrentContext()->extension(), isolate_);
12075             if (extension->IsJSContextExtensionObject()) {
12076               extension->Print();
12077             }
12078           }
12079         }
12080         break;
12081       }
12082 
12083       case ScopeIterator::ScopeTypeWith:
12084         PrintF("With:\n");
12085         CurrentContext()->extension()->Print();
12086         break;
12087 
12088       case ScopeIterator::ScopeTypeCatch:
12089         PrintF("Catch:\n");
12090         CurrentContext()->extension()->Print();
12091         CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
12092         break;
12093 
12094       case ScopeIterator::ScopeTypeClosure:
12095         PrintF("Closure:\n");
12096         CurrentContext()->Print();
12097         if (CurrentContext()->has_extension()) {
12098           Handle<Object> extension(CurrentContext()->extension(), isolate_);
12099           if (extension->IsJSContextExtensionObject()) {
12100             extension->Print();
12101           }
12102         }
12103         break;
12104 
12105       default:
12106         UNREACHABLE();
12107     }
12108     PrintF("\n");
12109   }
12110 #endif
12111 
12112  private:
12113   Isolate* isolate_;
12114   JavaScriptFrame* frame_;
12115   int inlined_jsframe_index_;
12116   Handle<JSFunction> function_;
12117   Handle<Context> context_;
12118   List<Handle<ScopeInfo> > nested_scope_chain_;
12119   bool failed_;
12120 
RetrieveScopeChain(Scope * scope,Handle<SharedFunctionInfo> shared_info)12121   void RetrieveScopeChain(Scope* scope,
12122                           Handle<SharedFunctionInfo> shared_info) {
12123     if (scope != NULL) {
12124       int source_position = shared_info->code()->SourcePosition(frame_->pc());
12125       scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
12126     } else {
12127       // A failed reparse indicates that the preparser has diverged from the
12128       // parser or that the preparse data given to the initial parse has been
12129       // faulty. We fail in debug mode but in release mode we only provide the
12130       // information we get from the context chain but nothing about
12131       // completely stack allocated scopes or stack allocated locals.
12132       // Or it could be due to stack overflow.
12133       ASSERT(isolate_->has_pending_exception());
12134       failed_ = true;
12135     }
12136   }
12137 
12138   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
12139 };
12140 
12141 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScopeCount)12142 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
12143   HandleScope scope(isolate);
12144   ASSERT(args.length() == 2);
12145 
12146   // Check arguments.
12147   Object* check;
12148   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12149       RUNTIME_ARGUMENTS(isolate, args));
12150     if (!maybe_check->ToObject(&check)) return maybe_check;
12151   }
12152   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12153 
12154   // Get the frame where the debugging is performed.
12155   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12156   JavaScriptFrameIterator it(isolate, id);
12157   JavaScriptFrame* frame = it.frame();
12158 
12159   // Count the visible scopes.
12160   int n = 0;
12161   for (ScopeIterator it(isolate, frame, 0);
12162        !it.Done();
12163        it.Next()) {
12164     n++;
12165   }
12166 
12167   return Smi::FromInt(n);
12168 }
12169 
12170 
12171 // Returns the list of step-in positions (text offset) in a function of the
12172 // stack frame in a range from the current debug break position to the end
12173 // of the corresponding statement.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetStepInPositions)12174 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
12175   HandleScope scope(isolate);
12176   ASSERT(args.length() == 2);
12177 
12178   // Check arguments.
12179   Object* check;
12180   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12181       RUNTIME_ARGUMENTS(isolate, args));
12182     if (!maybe_check->ToObject(&check)) return maybe_check;
12183   }
12184   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12185 
12186   // Get the frame where the debugging is performed.
12187   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12188   JavaScriptFrameIterator frame_it(isolate, id);
12189   RUNTIME_ASSERT(!frame_it.done());
12190 
12191   JavaScriptFrame* frame = frame_it.frame();
12192 
12193   Handle<JSFunction> fun =
12194       Handle<JSFunction>(frame->function());
12195   Handle<SharedFunctionInfo> shared =
12196       Handle<SharedFunctionInfo>(fun->shared());
12197 
12198   if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12199     return isolate->heap()->undefined_value();
12200   }
12201 
12202   Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12203 
12204   int len = 0;
12205   Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12206   // Find the break point where execution has stopped.
12207   BreakLocationIterator break_location_iterator(debug_info,
12208                                                 ALL_BREAK_LOCATIONS);
12209 
12210   break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12211   int current_statement_pos = break_location_iterator.statement_position();
12212 
12213   while (!break_location_iterator.Done()) {
12214     bool accept;
12215     if (break_location_iterator.pc() > frame->pc()) {
12216       accept = true;
12217     } else {
12218       StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
12219       // The break point is near our pc. Could be a step-in possibility,
12220       // that is currently taken by active debugger call.
12221       if (break_frame_id == StackFrame::NO_ID) {
12222         // We are not stepping.
12223         accept = false;
12224       } else {
12225         JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id);
12226         // If our frame is a top frame and we are stepping, we can do step-in
12227         // at this place.
12228         accept = additional_frame_it.frame()->id() == id;
12229       }
12230     }
12231     if (accept) {
12232       if (break_location_iterator.IsStepInLocation(isolate)) {
12233         Smi* position_value = Smi::FromInt(break_location_iterator.position());
12234         JSObject::SetElement(array, len,
12235             Handle<Object>(position_value, isolate),
12236             NONE, kNonStrictMode);
12237         len++;
12238       }
12239     }
12240     // Advance iterator.
12241     break_location_iterator.Next();
12242     if (current_statement_pos !=
12243         break_location_iterator.statement_position()) {
12244       break;
12245     }
12246   }
12247   return *array;
12248 }
12249 
12250 
12251 static const int kScopeDetailsTypeIndex = 0;
12252 static const int kScopeDetailsObjectIndex = 1;
12253 static const int kScopeDetailsSize = 2;
12254 
12255 
MaterializeScopeDetails(Isolate * isolate,ScopeIterator * it)12256 static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
12257     ScopeIterator* it) {
12258   // Calculate the size of the result.
12259   int details_size = kScopeDetailsSize;
12260   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12261 
12262   // Fill in scope details.
12263   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12264   Handle<JSObject> scope_object = it->ScopeObject();
12265   RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
12266   details->set(kScopeDetailsObjectIndex, *scope_object);
12267 
12268   return *isolate->factory()->NewJSArrayWithElements(details);
12269 }
12270 
12271 
12272 // Return an array with scope details
12273 // args[0]: number: break id
12274 // args[1]: number: frame index
12275 // args[2]: number: inlined frame index
12276 // args[3]: number: scope index
12277 //
12278 // The array returned contains the following information:
12279 // 0: Scope type
12280 // 1: Scope object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScopeDetails)12281 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
12282   HandleScope scope(isolate);
12283   ASSERT(args.length() == 4);
12284 
12285   // Check arguments.
12286   Object* check;
12287   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12288       RUNTIME_ARGUMENTS(isolate, args));
12289     if (!maybe_check->ToObject(&check)) return maybe_check;
12290   }
12291   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12292   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12293   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12294 
12295   // Get the frame where the debugging is performed.
12296   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12297   JavaScriptFrameIterator frame_it(isolate, id);
12298   JavaScriptFrame* frame = frame_it.frame();
12299 
12300   // Find the requested scope.
12301   int n = 0;
12302   ScopeIterator it(isolate, frame, inlined_jsframe_index);
12303   for (; !it.Done() && n < index; it.Next()) {
12304     n++;
12305   }
12306   if (it.Done()) {
12307     return isolate->heap()->undefined_value();
12308   }
12309   return MaterializeScopeDetails(isolate, &it);
12310 }
12311 
12312 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionScopeCount)12313 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
12314   HandleScope scope(isolate);
12315   ASSERT(args.length() == 1);
12316 
12317   // Check arguments.
12318   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12319 
12320   // Count the visible scopes.
12321   int n = 0;
12322   for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12323     n++;
12324   }
12325 
12326   return Smi::FromInt(n);
12327 }
12328 
12329 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionScopeDetails)12330 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
12331   HandleScope scope(isolate);
12332   ASSERT(args.length() == 2);
12333 
12334   // Check arguments.
12335   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12336   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12337 
12338   // Find the requested scope.
12339   int n = 0;
12340   ScopeIterator it(isolate, fun);
12341   for (; !it.Done() && n < index; it.Next()) {
12342     n++;
12343   }
12344   if (it.Done()) {
12345     return isolate->heap()->undefined_value();
12346   }
12347 
12348   return MaterializeScopeDetails(isolate, &it);
12349 }
12350 
12351 
SetScopeVariableValue(ScopeIterator * it,int index,Handle<String> variable_name,Handle<Object> new_value)12352 static bool SetScopeVariableValue(ScopeIterator* it, int index,
12353                                   Handle<String> variable_name,
12354                                   Handle<Object> new_value) {
12355   for (int n = 0; !it->Done() && n < index; it->Next()) {
12356     n++;
12357   }
12358   if (it->Done()) {
12359     return false;
12360   }
12361   return it->SetVariableValue(variable_name, new_value);
12362 }
12363 
12364 
12365 // Change variable value in closure or local scope
12366 // args[0]: number or JsFunction: break id or function
12367 // args[1]: number: frame index (when arg[0] is break id)
12368 // args[2]: number: inlined frame index (when arg[0] is break id)
12369 // args[3]: number: scope index
12370 // args[4]: string: variable name
12371 // args[5]: object: new value
12372 //
12373 // Return true if success and false otherwise
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetScopeVariableValue)12374 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
12375   HandleScope scope(isolate);
12376   ASSERT(args.length() == 6);
12377 
12378   // Check arguments.
12379   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12380   CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12381   Handle<Object> new_value = args.at<Object>(5);
12382 
12383   bool res;
12384   if (args[0]->IsNumber()) {
12385     Object* check;
12386     { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12387         RUNTIME_ARGUMENTS(isolate, args));
12388       if (!maybe_check->ToObject(&check)) return maybe_check;
12389     }
12390     CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12391     CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12392 
12393     // Get the frame where the debugging is performed.
12394     StackFrame::Id id = UnwrapFrameId(wrapped_id);
12395     JavaScriptFrameIterator frame_it(isolate, id);
12396     JavaScriptFrame* frame = frame_it.frame();
12397 
12398     ScopeIterator it(isolate, frame, inlined_jsframe_index);
12399     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12400   } else {
12401     CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12402     ScopeIterator it(isolate, fun);
12403     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12404   }
12405 
12406   return isolate->heap()->ToBoolean(res);
12407 }
12408 
12409 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPrintScopes)12410 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
12411   HandleScope scope(isolate);
12412   ASSERT(args.length() == 0);
12413 
12414 #ifdef DEBUG
12415   // Print the scopes for the top frame.
12416   StackFrameLocator locator(isolate);
12417   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12418   for (ScopeIterator it(isolate, frame, 0);
12419        !it.Done();
12420        it.Next()) {
12421     it.DebugPrint();
12422   }
12423 #endif
12424   return isolate->heap()->undefined_value();
12425 }
12426 
12427 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetThreadCount)12428 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
12429   HandleScope scope(isolate);
12430   ASSERT(args.length() == 1);
12431 
12432   // Check arguments.
12433   Object* result;
12434   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12435       RUNTIME_ARGUMENTS(isolate, args));
12436     if (!maybe_result->ToObject(&result)) return maybe_result;
12437   }
12438 
12439   // Count all archived V8 threads.
12440   int n = 0;
12441   for (ThreadState* thread =
12442           isolate->thread_manager()->FirstThreadStateInUse();
12443        thread != NULL;
12444        thread = thread->Next()) {
12445     n++;
12446   }
12447 
12448   // Total number of threads is current thread and archived threads.
12449   return Smi::FromInt(n + 1);
12450 }
12451 
12452 
12453 static const int kThreadDetailsCurrentThreadIndex = 0;
12454 static const int kThreadDetailsThreadIdIndex = 1;
12455 static const int kThreadDetailsSize = 2;
12456 
12457 // Return an array with thread details
12458 // args[0]: number: break id
12459 // args[1]: number: thread index
12460 //
12461 // The array returned contains the following information:
12462 // 0: Is current thread?
12463 // 1: Thread id
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetThreadDetails)12464 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
12465   HandleScope scope(isolate);
12466   ASSERT(args.length() == 2);
12467 
12468   // Check arguments.
12469   Object* check;
12470   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12471       RUNTIME_ARGUMENTS(isolate, args));
12472     if (!maybe_check->ToObject(&check)) return maybe_check;
12473   }
12474   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12475 
12476   // Allocate array for result.
12477   Handle<FixedArray> details =
12478       isolate->factory()->NewFixedArray(kThreadDetailsSize);
12479 
12480   // Thread index 0 is current thread.
12481   if (index == 0) {
12482     // Fill the details.
12483     details->set(kThreadDetailsCurrentThreadIndex,
12484                  isolate->heap()->true_value());
12485     details->set(kThreadDetailsThreadIdIndex,
12486                  Smi::FromInt(ThreadId::Current().ToInteger()));
12487   } else {
12488     // Find the thread with the requested index.
12489     int n = 1;
12490     ThreadState* thread =
12491         isolate->thread_manager()->FirstThreadStateInUse();
12492     while (index != n && thread != NULL) {
12493       thread = thread->Next();
12494       n++;
12495     }
12496     if (thread == NULL) {
12497       return isolate->heap()->undefined_value();
12498     }
12499 
12500     // Fill the details.
12501     details->set(kThreadDetailsCurrentThreadIndex,
12502                  isolate->heap()->false_value());
12503     details->set(kThreadDetailsThreadIdIndex,
12504                  Smi::FromInt(thread->id().ToInteger()));
12505   }
12506 
12507   // Convert to JS array and return.
12508   return *isolate->factory()->NewJSArrayWithElements(details);
12509 }
12510 
12511 
12512 // Sets the disable break state
12513 // args[0]: disable break state
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDisableBreak)12514 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
12515   HandleScope scope(isolate);
12516   ASSERT(args.length() == 1);
12517   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12518   isolate->debug()->set_disable_break(disable_break);
12519   return  isolate->heap()->undefined_value();
12520 }
12521 
12522 
IsPositionAlignmentCodeCorrect(int alignment)12523 static bool IsPositionAlignmentCodeCorrect(int alignment) {
12524   return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12525 }
12526 
12527 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetBreakLocations)12528 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
12529   HandleScope scope(isolate);
12530   ASSERT(args.length() == 2);
12531 
12532   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12533   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12534 
12535   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12536     return isolate->ThrowIllegalOperation();
12537   }
12538   BreakPositionAlignment alignment =
12539       static_cast<BreakPositionAlignment>(statement_aligned_code);
12540 
12541   Handle<SharedFunctionInfo> shared(fun->shared());
12542   // Find the number of break points
12543   Handle<Object> break_locations =
12544       Debug::GetSourceBreakLocations(shared, alignment);
12545   if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12546   // Return array as JS array
12547   return *isolate->factory()->NewJSArrayWithElements(
12548       Handle<FixedArray>::cast(break_locations));
12549 }
12550 
12551 
12552 // Set a break point in a function.
12553 // args[0]: function
12554 // args[1]: number: break source position (within the function source)
12555 // args[2]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetFunctionBreakPoint)12556 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
12557   HandleScope scope(isolate);
12558   ASSERT(args.length() == 3);
12559   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12560   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12561   RUNTIME_ASSERT(source_position >= 0);
12562   Handle<Object> break_point_object_arg = args.at<Object>(2);
12563 
12564   // Set break point.
12565   isolate->debug()->SetBreakPoint(function, break_point_object_arg,
12566                                   &source_position);
12567 
12568   return Smi::FromInt(source_position);
12569 }
12570 
12571 
12572 // Changes the state of a break point in a script and returns source position
12573 // where break point was set. NOTE: Regarding performance see the NOTE for
12574 // GetScriptFromScriptData.
12575 // args[0]: script to set break point in
12576 // args[1]: number: break source position (within the script source)
12577 // args[2]: number, breakpoint position alignment
12578 // args[3]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetScriptBreakPoint)12579 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
12580   HandleScope scope(isolate);
12581   ASSERT(args.length() == 4);
12582   CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12583   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12584   RUNTIME_ASSERT(source_position >= 0);
12585   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12586   Handle<Object> break_point_object_arg = args.at<Object>(3);
12587 
12588   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12589     return isolate->ThrowIllegalOperation();
12590   }
12591   BreakPositionAlignment alignment =
12592       static_cast<BreakPositionAlignment>(statement_aligned_code);
12593 
12594   // Get the script from the script wrapper.
12595   RUNTIME_ASSERT(wrapper->value()->IsScript());
12596   Handle<Script> script(Script::cast(wrapper->value()));
12597 
12598   // Set break point.
12599   if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12600                                                 &source_position,
12601                                                 alignment)) {
12602     return  isolate->heap()->undefined_value();
12603   }
12604 
12605   return Smi::FromInt(source_position);
12606 }
12607 
12608 
12609 // Clear a break point
12610 // args[0]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClearBreakPoint)12611 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
12612   HandleScope scope(isolate);
12613   ASSERT(args.length() == 1);
12614   Handle<Object> break_point_object_arg = args.at<Object>(0);
12615 
12616   // Clear break point.
12617   isolate->debug()->ClearBreakPoint(break_point_object_arg);
12618 
12619   return isolate->heap()->undefined_value();
12620 }
12621 
12622 
12623 // Change the state of break on exceptions.
12624 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12625 // args[1]: Boolean indicating on/off.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ChangeBreakOnException)12626 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
12627   HandleScope scope(isolate);
12628   ASSERT(args.length() == 2);
12629   RUNTIME_ASSERT(args[0]->IsNumber());
12630   CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12631 
12632   // If the number doesn't match an enum value, the ChangeBreakOnException
12633   // function will default to affecting caught exceptions.
12634   ExceptionBreakType type =
12635       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12636   // Update break point state.
12637   isolate->debug()->ChangeBreakOnException(type, enable);
12638   return isolate->heap()->undefined_value();
12639 }
12640 
12641 
12642 // Returns the state of break on exceptions
12643 // args[0]: boolean indicating uncaught exceptions
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsBreakOnException)12644 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
12645   HandleScope scope(isolate);
12646   ASSERT(args.length() == 1);
12647   RUNTIME_ASSERT(args[0]->IsNumber());
12648 
12649   ExceptionBreakType type =
12650       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12651   bool result = isolate->debug()->IsBreakOnException(type);
12652   return Smi::FromInt(result);
12653 }
12654 
12655 
12656 // Prepare for stepping
12657 // args[0]: break id for checking execution state
12658 // args[1]: step action from the enumeration StepAction
12659 // args[2]: number of times to perform the step, for step out it is the number
12660 //          of frames to step down.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PrepareStep)12661 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
12662   HandleScope scope(isolate);
12663   ASSERT(args.length() == 4);
12664   // Check arguments.
12665   Object* check;
12666   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12667       RUNTIME_ARGUMENTS(isolate, args));
12668     if (!maybe_check->ToObject(&check)) return maybe_check;
12669   }
12670   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12671     return isolate->Throw(isolate->heap()->illegal_argument_string());
12672   }
12673 
12674   CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]);
12675 
12676   StackFrame::Id frame_id;
12677   if (wrapped_frame_id == 0) {
12678     frame_id = StackFrame::NO_ID;
12679   } else {
12680     frame_id = UnwrapFrameId(wrapped_frame_id);
12681   }
12682 
12683   // Get the step action and check validity.
12684   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12685   if (step_action != StepIn &&
12686       step_action != StepNext &&
12687       step_action != StepOut &&
12688       step_action != StepInMin &&
12689       step_action != StepMin) {
12690     return isolate->Throw(isolate->heap()->illegal_argument_string());
12691   }
12692 
12693   if (frame_id != StackFrame::NO_ID && step_action != StepNext &&
12694       step_action != StepMin && step_action != StepOut) {
12695     return isolate->ThrowIllegalOperation();
12696   }
12697 
12698   // Get the number of steps.
12699   int step_count = NumberToInt32(args[2]);
12700   if (step_count < 1) {
12701     return isolate->Throw(isolate->heap()->illegal_argument_string());
12702   }
12703 
12704   // Clear all current stepping setup.
12705   isolate->debug()->ClearStepping();
12706 
12707   // Prepare step.
12708   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12709                                 step_count,
12710                                 frame_id);
12711   return isolate->heap()->undefined_value();
12712 }
12713 
12714 
12715 // Clear all stepping set by PrepareStep.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClearStepping)12716 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
12717   HandleScope scope(isolate);
12718   ASSERT(args.length() == 0);
12719   isolate->debug()->ClearStepping();
12720   return isolate->heap()->undefined_value();
12721 }
12722 
12723 
12724 // Helper function to find or create the arguments object for
12725 // Runtime_DebugEvaluate.
MaterializeArgumentsObject(Isolate * isolate,Handle<JSObject> target,Handle<JSFunction> function)12726 static Handle<JSObject> MaterializeArgumentsObject(
12727     Isolate* isolate,
12728     Handle<JSObject> target,
12729     Handle<JSFunction> function) {
12730   // Do not materialize the arguments object for eval or top-level code.
12731   // Skip if "arguments" is already taken.
12732   if (!function->shared()->is_function() ||
12733       JSReceiver::HasLocalProperty(target,
12734                                    isolate->factory()->arguments_string())) {
12735     return target;
12736   }
12737 
12738   // FunctionGetArguments can't throw an exception.
12739   Handle<JSObject> arguments = Handle<JSObject>::cast(
12740       Accessors::FunctionGetArguments(function));
12741   Runtime::SetObjectProperty(isolate, target,
12742                              isolate->factory()->arguments_string(),
12743                              arguments,
12744                              ::NONE,
12745                              kNonStrictMode);
12746   return target;
12747 }
12748 
12749 
12750 // Compile and evaluate source for the given context.
DebugEvaluate(Isolate * isolate,Handle<Context> context,Handle<Object> context_extension,Handle<Object> receiver,Handle<String> source)12751 static MaybeObject* DebugEvaluate(Isolate* isolate,
12752                                   Handle<Context> context,
12753                                   Handle<Object> context_extension,
12754                                   Handle<Object> receiver,
12755                                   Handle<String> source) {
12756   if (context_extension->IsJSObject()) {
12757     Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12758     Handle<JSFunction> closure(context->closure(), isolate);
12759     context = isolate->factory()->NewWithContext(closure, context, extension);
12760   }
12761 
12762   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
12763       source,
12764       context,
12765       context->IsNativeContext(),
12766       CLASSIC_MODE,
12767       NO_PARSE_RESTRICTION,
12768       RelocInfo::kNoPosition);
12769   RETURN_IF_EMPTY_HANDLE(isolate, shared);
12770 
12771   Handle<JSFunction> eval_fun =
12772       isolate->factory()->NewFunctionFromSharedFunctionInfo(
12773           shared, context, NOT_TENURED);
12774   bool pending_exception;
12775   Handle<Object> result = Execution::Call(
12776       isolate, eval_fun, receiver, 0, NULL, &pending_exception);
12777 
12778   if (pending_exception) return Failure::Exception();
12779 
12780   // Skip the global proxy as it has no properties and always delegates to the
12781   // real global object.
12782   if (result->IsJSGlobalProxy()) {
12783     result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
12784   }
12785 
12786   // Clear the oneshot breakpoints so that the debugger does not step further.
12787   isolate->debug()->ClearStepping();
12788   return *result;
12789 }
12790 
12791 
12792 // Evaluate a piece of JavaScript in the context of a stack frame for
12793 // debugging.  Things that need special attention are:
12794 // - Parameters and stack-allocated locals need to be materialized.  Altered
12795 //   values need to be written back to the stack afterwards.
12796 // - The arguments object needs to materialized.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugEvaluate)12797 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
12798   HandleScope scope(isolate);
12799 
12800   // Check the execution state and decode arguments frame and source to be
12801   // evaluated.
12802   ASSERT(args.length() == 6);
12803   Object* check_result;
12804   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12805       RUNTIME_ARGUMENTS(isolate, args));
12806     if (!maybe_result->ToObject(&check_result)) return maybe_result;
12807   }
12808   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12809   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12810   CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
12811   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
12812   Handle<Object> context_extension(args[5], isolate);
12813 
12814   // Handle the processing of break.
12815   DisableBreak disable_break_save(isolate, disable_break);
12816 
12817   // Get the frame where the debugging is performed.
12818   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12819   JavaScriptFrameIterator it(isolate, id);
12820   JavaScriptFrame* frame = it.frame();
12821   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12822   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12823 
12824   // Traverse the saved contexts chain to find the active context for the
12825   // selected frame.
12826   SaveContext* save = FindSavedContextForFrame(isolate, frame);
12827 
12828   SaveContext savex(isolate);
12829   isolate->set_context(*(save->context()));
12830 
12831   // Evaluate on the context of the frame.
12832   Handle<Context> context(Context::cast(frame->context()));
12833   ASSERT(!context.is_null());
12834 
12835   // Materialize stack locals and the arguments object.
12836   Handle<JSObject> materialized =
12837       isolate->factory()->NewJSObject(isolate->object_function());
12838 
12839   materialized = MaterializeStackLocalsWithFrameInspector(
12840       isolate, materialized, function, &frame_inspector);
12841   RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12842 
12843   materialized = MaterializeArgumentsObject(isolate, materialized, function);
12844   RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12845 
12846   // Add the materialized object in a with-scope to shadow the stack locals.
12847   context = isolate->factory()->NewWithContext(function, context, materialized);
12848 
12849   Handle<Object> receiver(frame->receiver(), isolate);
12850   Object* evaluate_result_object;
12851   { MaybeObject* maybe_result =
12852     DebugEvaluate(isolate, context, context_extension, receiver, source);
12853     if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
12854   }
12855 
12856   Handle<Object> result(evaluate_result_object, isolate);
12857 
12858   // Write back potential changes to materialized stack locals to the stack.
12859   UpdateStackLocalsFromMaterializedObject(
12860       isolate, materialized, function, frame, inlined_jsframe_index);
12861 
12862   return *result;
12863 }
12864 
12865 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugEvaluateGlobal)12866 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
12867   HandleScope scope(isolate);
12868 
12869   // Check the execution state and decode arguments frame and source to be
12870   // evaluated.
12871   ASSERT(args.length() == 4);
12872   Object* check_result;
12873   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12874       RUNTIME_ARGUMENTS(isolate, args));
12875     if (!maybe_result->ToObject(&check_result)) return maybe_result;
12876   }
12877   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12878   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
12879   Handle<Object> context_extension(args[3], isolate);
12880 
12881   // Handle the processing of break.
12882   DisableBreak disable_break_save(isolate, disable_break);
12883 
12884   // Enter the top context from before the debugger was invoked.
12885   SaveContext save(isolate);
12886   SaveContext* top = &save;
12887   while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
12888     top = top->prev();
12889   }
12890   if (top != NULL) {
12891     isolate->set_context(*top->context());
12892   }
12893 
12894   // Get the native context now set to the top context from before the
12895   // debugger was invoked.
12896   Handle<Context> context = isolate->native_context();
12897   Handle<Object> receiver = isolate->global_object();
12898   return DebugEvaluate(isolate, context, context_extension, receiver, source);
12899 }
12900 
12901 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetLoadedScripts)12902 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
12903   HandleScope scope(isolate);
12904   ASSERT(args.length() == 0);
12905 
12906   // Fill the script objects.
12907   Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
12908 
12909   // Convert the script objects to proper JS objects.
12910   for (int i = 0; i < instances->length(); i++) {
12911     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
12912     // Get the script wrapper in a local handle before calling GetScriptWrapper,
12913     // because using
12914     //   instances->set(i, *GetScriptWrapper(script))
12915     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12916     // already have dereferenced the instances handle.
12917     Handle<JSValue> wrapper = GetScriptWrapper(script);
12918     instances->set(i, *wrapper);
12919   }
12920 
12921   // Return result as a JS array.
12922   Handle<JSObject> result =
12923       isolate->factory()->NewJSObject(isolate->array_function());
12924   isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12925   return *result;
12926 }
12927 
12928 
12929 // 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)12930 static int DebugReferencedBy(HeapIterator* iterator,
12931                              JSObject* target,
12932                              Object* instance_filter, int max_references,
12933                              FixedArray* instances, int instances_size,
12934                              JSFunction* arguments_function) {
12935   Isolate* isolate = target->GetIsolate();
12936   SealHandleScope shs(isolate);
12937   DisallowHeapAllocation no_allocation;
12938 
12939   // Iterate the heap.
12940   int count = 0;
12941   JSObject* last = NULL;
12942   HeapObject* heap_obj = NULL;
12943   while (((heap_obj = iterator->next()) != NULL) &&
12944          (max_references == 0 || count < max_references)) {
12945     // Only look at all JSObjects.
12946     if (heap_obj->IsJSObject()) {
12947       // Skip context extension objects and argument arrays as these are
12948       // checked in the context of functions using them.
12949       JSObject* obj = JSObject::cast(heap_obj);
12950       if (obj->IsJSContextExtensionObject() ||
12951           obj->map()->constructor() == arguments_function) {
12952         continue;
12953       }
12954 
12955       // Check if the JS object has a reference to the object looked for.
12956       if (obj->ReferencesObject(target)) {
12957         // Check instance filter if supplied. This is normally used to avoid
12958         // references from mirror objects (see Runtime_IsInPrototypeChain).
12959         if (!instance_filter->IsUndefined()) {
12960           Object* V = obj;
12961           while (true) {
12962             Object* prototype = V->GetPrototype(isolate);
12963             if (prototype->IsNull()) {
12964               break;
12965             }
12966             if (instance_filter == prototype) {
12967               obj = NULL;  // Don't add this object.
12968               break;
12969             }
12970             V = prototype;
12971           }
12972         }
12973 
12974         if (obj != NULL) {
12975           // Valid reference found add to instance array if supplied an update
12976           // count.
12977           if (instances != NULL && count < instances_size) {
12978             instances->set(count, obj);
12979           }
12980           last = obj;
12981           count++;
12982         }
12983       }
12984     }
12985   }
12986 
12987   // Check for circular reference only. This can happen when the object is only
12988   // referenced from mirrors and has a circular reference in which case the
12989   // object is not really alive and would have been garbage collected if not
12990   // referenced from the mirror.
12991   if (count == 1 && last == target) {
12992     count = 0;
12993   }
12994 
12995   // Return the number of referencing objects found.
12996   return count;
12997 }
12998 
12999 
13000 // Scan the heap for objects with direct references to an object
13001 // args[0]: the object to find references to
13002 // args[1]: constructor function for instances to exclude (Mirror)
13003 // args[2]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugReferencedBy)13004 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
13005   SealHandleScope shs(isolate);
13006   ASSERT(args.length() == 3);
13007 
13008   // First perform a full GC in order to avoid references from dead objects.
13009   isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
13010                                      "%DebugReferencedBy");
13011   // The heap iterator reserves the right to do a GC to make the heap iterable.
13012   // Due to the GC above we know it won't need to do that, but it seems cleaner
13013   // to get the heap iterator constructed before we start having unprotected
13014   // Object* locals that are not protected by handles.
13015 
13016   // Check parameters.
13017   CONVERT_ARG_CHECKED(JSObject, target, 0);
13018   Object* instance_filter = args[1];
13019   RUNTIME_ASSERT(instance_filter->IsUndefined() ||
13020                  instance_filter->IsJSObject());
13021   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
13022   RUNTIME_ASSERT(max_references >= 0);
13023 
13024 
13025   // Get the constructor function for context extension and arguments array.
13026   JSObject* arguments_boilerplate =
13027       isolate->context()->native_context()->arguments_boilerplate();
13028   JSFunction* arguments_function =
13029       JSFunction::cast(arguments_boilerplate->map()->constructor());
13030 
13031   // Get the number of referencing objects.
13032   int count;
13033   Heap* heap = isolate->heap();
13034   HeapIterator heap_iterator(heap);
13035   count = DebugReferencedBy(&heap_iterator,
13036                             target, instance_filter, max_references,
13037                             NULL, 0, arguments_function);
13038 
13039   // Allocate an array to hold the result.
13040   Object* object;
13041   { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
13042     if (!maybe_object->ToObject(&object)) return maybe_object;
13043   }
13044   FixedArray* instances = FixedArray::cast(object);
13045 
13046   // Fill the referencing objects.
13047   // AllocateFixedArray above does not make the heap non-iterable.
13048   ASSERT(heap->IsHeapIterable());
13049   HeapIterator heap_iterator2(heap);
13050   count = DebugReferencedBy(&heap_iterator2,
13051                             target, instance_filter, max_references,
13052                             instances, count, arguments_function);
13053 
13054   // Return result as JS array.
13055   Object* result;
13056   MaybeObject* maybe_result = heap->AllocateJSObject(
13057       isolate->context()->native_context()->array_function());
13058   if (!maybe_result->ToObject(&result)) return maybe_result;
13059   return JSArray::cast(result)->SetContent(instances);
13060 }
13061 
13062 
13063 // Helper function used by Runtime_DebugConstructedBy below.
DebugConstructedBy(HeapIterator * iterator,JSFunction * constructor,int max_references,FixedArray * instances,int instances_size)13064 static int DebugConstructedBy(HeapIterator* iterator,
13065                               JSFunction* constructor,
13066                               int max_references,
13067                               FixedArray* instances,
13068                               int instances_size) {
13069   DisallowHeapAllocation no_allocation;
13070 
13071   // Iterate the heap.
13072   int count = 0;
13073   HeapObject* heap_obj = NULL;
13074   while (((heap_obj = iterator->next()) != NULL) &&
13075          (max_references == 0 || count < max_references)) {
13076     // Only look at all JSObjects.
13077     if (heap_obj->IsJSObject()) {
13078       JSObject* obj = JSObject::cast(heap_obj);
13079       if (obj->map()->constructor() == constructor) {
13080         // Valid reference found add to instance array if supplied an update
13081         // count.
13082         if (instances != NULL && count < instances_size) {
13083           instances->set(count, obj);
13084         }
13085         count++;
13086       }
13087     }
13088   }
13089 
13090   // Return the number of referencing objects found.
13091   return count;
13092 }
13093 
13094 
13095 // Scan the heap for objects constructed by a specific function.
13096 // args[0]: the constructor to find instances of
13097 // args[1]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugConstructedBy)13098 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
13099   SealHandleScope shs(isolate);
13100   ASSERT(args.length() == 2);
13101 
13102   // First perform a full GC in order to avoid dead objects.
13103   Heap* heap = isolate->heap();
13104   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13105 
13106   // Check parameters.
13107   CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
13108   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
13109   RUNTIME_ASSERT(max_references >= 0);
13110 
13111   // Get the number of referencing objects.
13112   int count;
13113   HeapIterator heap_iterator(heap);
13114   count = DebugConstructedBy(&heap_iterator,
13115                              constructor,
13116                              max_references,
13117                              NULL,
13118                              0);
13119 
13120   // Allocate an array to hold the result.
13121   Object* object;
13122   { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
13123     if (!maybe_object->ToObject(&object)) return maybe_object;
13124   }
13125   FixedArray* instances = FixedArray::cast(object);
13126 
13127   ASSERT(isolate->heap()->IsHeapIterable());
13128   // Fill the referencing objects.
13129   HeapIterator heap_iterator2(heap);
13130   count = DebugConstructedBy(&heap_iterator2,
13131                              constructor,
13132                              max_references,
13133                              instances,
13134                              count);
13135 
13136   // Return result as JS array.
13137   Object* result;
13138   { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
13139       isolate->context()->native_context()->array_function());
13140     if (!maybe_result->ToObject(&result)) return maybe_result;
13141   }
13142   return JSArray::cast(result)->SetContent(instances);
13143 }
13144 
13145 
13146 // Find the effective prototype object as returned by __proto__.
13147 // args[0]: the object to find the prototype for.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetPrototype)13148 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
13149   SealHandleScope shs(isolate);
13150   ASSERT(args.length() == 1);
13151   CONVERT_ARG_CHECKED(JSObject, obj, 0);
13152   return GetPrototypeSkipHiddenPrototypes(isolate, obj);
13153 }
13154 
13155 
13156 // Patches script source (should be called upon BeforeCompile event).
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugSetScriptSource)13157 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
13158   HandleScope scope(isolate);
13159   ASSERT(args.length() == 2);
13160 
13161   CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
13162   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13163 
13164   RUNTIME_ASSERT(script_wrapper->value()->IsScript());
13165   Handle<Script> script(Script::cast(script_wrapper->value()));
13166 
13167   int compilation_state = script->compilation_state();
13168   RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
13169   script->set_source(*source);
13170 
13171   return isolate->heap()->undefined_value();
13172 }
13173 
13174 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SystemBreak)13175 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
13176   SealHandleScope shs(isolate);
13177   ASSERT(args.length() == 0);
13178   OS::DebugBreak();
13179   return isolate->heap()->undefined_value();
13180 }
13181 
13182 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugDisassembleFunction)13183 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
13184   HandleScope scope(isolate);
13185 #ifdef DEBUG
13186   ASSERT(args.length() == 1);
13187   // Get the function and make sure it is compiled.
13188   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13189   if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
13190     return Failure::Exception();
13191   }
13192   func->code()->PrintLn();
13193 #endif  // DEBUG
13194   return isolate->heap()->undefined_value();
13195 }
13196 
13197 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugDisassembleConstructor)13198 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
13199   HandleScope scope(isolate);
13200 #ifdef DEBUG
13201   ASSERT(args.length() == 1);
13202   // Get the function and make sure it is compiled.
13203   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13204   if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
13205     return Failure::Exception();
13206   }
13207   func->shared()->construct_stub()->PrintLn();
13208 #endif  // DEBUG
13209   return isolate->heap()->undefined_value();
13210 }
13211 
13212 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetInferredName)13213 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
13214   SealHandleScope shs(isolate);
13215   ASSERT(args.length() == 1);
13216 
13217   CONVERT_ARG_CHECKED(JSFunction, f, 0);
13218   return f->shared()->inferred_name();
13219 }
13220 
13221 
FindSharedFunctionInfosForScript(HeapIterator * iterator,Script * script,FixedArray * buffer)13222 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13223                                             Script* script,
13224                                             FixedArray* buffer) {
13225   DisallowHeapAllocation no_allocation;
13226   int counter = 0;
13227   int buffer_size = buffer->length();
13228   for (HeapObject* obj = iterator->next();
13229        obj != NULL;
13230        obj = iterator->next()) {
13231     ASSERT(obj != NULL);
13232     if (!obj->IsSharedFunctionInfo()) {
13233       continue;
13234     }
13235     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13236     if (shared->script() != script) {
13237       continue;
13238     }
13239     if (counter < buffer_size) {
13240       buffer->set(counter, shared);
13241     }
13242     counter++;
13243   }
13244   return counter;
13245 }
13246 
13247 
13248 // For a script finds all SharedFunctionInfo's in the heap that points
13249 // to this script. Returns JSArray of SharedFunctionInfo wrapped
13250 // in OpaqueReferences.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFindSharedFunctionInfosForScript)13251 RUNTIME_FUNCTION(MaybeObject*,
13252                  Runtime_LiveEditFindSharedFunctionInfosForScript) {
13253   HandleScope scope(isolate);
13254   CHECK(isolate->debugger()->live_edit_enabled());
13255   ASSERT(args.length() == 1);
13256   CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13257 
13258   RUNTIME_ASSERT(script_value->value()->IsScript());
13259   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13260 
13261   const int kBufferSize = 32;
13262 
13263   Handle<FixedArray> array;
13264   array = isolate->factory()->NewFixedArray(kBufferSize);
13265   int number;
13266   Heap* heap = isolate->heap();
13267   {
13268     heap->EnsureHeapIsIterable();
13269     DisallowHeapAllocation no_allocation;
13270     HeapIterator heap_iterator(heap);
13271     Script* scr = *script;
13272     FixedArray* arr = *array;
13273     number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13274   }
13275   if (number > kBufferSize) {
13276     array = isolate->factory()->NewFixedArray(number);
13277     heap->EnsureHeapIsIterable();
13278     DisallowHeapAllocation no_allocation;
13279     HeapIterator heap_iterator(heap);
13280     Script* scr = *script;
13281     FixedArray* arr = *array;
13282     FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13283   }
13284 
13285   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13286   result->set_length(Smi::FromInt(number));
13287 
13288   LiveEdit::WrapSharedFunctionInfos(result);
13289 
13290   return *result;
13291 }
13292 
13293 
13294 // For a script calculates compilation information about all its functions.
13295 // The script source is explicitly specified by the second argument.
13296 // The source of the actual script is not used, however it is important that
13297 // all generated code keeps references to this particular instance of script.
13298 // Returns a JSArray of compilation infos. The array is ordered so that
13299 // each function with all its descendant is always stored in a continues range
13300 // with the function itself going first. The root function is a script function.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditGatherCompileInfo)13301 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
13302   HandleScope scope(isolate);
13303   CHECK(isolate->debugger()->live_edit_enabled());
13304   ASSERT(args.length() == 2);
13305   CONVERT_ARG_CHECKED(JSValue, script, 0);
13306   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13307 
13308   RUNTIME_ASSERT(script->value()->IsScript());
13309   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13310 
13311   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
13312 
13313   if (isolate->has_pending_exception()) {
13314     return Failure::Exception();
13315   }
13316 
13317   return result;
13318 }
13319 
13320 
13321 // Changes the source of the script to a new_source.
13322 // If old_script_name is provided (i.e. is a String), also creates a copy of
13323 // the script with its original source and sends notification to debugger.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceScript)13324 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
13325   HandleScope scope(isolate);
13326   CHECK(isolate->debugger()->live_edit_enabled());
13327   ASSERT(args.length() == 3);
13328   CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13329   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13330   Handle<Object> old_script_name(args[2], isolate);
13331 
13332   RUNTIME_ASSERT(original_script_value->value()->IsScript());
13333   Handle<Script> original_script(Script::cast(original_script_value->value()));
13334 
13335   Object* old_script = LiveEdit::ChangeScriptSource(original_script,
13336                                                     new_source,
13337                                                     old_script_name);
13338 
13339   if (old_script->IsScript()) {
13340     Handle<Script> script_handle(Script::cast(old_script));
13341     return *(GetScriptWrapper(script_handle));
13342   } else {
13343     return isolate->heap()->null_value();
13344   }
13345 }
13346 
13347 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFunctionSourceUpdated)13348 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
13349   HandleScope scope(isolate);
13350   CHECK(isolate->debugger()->live_edit_enabled());
13351   ASSERT(args.length() == 1);
13352   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13353   return LiveEdit::FunctionSourceUpdated(shared_info);
13354 }
13355 
13356 
13357 // Replaces code of SharedFunctionInfo with a new one.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceFunctionCode)13358 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
13359   HandleScope scope(isolate);
13360   CHECK(isolate->debugger()->live_edit_enabled());
13361   ASSERT(args.length() == 2);
13362   CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13363   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13364 
13365   return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13366 }
13367 
13368 
13369 // Connects SharedFunctionInfo to another script.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFunctionSetScript)13370 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
13371   HandleScope scope(isolate);
13372   CHECK(isolate->debugger()->live_edit_enabled());
13373   ASSERT(args.length() == 2);
13374   Handle<Object> function_object(args[0], isolate);
13375   Handle<Object> script_object(args[1], isolate);
13376 
13377   if (function_object->IsJSValue()) {
13378     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13379     if (script_object->IsJSValue()) {
13380       RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13381       Script* script = Script::cast(JSValue::cast(*script_object)->value());
13382       script_object = Handle<Object>(script, isolate);
13383     }
13384 
13385     LiveEdit::SetFunctionScript(function_wrapper, script_object);
13386   } else {
13387     // Just ignore this. We may not have a SharedFunctionInfo for some functions
13388     // and we check it in this function.
13389   }
13390 
13391   return isolate->heap()->undefined_value();
13392 }
13393 
13394 
13395 // In a code of a parent function replaces original function as embedded object
13396 // with a substitution one.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceRefToNestedFunction)13397 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
13398   HandleScope scope(isolate);
13399   CHECK(isolate->debugger()->live_edit_enabled());
13400   ASSERT(args.length() == 3);
13401 
13402   CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13403   CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13404   CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13405 
13406   LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
13407                                        subst_wrapper);
13408 
13409   return isolate->heap()->undefined_value();
13410 }
13411 
13412 
13413 // Updates positions of a shared function info (first parameter) according
13414 // to script source change. Text change is described in second parameter as
13415 // array of groups of 3 numbers:
13416 // (change_begin, change_end, change_end_new_position).
13417 // Each group describes a change in text; groups are sorted by change_begin.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditPatchFunctionPositions)13418 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
13419   HandleScope scope(isolate);
13420   CHECK(isolate->debugger()->live_edit_enabled());
13421   ASSERT(args.length() == 2);
13422   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13423   CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13424 
13425   return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13426 }
13427 
13428 
13429 // For array of SharedFunctionInfo's (each wrapped in JSValue)
13430 // checks that none of them have activations on stacks (of any thread).
13431 // Returns array of the same length with corresponding results of
13432 // LiveEdit::FunctionPatchabilityStatus type.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditCheckAndDropActivations)13433 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
13434   HandleScope scope(isolate);
13435   CHECK(isolate->debugger()->live_edit_enabled());
13436   ASSERT(args.length() == 2);
13437   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13438   CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13439 
13440   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13441 }
13442 
13443 
13444 // Compares 2 strings line-by-line, then token-wise and returns diff in form
13445 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13446 // of diff chunks.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditCompareStrings)13447 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
13448   HandleScope scope(isolate);
13449   CHECK(isolate->debugger()->live_edit_enabled());
13450   ASSERT(args.length() == 2);
13451   CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13452   CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13453 
13454   return *LiveEdit::CompareStrings(s1, s2);
13455 }
13456 
13457 
13458 // Restarts a call frame and completely drops all frames above.
13459 // Returns true if successful. Otherwise returns undefined or an error message.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditRestartFrame)13460 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
13461   HandleScope scope(isolate);
13462   CHECK(isolate->debugger()->live_edit_enabled());
13463   ASSERT(args.length() == 2);
13464 
13465   // Check arguments.
13466   Object* check;
13467   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
13468       RUNTIME_ARGUMENTS(isolate, args));
13469     if (!maybe_check->ToObject(&check)) return maybe_check;
13470   }
13471   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13472   Heap* heap = isolate->heap();
13473 
13474   // Find the relevant frame with the requested index.
13475   StackFrame::Id id = isolate->debug()->break_frame_id();
13476   if (id == StackFrame::NO_ID) {
13477     // If there are no JavaScript stack frames return undefined.
13478     return heap->undefined_value();
13479   }
13480 
13481   int count = 0;
13482   JavaScriptFrameIterator it(isolate, id);
13483   for (; !it.done(); it.Advance()) {
13484     if (index < count + it.frame()->GetInlineCount()) break;
13485     count += it.frame()->GetInlineCount();
13486   }
13487   if (it.done()) return heap->undefined_value();
13488 
13489   const char* error_message = LiveEdit::RestartFrame(it.frame());
13490   if (error_message) {
13491     return *(isolate->factory()->InternalizeUtf8String(error_message));
13492   }
13493   return heap->true_value();
13494 }
13495 
13496 
13497 // A testing entry. Returns statement position which is the closest to
13498 // source_position.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionCodePositionFromSource)13499 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
13500   HandleScope scope(isolate);
13501   CHECK(isolate->debugger()->live_edit_enabled());
13502   ASSERT(args.length() == 2);
13503   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13504   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13505 
13506   Handle<Code> code(function->code(), isolate);
13507 
13508   if (code->kind() != Code::FUNCTION &&
13509       code->kind() != Code::OPTIMIZED_FUNCTION) {
13510     return isolate->heap()->undefined_value();
13511   }
13512 
13513   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13514   int closest_pc = 0;
13515   int distance = kMaxInt;
13516   while (!it.done()) {
13517     int statement_position = static_cast<int>(it.rinfo()->data());
13518     // Check if this break point is closer that what was previously found.
13519     if (source_position <= statement_position &&
13520         statement_position - source_position < distance) {
13521       closest_pc =
13522           static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13523       distance = statement_position - source_position;
13524       // Check whether we can't get any closer.
13525       if (distance == 0) break;
13526     }
13527     it.next();
13528   }
13529 
13530   return Smi::FromInt(closest_pc);
13531 }
13532 
13533 
13534 // Calls specified function with or without entering the debugger.
13535 // This is used in unit tests to run code as if debugger is entered or simply
13536 // to have a stack with C++ frame in the middle.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ExecuteInDebugContext)13537 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
13538   HandleScope scope(isolate);
13539   ASSERT(args.length() == 2);
13540   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13541   CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13542 
13543   Handle<Object> result;
13544   bool pending_exception;
13545   {
13546     if (without_debugger) {
13547       result = Execution::Call(isolate,
13548                                function,
13549                                isolate->global_object(),
13550                                0,
13551                                NULL,
13552                                &pending_exception);
13553     } else {
13554       EnterDebugger enter_debugger(isolate);
13555       result = Execution::Call(isolate,
13556                                function,
13557                                isolate->global_object(),
13558                                0,
13559                                NULL,
13560                                &pending_exception);
13561     }
13562   }
13563   if (!pending_exception) {
13564     return *result;
13565   } else {
13566     return Failure::Exception();
13567   }
13568 }
13569 
13570 
13571 // Sets a v8 flag.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetFlags)13572 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
13573   SealHandleScope shs(isolate);
13574   CONVERT_ARG_CHECKED(String, arg, 0);
13575   SmartArrayPointer<char> flags =
13576       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13577   FlagList::SetFlagsFromString(*flags, StrLength(*flags));
13578   return isolate->heap()->undefined_value();
13579 }
13580 
13581 
13582 // Performs a GC.
13583 // Presently, it only does a full GC.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CollectGarbage)13584 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
13585   SealHandleScope shs(isolate);
13586   isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13587   return isolate->heap()->undefined_value();
13588 }
13589 
13590 
13591 // Gets the current heap usage.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetHeapUsage)13592 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
13593   SealHandleScope shs(isolate);
13594   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13595   if (!Smi::IsValid(usage)) {
13596     return *isolate->factory()->NewNumberFromInt(usage);
13597   }
13598   return Smi::FromInt(usage);
13599 }
13600 
13601 #endif  // ENABLE_DEBUGGER_SUPPORT
13602 
13603 
13604 #ifdef V8_I18N_SUPPORT
RUNTIME_FUNCTION(MaybeObject *,Runtime_CanonicalizeLanguageTag)13605 RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
13606   HandleScope scope(isolate);
13607 
13608   ASSERT(args.length() == 1);
13609   CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13610 
13611   v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13612 
13613   // Return value which denotes invalid language tag.
13614   const char* const kInvalidTag = "invalid-tag";
13615 
13616   UErrorCode error = U_ZERO_ERROR;
13617   char icu_result[ULOC_FULLNAME_CAPACITY];
13618   int icu_length = 0;
13619 
13620   uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13621                       &icu_length, &error);
13622   if (U_FAILURE(error) || icu_length == 0) {
13623     return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13624   }
13625 
13626   char result[ULOC_FULLNAME_CAPACITY];
13627 
13628   // Force strict BCP47 rules.
13629   uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13630 
13631   if (U_FAILURE(error)) {
13632     return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13633   }
13634 
13635   return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13636 }
13637 
13638 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AvailableLocalesOf)13639 RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
13640   HandleScope scope(isolate);
13641 
13642   ASSERT(args.length() == 1);
13643   CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13644 
13645   const icu::Locale* available_locales = NULL;
13646   int32_t count = 0;
13647 
13648   if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13649     available_locales = icu::Collator::getAvailableLocales(count);
13650   } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13651     available_locales = icu::NumberFormat::getAvailableLocales(count);
13652   } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13653     available_locales = icu::DateFormat::getAvailableLocales(count);
13654   } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13655     available_locales = icu::BreakIterator::getAvailableLocales(count);
13656   }
13657 
13658   UErrorCode error = U_ZERO_ERROR;
13659   char result[ULOC_FULLNAME_CAPACITY];
13660   Handle<JSObject> locales =
13661       isolate->factory()->NewJSObject(isolate->object_function());
13662 
13663   for (int32_t i = 0; i < count; ++i) {
13664     const char* icu_name = available_locales[i].getName();
13665 
13666     error = U_ZERO_ERROR;
13667     // No need to force strict BCP47 rules.
13668     uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13669     if (U_FAILURE(error)) {
13670       // This shouldn't happen, but lets not break the user.
13671       continue;
13672     }
13673 
13674     RETURN_IF_EMPTY_HANDLE(isolate,
13675         JSObject::SetLocalPropertyIgnoreAttributes(
13676             locales,
13677             isolate->factory()->NewStringFromAscii(CStrVector(result)),
13678             isolate->factory()->NewNumber(i),
13679             NONE));
13680   }
13681 
13682   return *locales;
13683 }
13684 
13685 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetDefaultICULocale)13686 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
13687   SealHandleScope shs(isolate);
13688 
13689   ASSERT(args.length() == 0);
13690 
13691   icu::Locale default_locale;
13692 
13693   // Set the locale
13694   char result[ULOC_FULLNAME_CAPACITY];
13695   UErrorCode status = U_ZERO_ERROR;
13696   uloc_toLanguageTag(
13697       default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13698   if (U_SUCCESS(status)) {
13699     return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13700   }
13701 
13702   return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
13703 }
13704 
13705 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLanguageTagVariants)13706 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
13707   HandleScope scope(isolate);
13708 
13709   ASSERT(args.length() == 1);
13710 
13711   CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13712 
13713   uint32_t length = static_cast<uint32_t>(input->length()->Number());
13714   Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
13715   Handle<Name> maximized =
13716       isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
13717   Handle<Name> base =
13718       isolate->factory()->NewStringFromAscii(CStrVector("base"));
13719   for (unsigned int i = 0; i < length; ++i) {
13720     MaybeObject* maybe_string = input->GetElement(isolate, i);
13721     Object* locale_id;
13722     if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
13723       return isolate->Throw(isolate->heap()->illegal_argument_string());
13724     }
13725 
13726     v8::String::Utf8Value utf8_locale_id(
13727         v8::Utils::ToLocal(Handle<String>(String::cast(locale_id))));
13728 
13729     UErrorCode error = U_ZERO_ERROR;
13730 
13731     // Convert from BCP47 to ICU format.
13732     // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13733     char icu_locale[ULOC_FULLNAME_CAPACITY];
13734     int icu_locale_length = 0;
13735     uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13736                         &icu_locale_length, &error);
13737     if (U_FAILURE(error) || icu_locale_length == 0) {
13738       return isolate->Throw(isolate->heap()->illegal_argument_string());
13739     }
13740 
13741     // Maximize the locale.
13742     // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13743     char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13744     uloc_addLikelySubtags(
13745         icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13746 
13747     // Remove extensions from maximized locale.
13748     // de_Latn_DE@collation=phonebook -> de_Latn_DE
13749     char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13750     uloc_getBaseName(
13751         icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13752 
13753     // Get original name without extensions.
13754     // de_DE@collation=phonebook -> de_DE
13755     char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13756     uloc_getBaseName(
13757         icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13758 
13759     // Convert from ICU locale format to BCP47 format.
13760     // de_Latn_DE -> de-Latn-DE
13761     char base_max_locale[ULOC_FULLNAME_CAPACITY];
13762     uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13763                        ULOC_FULLNAME_CAPACITY, FALSE, &error);
13764 
13765     // de_DE -> de-DE
13766     char base_locale[ULOC_FULLNAME_CAPACITY];
13767     uloc_toLanguageTag(
13768         icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13769 
13770     if (U_FAILURE(error)) {
13771       return isolate->Throw(isolate->heap()->illegal_argument_string());
13772     }
13773 
13774     Handle<JSObject> result =
13775         isolate->factory()->NewJSObject(isolate->object_function());
13776     RETURN_IF_EMPTY_HANDLE(isolate,
13777         JSObject::SetLocalPropertyIgnoreAttributes(
13778             result,
13779             maximized,
13780             isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
13781             NONE));
13782     RETURN_IF_EMPTY_HANDLE(isolate,
13783         JSObject::SetLocalPropertyIgnoreAttributes(
13784             result,
13785             base,
13786             isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
13787             NONE));
13788     output->set(i, *result);
13789   }
13790 
13791   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
13792   result->set_length(Smi::FromInt(length));
13793   return *result;
13794 }
13795 
13796 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateDateTimeFormat)13797 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
13798   HandleScope scope(isolate);
13799 
13800   ASSERT(args.length() == 3);
13801 
13802   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13803   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13804   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13805 
13806   Handle<ObjectTemplateInfo> date_format_template =
13807       I18N::GetTemplate(isolate);
13808 
13809   // Create an empty object wrapper.
13810   bool has_pending_exception = false;
13811   Handle<JSObject> local_object = Execution::InstantiateObject(
13812       date_format_template, &has_pending_exception);
13813   if (has_pending_exception) {
13814     ASSERT(isolate->has_pending_exception());
13815     return Failure::Exception();
13816   }
13817 
13818   // Set date time formatter as internal field of the resulting JS object.
13819   icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
13820       isolate, locale, options, resolved);
13821 
13822   if (!date_format) return isolate->ThrowIllegalOperation();
13823 
13824   local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
13825 
13826   RETURN_IF_EMPTY_HANDLE(isolate,
13827       JSObject::SetLocalPropertyIgnoreAttributes(
13828           local_object,
13829           isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
13830           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13831           NONE));
13832 
13833   // Make object handle weak so we can delete the data format once GC kicks in.
13834   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
13835   GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
13836                           NULL,
13837                           DateFormat::DeleteDateFormat);
13838   return *local_object;
13839 }
13840 
13841 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InternalDateFormat)13842 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
13843   HandleScope scope(isolate);
13844 
13845   ASSERT(args.length() == 2);
13846 
13847   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13848   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
13849 
13850   bool has_pending_exception = false;
13851   Handle<Object> value =
13852       Execution::ToNumber(isolate, date, &has_pending_exception);
13853   if (has_pending_exception) {
13854     ASSERT(isolate->has_pending_exception());
13855     return Failure::Exception();
13856   }
13857 
13858   icu::SimpleDateFormat* date_format =
13859       DateFormat::UnpackDateFormat(isolate, date_format_holder);
13860   if (!date_format) return isolate->ThrowIllegalOperation();
13861 
13862   icu::UnicodeString result;
13863   date_format->format(value->Number(), result);
13864 
13865   return *isolate->factory()->NewStringFromTwoByte(
13866       Vector<const uint16_t>(
13867           reinterpret_cast<const uint16_t*>(result.getBuffer()),
13868           result.length()));
13869 }
13870 
13871 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InternalDateParse)13872 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
13873   HandleScope scope(isolate);
13874 
13875   ASSERT(args.length() == 2);
13876 
13877   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13878   CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
13879 
13880   v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
13881   icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
13882   icu::SimpleDateFormat* date_format =
13883       DateFormat::UnpackDateFormat(isolate, date_format_holder);
13884   if (!date_format) return isolate->ThrowIllegalOperation();
13885 
13886   UErrorCode status = U_ZERO_ERROR;
13887   UDate date = date_format->parse(u_date, status);
13888   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
13889 
13890   bool has_pending_exception = false;
13891   Handle<JSDate> result = Handle<JSDate>::cast(
13892       Execution::NewDate(
13893           isolate, static_cast<double>(date), &has_pending_exception));
13894   if (has_pending_exception) {
13895     ASSERT(isolate->has_pending_exception());
13896     return Failure::Exception();
13897   }
13898   return *result;
13899 }
13900 
13901 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateNumberFormat)13902 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
13903   HandleScope scope(isolate);
13904 
13905   ASSERT(args.length() == 3);
13906 
13907   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13908   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13909   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13910 
13911   Handle<ObjectTemplateInfo> number_format_template =
13912       I18N::GetTemplate(isolate);
13913 
13914   // Create an empty object wrapper.
13915   bool has_pending_exception = false;
13916   Handle<JSObject> local_object = Execution::InstantiateObject(
13917       number_format_template, &has_pending_exception);
13918   if (has_pending_exception) {
13919     ASSERT(isolate->has_pending_exception());
13920     return Failure::Exception();
13921   }
13922 
13923   // Set number formatter as internal field of the resulting JS object.
13924   icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
13925       isolate, locale, options, resolved);
13926 
13927   if (!number_format) return isolate->ThrowIllegalOperation();
13928 
13929   local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
13930 
13931   RETURN_IF_EMPTY_HANDLE(isolate,
13932       JSObject::SetLocalPropertyIgnoreAttributes(
13933           local_object,
13934           isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
13935           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13936           NONE));
13937 
13938   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
13939   GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
13940                           NULL,
13941                           NumberFormat::DeleteNumberFormat);
13942   return *local_object;
13943 }
13944 
13945 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InternalNumberFormat)13946 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
13947   HandleScope scope(isolate);
13948 
13949   ASSERT(args.length() == 2);
13950 
13951   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13952   CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
13953 
13954   bool has_pending_exception = false;
13955   Handle<Object> value = Execution::ToNumber(
13956       isolate, number, &has_pending_exception);
13957   if (has_pending_exception) {
13958     ASSERT(isolate->has_pending_exception());
13959     return Failure::Exception();
13960   }
13961 
13962   icu::DecimalFormat* number_format =
13963       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13964   if (!number_format) return isolate->ThrowIllegalOperation();
13965 
13966   icu::UnicodeString result;
13967   number_format->format(value->Number(), result);
13968 
13969   return *isolate->factory()->NewStringFromTwoByte(
13970       Vector<const uint16_t>(
13971           reinterpret_cast<const uint16_t*>(result.getBuffer()),
13972           result.length()));
13973 }
13974 
13975 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InternalNumberParse)13976 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
13977   HandleScope scope(isolate);
13978 
13979   ASSERT(args.length() == 2);
13980 
13981   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13982   CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
13983 
13984   v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
13985   icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
13986   icu::DecimalFormat* number_format =
13987       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13988   if (!number_format) return isolate->ThrowIllegalOperation();
13989 
13990   UErrorCode status = U_ZERO_ERROR;
13991   icu::Formattable result;
13992   // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
13993   // to be part of Chrome.
13994   // TODO(cira): Include currency parsing code using parseCurrency call.
13995   // We need to check if the formatter parses all currencies or only the
13996   // one it was constructed with (it will impact the API - how to return ISO
13997   // code and the value).
13998   number_format->parse(u_number, result, status);
13999   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14000 
14001   switch (result.getType()) {
14002   case icu::Formattable::kDouble:
14003     return *isolate->factory()->NewNumber(result.getDouble());
14004   case icu::Formattable::kLong:
14005     return *isolate->factory()->NewNumberFromInt(result.getLong());
14006   case icu::Formattable::kInt64:
14007     return *isolate->factory()->NewNumber(
14008         static_cast<double>(result.getInt64()));
14009   default:
14010     return isolate->heap()->undefined_value();
14011   }
14012 }
14013 
14014 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateCollator)14015 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
14016   HandleScope scope(isolate);
14017 
14018   ASSERT(args.length() == 3);
14019 
14020   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14021   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14022   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14023 
14024   Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
14025 
14026   // Create an empty object wrapper.
14027   bool has_pending_exception = false;
14028   Handle<JSObject> local_object = Execution::InstantiateObject(
14029       collator_template, &has_pending_exception);
14030   if (has_pending_exception) {
14031     ASSERT(isolate->has_pending_exception());
14032     return Failure::Exception();
14033   }
14034 
14035   // Set collator as internal field of the resulting JS object.
14036   icu::Collator* collator = Collator::InitializeCollator(
14037       isolate, locale, options, resolved);
14038 
14039   if (!collator) return isolate->ThrowIllegalOperation();
14040 
14041   local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
14042 
14043   RETURN_IF_EMPTY_HANDLE(isolate,
14044       JSObject::SetLocalPropertyIgnoreAttributes(
14045           local_object,
14046           isolate->factory()->NewStringFromAscii(CStrVector("collator")),
14047           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14048           NONE));
14049 
14050   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14051   GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
14052                           NULL,
14053                           Collator::DeleteCollator);
14054   return *local_object;
14055 }
14056 
14057 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InternalCompare)14058 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
14059   HandleScope scope(isolate);
14060 
14061   ASSERT(args.length() == 3);
14062 
14063   CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
14064   CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
14065   CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
14066 
14067   icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
14068   if (!collator) return isolate->ThrowIllegalOperation();
14069 
14070   v8::String::Value string_value1(v8::Utils::ToLocal(string1));
14071   v8::String::Value string_value2(v8::Utils::ToLocal(string2));
14072   const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
14073   const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
14074   UErrorCode status = U_ZERO_ERROR;
14075   UCollationResult result = collator->compare(u_string1,
14076                                               string_value1.length(),
14077                                               u_string2,
14078                                               string_value2.length(),
14079                                               status);
14080   if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
14081 
14082   return *isolate->factory()->NewNumberFromInt(result);
14083 }
14084 
14085 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateBreakIterator)14086 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
14087   HandleScope scope(isolate);
14088 
14089   ASSERT(args.length() == 3);
14090 
14091   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14092   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14093   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14094 
14095   Handle<ObjectTemplateInfo> break_iterator_template =
14096       I18N::GetTemplate2(isolate);
14097 
14098   // Create an empty object wrapper.
14099   bool has_pending_exception = false;
14100   Handle<JSObject> local_object = Execution::InstantiateObject(
14101       break_iterator_template, &has_pending_exception);
14102   if (has_pending_exception) {
14103     ASSERT(isolate->has_pending_exception());
14104     return Failure::Exception();
14105   }
14106 
14107   // Set break iterator as internal field of the resulting JS object.
14108   icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
14109       isolate, locale, options, resolved);
14110 
14111   if (!break_iterator) return isolate->ThrowIllegalOperation();
14112 
14113   local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
14114   // Make sure that the pointer to adopted text is NULL.
14115   local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
14116 
14117   RETURN_IF_EMPTY_HANDLE(isolate,
14118       JSObject::SetLocalPropertyIgnoreAttributes(
14119           local_object,
14120           isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")),
14121           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14122           NONE));
14123 
14124   // Make object handle weak so we can delete the break iterator once GC kicks
14125   // in.
14126   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14127   GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
14128                           NULL,
14129                           BreakIterator::DeleteBreakIterator);
14130   return *local_object;
14131 }
14132 
14133 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BreakIteratorAdoptText)14134 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
14135   HandleScope scope(isolate);
14136 
14137   ASSERT(args.length() == 2);
14138 
14139   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14140   CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
14141 
14142   icu::BreakIterator* break_iterator =
14143       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14144   if (!break_iterator) return isolate->ThrowIllegalOperation();
14145 
14146   icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
14147       break_iterator_holder->GetInternalField(1));
14148   delete u_text;
14149 
14150   v8::String::Value text_value(v8::Utils::ToLocal(text));
14151   u_text = new icu::UnicodeString(
14152       reinterpret_cast<const UChar*>(*text_value), text_value.length());
14153   break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
14154 
14155   break_iterator->setText(*u_text);
14156 
14157   return isolate->heap()->undefined_value();
14158 }
14159 
14160 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BreakIteratorFirst)14161 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
14162   HandleScope scope(isolate);
14163 
14164   ASSERT(args.length() == 1);
14165 
14166   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14167 
14168   icu::BreakIterator* break_iterator =
14169       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14170   if (!break_iterator) return isolate->ThrowIllegalOperation();
14171 
14172   return *isolate->factory()->NewNumberFromInt(break_iterator->first());
14173 }
14174 
14175 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BreakIteratorNext)14176 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
14177   HandleScope scope(isolate);
14178 
14179   ASSERT(args.length() == 1);
14180 
14181   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14182 
14183   icu::BreakIterator* break_iterator =
14184       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14185   if (!break_iterator) return isolate->ThrowIllegalOperation();
14186 
14187   return *isolate->factory()->NewNumberFromInt(break_iterator->next());
14188 }
14189 
14190 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BreakIteratorCurrent)14191 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
14192   HandleScope scope(isolate);
14193 
14194   ASSERT(args.length() == 1);
14195 
14196   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14197 
14198   icu::BreakIterator* break_iterator =
14199       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14200   if (!break_iterator) return isolate->ThrowIllegalOperation();
14201 
14202   return *isolate->factory()->NewNumberFromInt(break_iterator->current());
14203 }
14204 
14205 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BreakIteratorBreakType)14206 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
14207   HandleScope scope(isolate);
14208 
14209   ASSERT(args.length() == 1);
14210 
14211   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14212 
14213   icu::BreakIterator* break_iterator =
14214       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14215   if (!break_iterator) return isolate->ThrowIllegalOperation();
14216 
14217   // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
14218   icu::RuleBasedBreakIterator* rule_based_iterator =
14219       static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
14220   int32_t status = rule_based_iterator->getRuleStatus();
14221   // Keep return values in sync with JavaScript BreakType enum.
14222   if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
14223     return *isolate->factory()->NewStringFromAscii(CStrVector("none"));
14224   } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
14225     return *isolate->factory()->NewStringFromAscii(CStrVector("number"));
14226   } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
14227     return *isolate->factory()->NewStringFromAscii(CStrVector("letter"));
14228   } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
14229     return *isolate->factory()->NewStringFromAscii(CStrVector("kana"));
14230   } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
14231     return *isolate->factory()->NewStringFromAscii(CStrVector("ideo"));
14232   } else {
14233     return *isolate->factory()->NewStringFromAscii(CStrVector("unknown"));
14234   }
14235 }
14236 #endif  // V8_I18N_SUPPORT
14237 
14238 
14239 // Finds the script object from the script data. NOTE: This operation uses
14240 // heap traversal to find the function generated for the source position
14241 // for the requested break point. For lazily compiled functions several heap
14242 // traversals might be required rendering this operation as a rather slow
14243 // operation. However for setting break points which is normally done through
14244 // some kind of user interaction the performance is not crucial.
Runtime_GetScriptFromScriptName(Handle<String> script_name)14245 static Handle<Object> Runtime_GetScriptFromScriptName(
14246     Handle<String> script_name) {
14247   // Scan the heap for Script objects to find the script with the requested
14248   // script data.
14249   Handle<Script> script;
14250   Factory* factory = script_name->GetIsolate()->factory();
14251   Heap* heap = script_name->GetHeap();
14252   heap->EnsureHeapIsIterable();
14253   DisallowHeapAllocation no_allocation_during_heap_iteration;
14254   HeapIterator iterator(heap);
14255   HeapObject* obj = NULL;
14256   while (script.is_null() && ((obj = iterator.next()) != NULL)) {
14257     // If a script is found check if it has the script data requested.
14258     if (obj->IsScript()) {
14259       if (Script::cast(obj)->name()->IsString()) {
14260         if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
14261           script = Handle<Script>(Script::cast(obj));
14262         }
14263       }
14264     }
14265   }
14266 
14267   // If no script with the requested script data is found return undefined.
14268   if (script.is_null()) return factory->undefined_value();
14269 
14270   // Return the script found.
14271   return GetScriptWrapper(script);
14272 }
14273 
14274 
14275 // Get the script object from script data. NOTE: Regarding performance
14276 // see the NOTE for GetScriptFromScriptData.
14277 // args[0]: script data for the script to find the source for
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScript)14278 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
14279   HandleScope scope(isolate);
14280 
14281   ASSERT(args.length() == 1);
14282 
14283   CONVERT_ARG_CHECKED(String, script_name, 0);
14284 
14285   // Find the requested script.
14286   Handle<Object> result =
14287       Runtime_GetScriptFromScriptName(Handle<String>(script_name));
14288   return *result;
14289 }
14290 
14291 
14292 // Collect the raw data for a stack trace.  Returns an array of 4
14293 // element segments each containing a receiver, function, code and
14294 // native code offset.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CollectStackTrace)14295 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
14296   HandleScope scope(isolate);
14297   ASSERT_EQ(args.length(), 3);
14298   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14299   Handle<Object> caller = args.at<Object>(1);
14300   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
14301 
14302   // Optionally capture a more detailed stack trace for the message.
14303   isolate->CaptureAndSetDetailedStackTrace(error_object);
14304   // Capture a simple stack trace for the stack property.
14305   return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
14306 }
14307 
14308 
14309 // Retrieve the stack trace.  This is the raw stack trace that yet has to
14310 // be formatted.  Since we only need this once, clear it afterwards.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetAndClearOverflowedStackTrace)14311 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
14312   HandleScope scope(isolate);
14313   ASSERT_EQ(args.length(), 1);
14314   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14315   Handle<String> key = isolate->factory()->hidden_stack_trace_string();
14316   Handle<Object> result(error_object->GetHiddenProperty(*key), isolate);
14317   if (result->IsTheHole()) return isolate->heap()->undefined_value();
14318   RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
14319   JSObject::DeleteHiddenProperty(error_object, key);
14320   return *result;
14321 }
14322 
14323 
14324 // Returns V8 version as a string.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetV8Version)14325 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
14326   SealHandleScope shs(isolate);
14327   ASSERT_EQ(args.length(), 0);
14328 
14329   const char* version_string = v8::V8::GetVersion();
14330 
14331   return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
14332                                                   NOT_TENURED);
14333 }
14334 
14335 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Abort)14336 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
14337   SealHandleScope shs(isolate);
14338   ASSERT(args.length() == 2);
14339   OS::PrintError("abort: %s\n",
14340                  reinterpret_cast<char*>(args[0]) + args.smi_at(1));
14341   isolate->PrintStack(stderr);
14342   OS::Abort();
14343   UNREACHABLE();
14344   return NULL;
14345 }
14346 
14347 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AbortJS)14348 RUNTIME_FUNCTION(MaybeObject*, Runtime_AbortJS) {
14349   HandleScope scope(isolate);
14350   ASSERT(args.length() == 1);
14351   CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
14352   OS::PrintError("abort: %s\n", *message->ToCString());
14353   isolate->PrintStack(stderr);
14354   OS::Abort();
14355   UNREACHABLE();
14356   return NULL;
14357 }
14358 
14359 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FlattenString)14360 RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
14361   HandleScope scope(isolate);
14362   ASSERT(args.length() == 1);
14363   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
14364   FlattenString(str);
14365   return isolate->heap()->undefined_value();
14366 }
14367 
14368 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NotifyContextDisposed)14369 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
14370   HandleScope scope(isolate);
14371   ASSERT(args.length() == 0);
14372   isolate->heap()->NotifyContextDisposed();
14373   return isolate->heap()->undefined_value();
14374 }
14375 
14376 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MigrateInstance)14377 RUNTIME_FUNCTION(MaybeObject*, Runtime_MigrateInstance) {
14378   HandleScope scope(isolate);
14379   ASSERT(args.length() == 1);
14380   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14381   if (!object->IsJSObject()) return Smi::FromInt(0);
14382   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14383   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14384   JSObject::MigrateInstance(js_object);
14385   return *object;
14386 }
14387 
14388 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFromCache)14389 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
14390   SealHandleScope shs(isolate);
14391   // This is only called from codegen, so checks might be more lax.
14392   CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
14393   Object* key = args[1];
14394 
14395   int finger_index = cache->finger_index();
14396   Object* o = cache->get(finger_index);
14397   if (o == key) {
14398     // The fastest case: hit the same place again.
14399     return cache->get(finger_index + 1);
14400   }
14401 
14402   for (int i = finger_index - 2;
14403        i >= JSFunctionResultCache::kEntriesIndex;
14404        i -= 2) {
14405     o = cache->get(i);
14406     if (o == key) {
14407       cache->set_finger_index(i);
14408       return cache->get(i + 1);
14409     }
14410   }
14411 
14412   int size = cache->size();
14413   ASSERT(size <= cache->length());
14414 
14415   for (int i = size - 2; i > finger_index; i -= 2) {
14416     o = cache->get(i);
14417     if (o == key) {
14418       cache->set_finger_index(i);
14419       return cache->get(i + 1);
14420     }
14421   }
14422 
14423   // There is no value in the cache.  Invoke the function and cache result.
14424   HandleScope scope(isolate);
14425 
14426   Handle<JSFunctionResultCache> cache_handle(cache);
14427   Handle<Object> key_handle(key, isolate);
14428   Handle<Object> value;
14429   {
14430     Handle<JSFunction> factory(JSFunction::cast(
14431           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14432     // TODO(antonm): consider passing a receiver when constructing a cache.
14433     Handle<Object> receiver(isolate->native_context()->global_object(),
14434                             isolate);
14435     // This handle is nor shared, nor used later, so it's safe.
14436     Handle<Object> argv[] = { key_handle };
14437     bool pending_exception;
14438     value = Execution::Call(isolate,
14439                             factory,
14440                             receiver,
14441                             ARRAY_SIZE(argv),
14442                             argv,
14443                             &pending_exception);
14444     if (pending_exception) return Failure::Exception();
14445   }
14446 
14447 #ifdef VERIFY_HEAP
14448   if (FLAG_verify_heap) {
14449     cache_handle->JSFunctionResultCacheVerify();
14450   }
14451 #endif
14452 
14453   // Function invocation may have cleared the cache.  Reread all the data.
14454   finger_index = cache_handle->finger_index();
14455   size = cache_handle->size();
14456 
14457   // If we have spare room, put new data into it, otherwise evict post finger
14458   // entry which is likely to be the least recently used.
14459   int index = -1;
14460   if (size < cache_handle->length()) {
14461     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14462     index = size;
14463   } else {
14464     index = finger_index + JSFunctionResultCache::kEntrySize;
14465     if (index == cache_handle->length()) {
14466       index = JSFunctionResultCache::kEntriesIndex;
14467     }
14468   }
14469 
14470   ASSERT(index % 2 == 0);
14471   ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
14472   ASSERT(index < cache_handle->length());
14473 
14474   cache_handle->set(index, *key_handle);
14475   cache_handle->set(index + 1, *value);
14476   cache_handle->set_finger_index(index);
14477 
14478 #ifdef VERIFY_HEAP
14479   if (FLAG_verify_heap) {
14480     cache_handle->JSFunctionResultCacheVerify();
14481   }
14482 #endif
14483 
14484   return *value;
14485 }
14486 
14487 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetStartPosition)14488 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
14489   SealHandleScope shs(isolate);
14490   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14491   return Smi::FromInt(message->start_position());
14492 }
14493 
14494 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetScript)14495 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
14496   SealHandleScope shs(isolate);
14497   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14498   return message->script();
14499 }
14500 
14501 
14502 #ifdef DEBUG
14503 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
14504 // Exclude the code in release mode.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ListNatives)14505 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
14506   HandleScope scope(isolate);
14507   ASSERT(args.length() == 0);
14508 #define COUNT_ENTRY(Name, argc, ressize) + 1
14509   int entry_count = 0
14510       RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14511       INLINE_FUNCTION_LIST(COUNT_ENTRY)
14512       INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
14513 #undef COUNT_ENTRY
14514   Factory* factory = isolate->factory();
14515   Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14516   int index = 0;
14517   bool inline_runtime_functions = false;
14518 #define ADD_ENTRY(Name, argc, ressize)                                       \
14519   {                                                                          \
14520     HandleScope inner(isolate);                                              \
14521     Handle<String> name;                                                     \
14522     /* Inline runtime functions have an underscore in front of the name. */  \
14523     if (inline_runtime_functions) {                                          \
14524       name = factory->NewStringFromAscii(                                    \
14525           Vector<const char>("_" #Name, StrLength("_" #Name)));              \
14526     } else {                                                                 \
14527       name = factory->NewStringFromAscii(                                    \
14528           Vector<const char>(#Name, StrLength(#Name)));                      \
14529     }                                                                        \
14530     Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
14531     pair_elements->set(0, *name);                                            \
14532     pair_elements->set(1, Smi::FromInt(argc));                               \
14533     Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
14534     elements->set(index++, *pair);                                           \
14535   }
14536   inline_runtime_functions = false;
14537   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14538   inline_runtime_functions = true;
14539   INLINE_FUNCTION_LIST(ADD_ENTRY)
14540   INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14541 #undef ADD_ENTRY
14542   ASSERT_EQ(index, entry_count);
14543   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14544   return *result;
14545 }
14546 #endif
14547 
14548 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Log)14549 RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
14550   SealHandleScope shs(isolate);
14551   ASSERT(args.length() == 2);
14552   CONVERT_ARG_CHECKED(String, format, 0);
14553   CONVERT_ARG_CHECKED(JSArray, elms, 1);
14554   DisallowHeapAllocation no_gc;
14555   String::FlatContent format_content = format->GetFlatContent();
14556   RUNTIME_ASSERT(format_content.IsAscii());
14557   Vector<const uint8_t> chars = format_content.ToOneByteVector();
14558   isolate->logger()->LogRuntime(Vector<const char>::cast(chars), elms);
14559   return isolate->heap()->undefined_value();
14560 }
14561 
14562 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IS_VAR)14563 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
14564   UNREACHABLE();  // implemented as macro in the parser
14565   return NULL;
14566 }
14567 
14568 
14569 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
14570   RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
14571     CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
14572     return isolate->heap()->ToBoolean(obj->Has##Name());  \
14573   }
14574 
14575 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)14576 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14577 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14578 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14579 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14580 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14581 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
14582 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
14583 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14584 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
14585 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
14586 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
14587 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
14588 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
14589 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
14590 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
14591 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
14592 // Properties test sitting with elements tests - not fooling anyone.
14593 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
14594 
14595 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14596 
14597 
14598 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
14599   SealHandleScope shs(isolate);
14600   ASSERT(args.length() == 2);
14601   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14602   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14603   return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14604 }
14605 
14606 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsAccessCheckNeeded)14607 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) {
14608   SealHandleScope shs(isolate);
14609   ASSERT(args.length() == 1);
14610   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
14611   return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded());
14612 }
14613 
14614 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsObserved)14615 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
14616   SealHandleScope shs(isolate);
14617   ASSERT(args.length() == 1);
14618 
14619   if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14620   JSReceiver* obj = JSReceiver::cast(args[0]);
14621   if (obj->IsJSGlobalProxy()) {
14622     Object* proto = obj->GetPrototype();
14623     if (proto->IsNull()) return isolate->heap()->false_value();
14624     ASSERT(proto->IsJSGlobalObject());
14625     obj = JSReceiver::cast(proto);
14626   }
14627   return isolate->heap()->ToBoolean(obj->map()->is_observed());
14628 }
14629 
14630 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetIsObserved)14631 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
14632   HandleScope scope(isolate);
14633   ASSERT(args.length() == 1);
14634   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
14635   if (obj->IsJSGlobalProxy()) {
14636     Object* proto = obj->GetPrototype();
14637     if (proto->IsNull()) return isolate->heap()->undefined_value();
14638     ASSERT(proto->IsJSGlobalObject());
14639     obj = handle(JSReceiver::cast(proto));
14640   }
14641   if (obj->IsJSProxy())
14642     return isolate->heap()->undefined_value();
14643 
14644   ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
14645            Handle<JSObject>::cast(obj)->HasFastElements()));
14646   ASSERT(obj->IsJSObject());
14647   JSObject::SetObserved(Handle<JSObject>::cast(obj));
14648   return isolate->heap()->undefined_value();
14649 }
14650 
14651 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetMicrotaskPending)14652 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetMicrotaskPending) {
14653   SealHandleScope shs(isolate);
14654   ASSERT(args.length() == 1);
14655   CONVERT_BOOLEAN_ARG_CHECKED(new_state, 0);
14656   bool old_state = isolate->microtask_pending();
14657   isolate->set_microtask_pending(new_state);
14658   return isolate->heap()->ToBoolean(old_state);
14659 }
14660 
14661 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetObservationState)14662 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
14663   SealHandleScope shs(isolate);
14664   ASSERT(args.length() == 0);
14665   return isolate->heap()->observation_state();
14666 }
14667 
14668 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ObservationWeakMapCreate)14669 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
14670   HandleScope scope(isolate);
14671   ASSERT(args.length() == 0);
14672   // TODO(adamk): Currently this runtime function is only called three times per
14673   // isolate. If it's called more often, the map should be moved into the
14674   // strong root list.
14675   Handle<Map> map =
14676       isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
14677   Handle<JSWeakMap> weakmap =
14678       Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
14679   return WeakCollectionInitialize(isolate, weakmap);
14680 }
14681 
14682 
RUNTIME_FUNCTION(MaybeObject *,Runtime_UnwrapGlobalProxy)14683 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
14684   SealHandleScope shs(isolate);
14685   ASSERT(args.length() == 1);
14686   Object* object = args[0];
14687   if (object->IsJSGlobalProxy()) {
14688     object = object->GetPrototype(isolate);
14689     if (object->IsNull()) return isolate->heap()->undefined_value();
14690   }
14691   return object;
14692 }
14693 
14694 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsAccessAllowedForObserver)14695 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
14696   HandleScope scope(isolate);
14697   ASSERT(args.length() == 3);
14698   CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
14699   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
14700   ASSERT(object->IsAccessCheckNeeded());
14701   Handle<Object> key = args.at<Object>(2);
14702   SaveContext save(isolate);
14703   isolate->set_context(observer->context());
14704   if (!isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
14705                                v8::ACCESS_KEYS)) {
14706     return isolate->heap()->false_value();
14707   }
14708   bool access_allowed = false;
14709   uint32_t index = 0;
14710   if (key->ToArrayIndex(&index) ||
14711       (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) {
14712     access_allowed =
14713         isolate->MayIndexedAccess(*object, index, v8::ACCESS_GET) &&
14714         isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS);
14715   } else {
14716     access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) &&
14717         isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS);
14718   }
14719   return isolate->heap()->ToBoolean(access_allowed);
14720 }
14721 
14722 
ArrayConstructorCommon(Isolate * isolate,Handle<JSFunction> constructor,Handle<AllocationSite> site,Arguments * caller_args)14723 static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
14724                                            Handle<JSFunction> constructor,
14725                                            Handle<AllocationSite> site,
14726                                            Arguments* caller_args) {
14727   bool holey = false;
14728   bool can_use_type_feedback = true;
14729   if (caller_args->length() == 1) {
14730     Object* argument_one = (*caller_args)[0];
14731     if (argument_one->IsSmi()) {
14732       int value = Smi::cast(argument_one)->value();
14733       if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
14734         // the array is a dictionary in this case.
14735         can_use_type_feedback = false;
14736       } else if (value != 0) {
14737         holey = true;
14738       }
14739     } else {
14740       // Non-smi length argument produces a dictionary
14741       can_use_type_feedback = false;
14742     }
14743   }
14744 
14745   JSArray* array;
14746   MaybeObject* maybe_array;
14747   if (!site.is_null() && can_use_type_feedback) {
14748     ElementsKind to_kind = site->GetElementsKind();
14749     if (holey && !IsFastHoleyElementsKind(to_kind)) {
14750       to_kind = GetHoleyElementsKind(to_kind);
14751       // Update the allocation site info to reflect the advice alteration.
14752       site->SetElementsKind(to_kind);
14753     }
14754 
14755     maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite(
14756         *constructor, site);
14757     if (!maybe_array->To(&array)) return maybe_array;
14758   } else {
14759     maybe_array = isolate->heap()->AllocateJSObject(*constructor);
14760     if (!maybe_array->To(&array)) return maybe_array;
14761     // We might need to transition to holey
14762     ElementsKind kind = constructor->initial_map()->elements_kind();
14763     if (holey && !IsFastHoleyElementsKind(kind)) {
14764       kind = GetHoleyElementsKind(kind);
14765       maybe_array = array->TransitionElementsKind(kind);
14766       if (maybe_array->IsFailure()) return maybe_array;
14767     }
14768   }
14769 
14770   maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0,
14771       DONT_INITIALIZE_ARRAY_ELEMENTS);
14772   if (maybe_array->IsFailure()) return maybe_array;
14773   ElementsKind old_kind = array->GetElementsKind();
14774   maybe_array = ArrayConstructInitializeElements(array, caller_args);
14775   if (maybe_array->IsFailure()) return maybe_array;
14776   if (!site.is_null() &&
14777       (old_kind != array->GetElementsKind() ||
14778        !can_use_type_feedback)) {
14779     // The arguments passed in caused a transition. This kind of complexity
14780     // can't be dealt with in the inlined hydrogen array constructor case.
14781     // We must mark the allocationsite as un-inlinable.
14782     site->SetDoNotInlineCall();
14783   }
14784   return array;
14785 }
14786 
14787 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayConstructor)14788 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
14789   HandleScope scope(isolate);
14790   // If we get 2 arguments then they are the stub parameters (constructor, type
14791   // info).  If we get 4, then the first one is a pointer to the arguments
14792   // passed by the caller, and the last one is the length of the arguments
14793   // passed to the caller (redundant, but useful to check on the deoptimizer
14794   // with an assert).
14795   Arguments empty_args(0, NULL);
14796   bool no_caller_args = args.length() == 2;
14797   ASSERT(no_caller_args || args.length() == 4);
14798   int parameters_start = no_caller_args ? 0 : 1;
14799   Arguments* caller_args = no_caller_args
14800       ? &empty_args
14801       : reinterpret_cast<Arguments*>(args[0]);
14802   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14803   CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
14804 #ifdef DEBUG
14805   if (!no_caller_args) {
14806     CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
14807     ASSERT(arg_count == caller_args->length());
14808   }
14809 #endif
14810 
14811   Handle<AllocationSite> site;
14812   if (!type_info.is_null() &&
14813       *type_info != isolate->heap()->undefined_value() &&
14814       Cell::cast(*type_info)->value()->IsAllocationSite()) {
14815     site = Handle<AllocationSite>(
14816         AllocationSite::cast(Cell::cast(*type_info)->value()), isolate);
14817     ASSERT(!site->SitePointsToLiteral());
14818   }
14819 
14820   return ArrayConstructorCommon(isolate,
14821                                 constructor,
14822                                 site,
14823                                 caller_args);
14824 }
14825 
14826 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InternalArrayConstructor)14827 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) {
14828   HandleScope scope(isolate);
14829   Arguments empty_args(0, NULL);
14830   bool no_caller_args = args.length() == 1;
14831   ASSERT(no_caller_args || args.length() == 3);
14832   int parameters_start = no_caller_args ? 0 : 1;
14833   Arguments* caller_args = no_caller_args
14834       ? &empty_args
14835       : reinterpret_cast<Arguments*>(args[0]);
14836   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14837 #ifdef DEBUG
14838   if (!no_caller_args) {
14839     CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
14840     ASSERT(arg_count == caller_args->length());
14841   }
14842 #endif
14843   return ArrayConstructorCommon(isolate,
14844                                 constructor,
14845                                 Handle<AllocationSite>::null(),
14846                                 caller_args);
14847 }
14848 
14849 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MaxSmi)14850 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaxSmi) {
14851   return Smi::FromInt(Smi::kMaxValue);
14852 }
14853 
14854 
14855 // ----------------------------------------------------------------------------
14856 // Implementation of Runtime
14857 
14858 #define F(name, number_of_args, result_size)                             \
14859   { Runtime::k##name, Runtime::RUNTIME, #name,   \
14860     FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
14861 
14862 
14863 #define I(name, number_of_args, result_size)                             \
14864   { Runtime::kInline##name, Runtime::INLINE,     \
14865     "_" #name, NULL, number_of_args, result_size },
14866 
14867 static const Runtime::Function kIntrinsicFunctions[] = {
14868   RUNTIME_FUNCTION_LIST(F)
14869   INLINE_FUNCTION_LIST(I)
14870   INLINE_RUNTIME_FUNCTION_LIST(I)
14871 };
14872 
14873 
InitializeIntrinsicFunctionNames(Heap * heap,Object * dictionary)14874 MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
14875                                                        Object* dictionary) {
14876   ASSERT(dictionary != NULL);
14877   ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
14878   for (int i = 0; i < kNumFunctions; ++i) {
14879     Object* name_string;
14880     { MaybeObject* maybe_name_string =
14881           heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
14882       if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
14883     }
14884     NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
14885     { MaybeObject* maybe_dictionary = name_dictionary->Add(
14886           String::cast(name_string),
14887           Smi::FromInt(i),
14888           PropertyDetails(NONE, NORMAL, Representation::None()));
14889       if (!maybe_dictionary->ToObject(&dictionary)) {
14890         // Non-recoverable failure.  Calling code must restart heap
14891         // initialization.
14892         return maybe_dictionary;
14893       }
14894     }
14895   }
14896   return dictionary;
14897 }
14898 
14899 
FunctionForName(Handle<String> name)14900 const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
14901   Heap* heap = name->GetHeap();
14902   int entry = heap->intrinsic_function_names()->FindEntry(*name);
14903   if (entry != kNotFound) {
14904     Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
14905     int function_index = Smi::cast(smi_index)->value();
14906     return &(kIntrinsicFunctions[function_index]);
14907   }
14908   return NULL;
14909 }
14910 
14911 
FunctionForId(Runtime::FunctionId id)14912 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
14913   return &(kIntrinsicFunctions[static_cast<int>(id)]);
14914 }
14915 
14916 
PerformGC(Object * result,Isolate * isolate)14917 void Runtime::PerformGC(Object* result, Isolate* isolate) {
14918   Failure* failure = Failure::cast(result);
14919   if (failure->IsRetryAfterGC()) {
14920     if (isolate->heap()->new_space()->AddFreshPage()) {
14921       return;
14922     }
14923 
14924     // Try to do a garbage collection; ignore it if it fails. The C
14925     // entry stub will throw an out-of-memory exception in that case.
14926     isolate->heap()->CollectGarbage(failure->allocation_space(),
14927                                     "Runtime::PerformGC");
14928   } else {
14929     // Handle last resort GC and make sure to allow future allocations
14930     // to grow the heap without causing GCs (if possible).
14931     isolate->counters()->gc_last_resort_from_js()->Increment();
14932     isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
14933                                        "Runtime::PerformGC");
14934   }
14935 }
14936 
14937 
14938 } }  // namespace v8::internal
14939