• 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 
30 #include "v8.h"
31 
32 #include "accessors.h"
33 #include "api.h"
34 #include "arguments.h"
35 #include "bootstrapper.h"
36 #include "codegen.h"
37 #include "compilation-cache.h"
38 #include "compiler.h"
39 #include "cpu.h"
40 #include "dateparser-inl.h"
41 #include "debug.h"
42 #include "deoptimizer.h"
43 #include "date.h"
44 #include "execution.h"
45 #include "global-handles.h"
46 #include "isolate-inl.h"
47 #include "jsregexp.h"
48 #include "json-parser.h"
49 #include "liveedit.h"
50 #include "liveobjectlist-inl.h"
51 #include "misc-intrinsics.h"
52 #include "parser.h"
53 #include "platform.h"
54 #include "runtime-profiler.h"
55 #include "runtime.h"
56 #include "scopeinfo.h"
57 #include "smart-array-pointer.h"
58 #include "string-search.h"
59 #include "stub-cache.h"
60 #include "v8threads.h"
61 #include "vm-state-inl.h"
62 
63 namespace v8 {
64 namespace internal {
65 
66 
67 #define RUNTIME_ASSERT(value) \
68   if (!(value)) return isolate->ThrowIllegalOperation();
69 
70 // Cast the given object to a value of the specified type and store
71 // it in a variable with the given name.  If the object is not of the
72 // expected type call IllegalOperation and return.
73 #define CONVERT_ARG_CHECKED(Type, name, index)                       \
74   RUNTIME_ASSERT(args[index]->Is##Type());                           \
75   Type* name = Type::cast(args[index]);
76 
77 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
78   RUNTIME_ASSERT(args[index]->Is##Type());                           \
79   Handle<Type> name = args.at<Type>(index);
80 
81 // Cast the given object to a boolean and store it in a variable with
82 // the given name.  If the object is not a boolean call IllegalOperation
83 // and return.
84 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
85   RUNTIME_ASSERT(args[index]->IsBoolean());                          \
86   bool name = args[index]->IsTrue();
87 
88 // Cast the given argument to a Smi and store its value in an int variable
89 // with the given name.  If the argument is not a Smi call IllegalOperation
90 // and return.
91 #define CONVERT_SMI_ARG_CHECKED(name, index)                         \
92   RUNTIME_ASSERT(args[index]->IsSmi());                              \
93   int name = args.smi_at(index);
94 
95 // Cast the given argument to a double and store it in a variable with
96 // the given name.  If the argument is not a number (as opposed to
97 // the number not-a-number) call IllegalOperation and return.
98 #define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
99   RUNTIME_ASSERT(args[index]->IsNumber());                           \
100   double name = args.number_at(index);
101 
102 // Call the specified converter on the object *comand store the result in
103 // a variable of the specified type with the given name.  If the
104 // object is not a Number call IllegalOperation and return.
105 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
106   RUNTIME_ASSERT(obj->IsNumber());                                   \
107   type name = NumberTo##Type(obj);
108 
109 
110 // Cast the given argument to PropertyDetails and store its value in a
111 // variable with the given name.  If the argument is not a Smi call
112 // IllegalOperation and return.
113 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
114   RUNTIME_ASSERT(args[index]->IsSmi());                              \
115   PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
116 
117 
118 // Assert that the given argument has a valid value for a StrictModeFlag
119 // and store it in a StrictModeFlag variable with the given name.
120 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
121   RUNTIME_ASSERT(args[index]->IsSmi());                              \
122   RUNTIME_ASSERT(args.smi_at(index) == kStrictMode ||                \
123                  args.smi_at(index) == kNonStrictMode);              \
124   StrictModeFlag name =                                              \
125       static_cast<StrictModeFlag>(args.smi_at(index));
126 
127 
128 // Assert that the given argument has a valid value for a LanguageMode
129 // and store it in a LanguageMode variable with the given name.
130 #define CONVERT_LANGUAGE_MODE_ARG(name, index)                       \
131   ASSERT(args[index]->IsSmi());                                      \
132   ASSERT(args.smi_at(index) == CLASSIC_MODE ||                       \
133          args.smi_at(index) == STRICT_MODE ||                        \
134          args.smi_at(index) == EXTENDED_MODE);                       \
135   LanguageMode name =                                                \
136       static_cast<LanguageMode>(args.smi_at(index));
137 
138 
DeepCopyBoilerplate(Isolate * isolate,JSObject * boilerplate)139 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
140                                                    JSObject* boilerplate) {
141   StackLimitCheck check(isolate);
142   if (check.HasOverflowed()) return isolate->StackOverflow();
143 
144   Heap* heap = isolate->heap();
145   Object* result;
146   { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
147     if (!maybe_result->ToObject(&result)) return maybe_result;
148   }
149   JSObject* copy = JSObject::cast(result);
150 
151   // Deep copy local properties.
152   if (copy->HasFastProperties()) {
153     FixedArray* properties = copy->properties();
154     for (int i = 0; i < properties->length(); i++) {
155       Object* value = properties->get(i);
156       if (value->IsJSObject()) {
157         JSObject* js_object = JSObject::cast(value);
158         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
159           if (!maybe_result->ToObject(&result)) return maybe_result;
160         }
161         properties->set(i, result);
162       }
163     }
164     int nof = copy->map()->inobject_properties();
165     for (int i = 0; i < nof; i++) {
166       Object* value = copy->InObjectPropertyAt(i);
167       if (value->IsJSObject()) {
168         JSObject* js_object = JSObject::cast(value);
169         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
170           if (!maybe_result->ToObject(&result)) return maybe_result;
171         }
172         copy->InObjectPropertyAtPut(i, result);
173       }
174     }
175   } else {
176     { MaybeObject* maybe_result =
177           heap->AllocateFixedArray(copy->NumberOfLocalProperties());
178       if (!maybe_result->ToObject(&result)) return maybe_result;
179     }
180     FixedArray* names = FixedArray::cast(result);
181     copy->GetLocalPropertyNames(names, 0);
182     for (int i = 0; i < names->length(); i++) {
183       ASSERT(names->get(i)->IsString());
184       String* key_string = String::cast(names->get(i));
185       PropertyAttributes attributes =
186           copy->GetLocalPropertyAttribute(key_string);
187       // Only deep copy fields from the object literal expression.
188       // In particular, don't try to copy the length attribute of
189       // an array.
190       if (attributes != NONE) continue;
191       Object* value =
192           copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
193       if (value->IsJSObject()) {
194         JSObject* js_object = JSObject::cast(value);
195         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
196           if (!maybe_result->ToObject(&result)) return maybe_result;
197         }
198         { MaybeObject* maybe_result =
199               // Creating object copy for literals. No strict mode needed.
200               copy->SetProperty(key_string, result, NONE, kNonStrictMode);
201           if (!maybe_result->ToObject(&result)) return maybe_result;
202         }
203       }
204     }
205   }
206 
207   // Deep copy local elements.
208   // Pixel elements cannot be created using an object literal.
209   ASSERT(!copy->HasExternalArrayElements());
210   switch (copy->GetElementsKind()) {
211     case FAST_SMI_ONLY_ELEMENTS:
212     case FAST_ELEMENTS: {
213       FixedArray* elements = FixedArray::cast(copy->elements());
214       if (elements->map() == heap->fixed_cow_array_map()) {
215         isolate->counters()->cow_arrays_created_runtime()->Increment();
216 #ifdef DEBUG
217         for (int i = 0; i < elements->length(); i++) {
218           ASSERT(!elements->get(i)->IsJSObject());
219         }
220 #endif
221       } else {
222         for (int i = 0; i < elements->length(); i++) {
223           Object* value = elements->get(i);
224           ASSERT(value->IsSmi() ||
225                  value->IsTheHole() ||
226                  (copy->GetElementsKind() == FAST_ELEMENTS));
227           if (value->IsJSObject()) {
228             JSObject* js_object = JSObject::cast(value);
229             { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
230                                                               js_object);
231               if (!maybe_result->ToObject(&result)) return maybe_result;
232             }
233             elements->set(i, result);
234           }
235         }
236       }
237       break;
238     }
239     case DICTIONARY_ELEMENTS: {
240       SeededNumberDictionary* element_dictionary = copy->element_dictionary();
241       int capacity = element_dictionary->Capacity();
242       for (int i = 0; i < capacity; i++) {
243         Object* k = element_dictionary->KeyAt(i);
244         if (element_dictionary->IsKey(k)) {
245           Object* value = element_dictionary->ValueAt(i);
246           if (value->IsJSObject()) {
247             JSObject* js_object = JSObject::cast(value);
248             { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
249                                                               js_object);
250               if (!maybe_result->ToObject(&result)) return maybe_result;
251             }
252             element_dictionary->ValueAtPut(i, result);
253           }
254         }
255       }
256       break;
257     }
258     case NON_STRICT_ARGUMENTS_ELEMENTS:
259       UNIMPLEMENTED();
260       break;
261     case EXTERNAL_PIXEL_ELEMENTS:
262     case EXTERNAL_BYTE_ELEMENTS:
263     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
264     case EXTERNAL_SHORT_ELEMENTS:
265     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
266     case EXTERNAL_INT_ELEMENTS:
267     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
268     case EXTERNAL_FLOAT_ELEMENTS:
269     case EXTERNAL_DOUBLE_ELEMENTS:
270     case FAST_DOUBLE_ELEMENTS:
271       // No contained objects, nothing to do.
272       break;
273   }
274   return copy;
275 }
276 
277 
ComputeObjectLiteralMap(Handle<Context> context,Handle<FixedArray> constant_properties,bool * is_result_from_cache)278 static Handle<Map> ComputeObjectLiteralMap(
279     Handle<Context> context,
280     Handle<FixedArray> constant_properties,
281     bool* is_result_from_cache) {
282   Isolate* isolate = context->GetIsolate();
283   int properties_length = constant_properties->length();
284   int number_of_properties = properties_length / 2;
285   // Check that there are only symbols and array indices among keys.
286   int number_of_symbol_keys = 0;
287   for (int p = 0; p != properties_length; p += 2) {
288     Object* key = constant_properties->get(p);
289     uint32_t element_index = 0;
290     if (key->IsSymbol()) {
291       number_of_symbol_keys++;
292     } else if (key->ToArrayIndex(&element_index)) {
293       // An index key does not require space in the property backing store.
294       number_of_properties--;
295     } else {
296       // Bail out as a non-symbol non-index key makes caching impossible.
297       // ASSERT to make sure that the if condition after the loop is false.
298       ASSERT(number_of_symbol_keys != number_of_properties);
299       break;
300     }
301   }
302   // If we only have symbols and array indices among keys then we can
303   // use the map cache in the global context.
304   const int kMaxKeys = 10;
305   if ((number_of_symbol_keys == number_of_properties) &&
306       (number_of_symbol_keys < kMaxKeys)) {
307     // Create the fixed array with the key.
308     Handle<FixedArray> keys =
309         isolate->factory()->NewFixedArray(number_of_symbol_keys);
310     if (number_of_symbol_keys > 0) {
311       int index = 0;
312       for (int p = 0; p < properties_length; p += 2) {
313         Object* key = constant_properties->get(p);
314         if (key->IsSymbol()) {
315           keys->set(index++, key);
316         }
317       }
318       ASSERT(index == number_of_symbol_keys);
319     }
320     *is_result_from_cache = true;
321     return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
322   }
323   *is_result_from_cache = false;
324   return isolate->factory()->CopyMap(
325       Handle<Map>(context->object_function()->initial_map()),
326       number_of_properties);
327 }
328 
329 
330 static Handle<Object> CreateLiteralBoilerplate(
331     Isolate* isolate,
332     Handle<FixedArray> literals,
333     Handle<FixedArray> constant_properties);
334 
335 
CreateObjectLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> constant_properties,bool should_have_fast_elements,bool has_function_literal)336 static Handle<Object> CreateObjectLiteralBoilerplate(
337     Isolate* isolate,
338     Handle<FixedArray> literals,
339     Handle<FixedArray> constant_properties,
340     bool should_have_fast_elements,
341     bool has_function_literal) {
342   // Get the global context from the literals array.  This is the
343   // context in which the function was created and we use the object
344   // function from this context to create the object literal.  We do
345   // not use the object function from the current global context
346   // because this might be the object function from another context
347   // which we should not have access to.
348   Handle<Context> context =
349       Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
350 
351   // In case we have function literals, we want the object to be in
352   // slow properties mode for now. We don't go in the map cache because
353   // maps with constant functions can't be shared if the functions are
354   // not the same (which is the common case).
355   bool is_result_from_cache = false;
356   Handle<Map> map = has_function_literal
357       ? Handle<Map>(context->object_function()->initial_map())
358       : ComputeObjectLiteralMap(context,
359                                 constant_properties,
360                                 &is_result_from_cache);
361 
362   Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
363 
364   // Normalize the elements of the boilerplate to save space if needed.
365   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
366 
367   // Add the constant properties to the boilerplate.
368   int length = constant_properties->length();
369   bool should_transform =
370       !is_result_from_cache && boilerplate->HasFastProperties();
371   if (should_transform || has_function_literal) {
372     // Normalize the properties of object to avoid n^2 behavior
373     // when extending the object multiple properties. Indicate the number of
374     // properties to be added.
375     JSObject::NormalizeProperties(
376         boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
377   }
378 
379   for (int index = 0; index < length; index +=2) {
380     Handle<Object> key(constant_properties->get(index+0), isolate);
381     Handle<Object> value(constant_properties->get(index+1), isolate);
382     if (value->IsFixedArray()) {
383       // The value contains the constant_properties of a
384       // simple object or array literal.
385       Handle<FixedArray> array = Handle<FixedArray>::cast(value);
386       value = CreateLiteralBoilerplate(isolate, literals, array);
387       if (value.is_null()) return value;
388     }
389     Handle<Object> result;
390     uint32_t element_index = 0;
391     if (key->IsSymbol()) {
392       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
393         // Array index as string (uint32).
394         result = JSObject::SetOwnElement(
395             boilerplate, element_index, value, kNonStrictMode);
396       } else {
397         Handle<String> name(String::cast(*key));
398         ASSERT(!name->AsArrayIndex(&element_index));
399         result = JSObject::SetLocalPropertyIgnoreAttributes(
400             boilerplate, name, value, NONE);
401       }
402     } else if (key->ToArrayIndex(&element_index)) {
403       // Array index (uint32).
404       result = JSObject::SetOwnElement(
405           boilerplate, element_index, value, kNonStrictMode);
406     } else {
407       // Non-uint32 number.
408       ASSERT(key->IsNumber());
409       double num = key->Number();
410       char arr[100];
411       Vector<char> buffer(arr, ARRAY_SIZE(arr));
412       const char* str = DoubleToCString(num, buffer);
413       Handle<String> name =
414           isolate->factory()->NewStringFromAscii(CStrVector(str));
415       result = JSObject::SetLocalPropertyIgnoreAttributes(
416           boilerplate, name, value, NONE);
417     }
418     // If setting the property on the boilerplate throws an
419     // exception, the exception is converted to an empty handle in
420     // the handle based operations.  In that case, we need to
421     // convert back to an exception.
422     if (result.is_null()) return result;
423   }
424 
425   // Transform to fast properties if necessary. For object literals with
426   // containing function literals we defer this operation until after all
427   // computed properties have been assigned so that we can generate
428   // constant function properties.
429   if (should_transform && !has_function_literal) {
430     JSObject::TransformToFastProperties(
431         boilerplate, boilerplate->map()->unused_property_fields());
432   }
433 
434   return boilerplate;
435 }
436 
437 
TransitionElements(Handle<Object> object,ElementsKind to_kind,Isolate * isolate)438 MaybeObject* TransitionElements(Handle<Object> object,
439                                 ElementsKind to_kind,
440                                 Isolate* isolate) {
441   HandleScope scope(isolate);
442   if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
443   ElementsKind from_kind =
444       Handle<JSObject>::cast(object)->map()->elements_kind();
445   if (Map::IsValidElementsTransition(from_kind, to_kind)) {
446     Handle<Object> result = JSObject::TransitionElementsKind(
447         Handle<JSObject>::cast(object), to_kind);
448     if (result.is_null()) return isolate->ThrowIllegalOperation();
449     return *result;
450   }
451   return isolate->ThrowIllegalOperation();
452 }
453 
454 
455 static const int kSmiOnlyLiteralMinimumLength = 1024;
456 
457 
CreateArrayLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> elements)458 Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
459     Isolate* isolate,
460     Handle<FixedArray> literals,
461     Handle<FixedArray> elements) {
462   // Create the JSArray.
463   Handle<JSFunction> constructor(
464       JSFunction::GlobalContextFromLiterals(*literals)->array_function());
465   Handle<JSArray> object =
466       Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor));
467 
468   ElementsKind constant_elements_kind =
469       static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
470   Handle<FixedArrayBase> constant_elements_values(
471       FixedArrayBase::cast(elements->get(1)));
472 
473   Context* global_context = isolate->context()->global_context();
474   if (constant_elements_kind == FAST_SMI_ONLY_ELEMENTS) {
475     object->set_map(Map::cast(global_context->smi_js_array_map()));
476   } else if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) {
477     object->set_map(Map::cast(global_context->double_js_array_map()));
478   } else {
479     object->set_map(Map::cast(global_context->object_js_array_map()));
480   }
481 
482   Handle<FixedArrayBase> copied_elements_values;
483   if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) {
484     ASSERT(FLAG_smi_only_arrays);
485     copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
486         Handle<FixedDoubleArray>::cast(constant_elements_values));
487   } else {
488     ASSERT(constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
489            constant_elements_kind == FAST_ELEMENTS);
490     const bool is_cow =
491         (constant_elements_values->map() ==
492          isolate->heap()->fixed_cow_array_map());
493     if (is_cow) {
494       copied_elements_values = constant_elements_values;
495 #if DEBUG
496       Handle<FixedArray> fixed_array_values =
497           Handle<FixedArray>::cast(copied_elements_values);
498       for (int i = 0; i < fixed_array_values->length(); i++) {
499         ASSERT(!fixed_array_values->get(i)->IsFixedArray());
500       }
501 #endif
502     } else {
503       Handle<FixedArray> fixed_array_values =
504           Handle<FixedArray>::cast(constant_elements_values);
505       Handle<FixedArray> fixed_array_values_copy =
506           isolate->factory()->CopyFixedArray(fixed_array_values);
507       copied_elements_values = fixed_array_values_copy;
508       for (int i = 0; i < fixed_array_values->length(); i++) {
509         Object* current = fixed_array_values->get(i);
510         if (current->IsFixedArray()) {
511           // The value contains the constant_properties of a
512           // simple object or array literal.
513           Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
514           Handle<Object> result =
515               CreateLiteralBoilerplate(isolate, literals, fa);
516           if (result.is_null()) return result;
517           fixed_array_values_copy->set(i, *result);
518         }
519       }
520     }
521   }
522   object->set_elements(*copied_elements_values);
523   object->set_length(Smi::FromInt(copied_elements_values->length()));
524 
525   //  Ensure that the boilerplate object has FAST_ELEMENTS, unless the flag is
526   //  on or the object is larger than the threshold.
527   if (!FLAG_smi_only_arrays &&
528       constant_elements_values->length() < kSmiOnlyLiteralMinimumLength) {
529     if (object->GetElementsKind() != FAST_ELEMENTS) {
530       CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
531     }
532   }
533 
534   return object;
535 }
536 
537 
CreateLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> array)538 static Handle<Object> CreateLiteralBoilerplate(
539     Isolate* isolate,
540     Handle<FixedArray> literals,
541     Handle<FixedArray> array) {
542   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
543   const bool kHasNoFunctionLiteral = false;
544   switch (CompileTimeValue::GetType(array)) {
545     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
546       return CreateObjectLiteralBoilerplate(isolate,
547                                             literals,
548                                             elements,
549                                             true,
550                                             kHasNoFunctionLiteral);
551     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
552       return CreateObjectLiteralBoilerplate(isolate,
553                                             literals,
554                                             elements,
555                                             false,
556                                             kHasNoFunctionLiteral);
557     case CompileTimeValue::ARRAY_LITERAL:
558       return Runtime::CreateArrayLiteralBoilerplate(
559           isolate, literals, elements);
560     default:
561       UNREACHABLE();
562       return Handle<Object>::null();
563   }
564 }
565 
566 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateObjectLiteral)567 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
568   HandleScope scope(isolate);
569   ASSERT(args.length() == 4);
570   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
571   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
572   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
573   CONVERT_SMI_ARG_CHECKED(flags, 3);
574   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
575   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
576 
577   // Check if boilerplate exists. If not, create it first.
578   Handle<Object> boilerplate(literals->get(literals_index), isolate);
579   if (*boilerplate == isolate->heap()->undefined_value()) {
580     boilerplate = CreateObjectLiteralBoilerplate(isolate,
581                                                  literals,
582                                                  constant_properties,
583                                                  should_have_fast_elements,
584                                                  has_function_literal);
585     if (boilerplate.is_null()) return Failure::Exception();
586     // Update the functions literal and return the boilerplate.
587     literals->set(literals_index, *boilerplate);
588   }
589   return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
590 }
591 
592 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateObjectLiteralShallow)593 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
594   HandleScope scope(isolate);
595   ASSERT(args.length() == 4);
596   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
597   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
598   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
599   CONVERT_SMI_ARG_CHECKED(flags, 3);
600   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
601   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
602 
603   // Check if boilerplate exists. If not, create it first.
604   Handle<Object> boilerplate(literals->get(literals_index), isolate);
605   if (*boilerplate == isolate->heap()->undefined_value()) {
606     boilerplate = CreateObjectLiteralBoilerplate(isolate,
607                                                  literals,
608                                                  constant_properties,
609                                                  should_have_fast_elements,
610                                                  has_function_literal);
611     if (boilerplate.is_null()) return Failure::Exception();
612     // Update the functions literal and return the boilerplate.
613     literals->set(literals_index, *boilerplate);
614   }
615   return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
616 }
617 
618 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateArrayLiteral)619 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
620   HandleScope scope(isolate);
621   ASSERT(args.length() == 3);
622   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
623   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
624   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
625 
626   // Check if boilerplate exists. If not, create it first.
627   Handle<Object> boilerplate(literals->get(literals_index), isolate);
628   if (*boilerplate == isolate->heap()->undefined_value()) {
629     boilerplate =
630         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
631     if (boilerplate.is_null()) return Failure::Exception();
632     // Update the functions literal and return the boilerplate.
633     literals->set(literals_index, *boilerplate);
634   }
635   return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
636 }
637 
638 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateArrayLiteralShallow)639 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
640   HandleScope scope(isolate);
641   ASSERT(args.length() == 3);
642   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
643   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
644   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
645 
646   // Check if boilerplate exists. If not, create it first.
647   Handle<Object> boilerplate(literals->get(literals_index), isolate);
648   if (*boilerplate == isolate->heap()->undefined_value()) {
649     ASSERT(*elements != isolate->heap()->empty_fixed_array());
650     boilerplate =
651         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
652     if (boilerplate.is_null()) return Failure::Exception();
653     // Update the functions literal and return the boilerplate.
654     literals->set(literals_index, *boilerplate);
655   }
656   if (JSObject::cast(*boilerplate)->elements()->map() ==
657       isolate->heap()->fixed_cow_array_map()) {
658     isolate->counters()->cow_arrays_created_runtime()->Increment();
659   }
660   return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
661 }
662 
663 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateJSProxy)664 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
665   ASSERT(args.length() == 2);
666   Object* handler = args[0];
667   Object* prototype = args[1];
668   Object* used_prototype =
669       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
670   return isolate->heap()->AllocateJSProxy(handler, used_prototype);
671 }
672 
673 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateJSFunctionProxy)674 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
675   ASSERT(args.length() == 4);
676   Object* handler = args[0];
677   Object* call_trap = args[1];
678   Object* construct_trap = args[2];
679   Object* prototype = args[3];
680   Object* used_prototype =
681       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
682   return isolate->heap()->AllocateJSFunctionProxy(
683       handler, call_trap, construct_trap, used_prototype);
684 }
685 
686 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsJSProxy)687 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
688   ASSERT(args.length() == 1);
689   Object* obj = args[0];
690   return isolate->heap()->ToBoolean(obj->IsJSProxy());
691 }
692 
693 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsJSFunctionProxy)694 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
695   ASSERT(args.length() == 1);
696   Object* obj = args[0];
697   return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
698 }
699 
700 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetHandler)701 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
702   ASSERT(args.length() == 1);
703   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
704   return proxy->handler();
705 }
706 
707 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetCallTrap)708 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
709   ASSERT(args.length() == 1);
710   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
711   return proxy->call_trap();
712 }
713 
714 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetConstructTrap)715 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
716   ASSERT(args.length() == 1);
717   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
718   return proxy->construct_trap();
719 }
720 
721 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Fix)722 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
723   ASSERT(args.length() == 1);
724   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
725   proxy->Fix();
726   return isolate->heap()->undefined_value();
727 }
728 
729 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetInitialize)730 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
731   HandleScope scope(isolate);
732   ASSERT(args.length() == 1);
733   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
734   Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
735   holder->set_table(*table);
736   return *holder;
737 }
738 
739 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetAdd)740 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
741   HandleScope scope(isolate);
742   ASSERT(args.length() == 2);
743   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
744   Handle<Object> key(args[1]);
745   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
746   table = ObjectHashSetAdd(table, key);
747   holder->set_table(*table);
748   return isolate->heap()->undefined_symbol();
749 }
750 
751 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetHas)752 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
753   HandleScope scope(isolate);
754   ASSERT(args.length() == 2);
755   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
756   Handle<Object> key(args[1]);
757   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
758   return isolate->heap()->ToBoolean(table->Contains(*key));
759 }
760 
761 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDelete)762 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
763   HandleScope scope(isolate);
764   ASSERT(args.length() == 2);
765   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
766   Handle<Object> key(args[1]);
767   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
768   table = ObjectHashSetRemove(table, key);
769   holder->set_table(*table);
770   return isolate->heap()->undefined_symbol();
771 }
772 
773 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapInitialize)774 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
775   HandleScope scope(isolate);
776   ASSERT(args.length() == 1);
777   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
778   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
779   holder->set_table(*table);
780   return *holder;
781 }
782 
783 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapGet)784 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
785   HandleScope scope(isolate);
786   ASSERT(args.length() == 2);
787   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
788   Handle<Object> key(args[1]);
789   return ObjectHashTable::cast(holder->table())->Lookup(*key);
790 }
791 
792 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MapSet)793 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
794   HandleScope scope(isolate);
795   ASSERT(args.length() == 3);
796   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
797   Handle<Object> key(args[1]);
798   Handle<Object> value(args[2]);
799   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
800   Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
801   holder->set_table(*new_table);
802   return *value;
803 }
804 
805 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakMapInitialize)806 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
807   HandleScope scope(isolate);
808   ASSERT(args.length() == 1);
809   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
810   ASSERT(weakmap->map()->inobject_properties() == 0);
811   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
812   weakmap->set_table(*table);
813   weakmap->set_next(Smi::FromInt(0));
814   return *weakmap;
815 }
816 
817 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakMapGet)818 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
819   NoHandleAllocation ha;
820   ASSERT(args.length() == 2);
821   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
822   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
823   return ObjectHashTable::cast(weakmap->table())->Lookup(*key);
824 }
825 
826 
RUNTIME_FUNCTION(MaybeObject *,Runtime_WeakMapSet)827 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
828   HandleScope scope(isolate);
829   ASSERT(args.length() == 3);
830   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
831   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
832   Handle<Object> value(args[2]);
833   Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
834   Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
835   weakmap->set_table(*new_table);
836   return *value;
837 }
838 
839 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClassOf)840 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
841   NoHandleAllocation ha;
842   ASSERT(args.length() == 1);
843   Object* obj = args[0];
844   if (!obj->IsJSObject()) return isolate->heap()->null_value();
845   return JSObject::cast(obj)->class_name();
846 }
847 
848 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPrototype)849 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
850   NoHandleAllocation ha;
851   ASSERT(args.length() == 1);
852   CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
853   Object* obj = input_obj;
854   // We don't expect access checks to be needed on JSProxy objects.
855   ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
856   do {
857     if (obj->IsAccessCheckNeeded() &&
858         !isolate->MayNamedAccess(JSObject::cast(obj),
859                                  isolate->heap()->Proto_symbol(),
860                                  v8::ACCESS_GET)) {
861       isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
862       return isolate->heap()->undefined_value();
863     }
864     obj = obj->GetPrototype();
865   } while (obj->IsJSObject() &&
866            JSObject::cast(obj)->map()->is_hidden_prototype());
867   return obj;
868 }
869 
870 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsInPrototypeChain)871 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
872   NoHandleAllocation ha;
873   ASSERT(args.length() == 2);
874   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
875   Object* O = args[0];
876   Object* V = args[1];
877   while (true) {
878     Object* prototype = V->GetPrototype();
879     if (prototype->IsNull()) return isolate->heap()->false_value();
880     if (O == prototype) return isolate->heap()->true_value();
881     V = prototype;
882   }
883 }
884 
885 
886 // Recursively traverses hidden prototypes if property is not found
GetOwnPropertyImplementation(JSObject * obj,String * name,LookupResult * result)887 static void GetOwnPropertyImplementation(JSObject* obj,
888                                          String* name,
889                                          LookupResult* result) {
890   obj->LocalLookupRealNamedProperty(name, result);
891 
892   if (!result->IsProperty()) {
893     Object* proto = obj->GetPrototype();
894     if (proto->IsJSObject() &&
895       JSObject::cast(proto)->map()->is_hidden_prototype())
896       GetOwnPropertyImplementation(JSObject::cast(proto),
897                                    name, result);
898   }
899 }
900 
901 
CheckAccessException(LookupResult * result,v8::AccessType access_type)902 static bool CheckAccessException(LookupResult* result,
903                                  v8::AccessType access_type) {
904   if (result->type() == CALLBACKS) {
905     Object* callback = result->GetCallbackObject();
906     if (callback->IsAccessorInfo()) {
907       AccessorInfo* info = AccessorInfo::cast(callback);
908       bool can_access =
909           (access_type == v8::ACCESS_HAS &&
910               (info->all_can_read() || info->all_can_write())) ||
911           (access_type == v8::ACCESS_GET && info->all_can_read()) ||
912           (access_type == v8::ACCESS_SET && info->all_can_write());
913       return can_access;
914     }
915   }
916 
917   return false;
918 }
919 
920 
CheckAccess(JSObject * obj,String * name,LookupResult * result,v8::AccessType access_type)921 static bool CheckAccess(JSObject* obj,
922                         String* name,
923                         LookupResult* result,
924                         v8::AccessType access_type) {
925   ASSERT(result->IsProperty());
926 
927   JSObject* holder = result->holder();
928   JSObject* current = obj;
929   Isolate* isolate = obj->GetIsolate();
930   while (true) {
931     if (current->IsAccessCheckNeeded() &&
932         !isolate->MayNamedAccess(current, name, access_type)) {
933       // Access check callback denied the access, but some properties
934       // can have a special permissions which override callbacks descision
935       // (currently see v8::AccessControl).
936       break;
937     }
938 
939     if (current == holder) {
940       return true;
941     }
942 
943     current = JSObject::cast(current->GetPrototype());
944   }
945 
946   // API callbacks can have per callback access exceptions.
947   switch (result->type()) {
948     case CALLBACKS: {
949       if (CheckAccessException(result, access_type)) {
950         return true;
951       }
952       break;
953     }
954     case INTERCEPTOR: {
955       // If the object has an interceptor, try real named properties.
956       // Overwrite the result to fetch the correct property later.
957       holder->LookupRealNamedProperty(name, result);
958       if (result->IsProperty()) {
959         if (CheckAccessException(result, access_type)) {
960           return true;
961         }
962       }
963       break;
964     }
965     default:
966       break;
967   }
968 
969   isolate->ReportFailedAccessCheck(current, access_type);
970   return false;
971 }
972 
973 
974 // TODO(1095): we should traverse hidden prototype hierachy as well.
CheckElementAccess(JSObject * obj,uint32_t index,v8::AccessType access_type)975 static bool CheckElementAccess(JSObject* obj,
976                                uint32_t index,
977                                v8::AccessType access_type) {
978   if (obj->IsAccessCheckNeeded() &&
979       !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
980     return false;
981   }
982 
983   return true;
984 }
985 
986 
987 // Enumerator used as indices into the array returned from GetOwnProperty
988 enum PropertyDescriptorIndices {
989   IS_ACCESSOR_INDEX,
990   VALUE_INDEX,
991   GETTER_INDEX,
992   SETTER_INDEX,
993   WRITABLE_INDEX,
994   ENUMERABLE_INDEX,
995   CONFIGURABLE_INDEX,
996   DESCRIPTOR_SIZE
997 };
998 
999 
GetOwnProperty(Isolate * isolate,Handle<JSObject> obj,Handle<String> name)1000 static MaybeObject* GetOwnProperty(Isolate* isolate,
1001                                    Handle<JSObject> obj,
1002                                    Handle<String> name) {
1003   Heap* heap = isolate->heap();
1004   Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1005   Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
1006   LookupResult result(isolate);
1007   // This could be an element.
1008   uint32_t index;
1009   if (name->AsArrayIndex(&index)) {
1010     switch (obj->HasLocalElement(index)) {
1011       case JSObject::UNDEFINED_ELEMENT:
1012         return heap->undefined_value();
1013 
1014       case JSObject::STRING_CHARACTER_ELEMENT: {
1015         // Special handling of string objects according to ECMAScript 5
1016         // 15.5.5.2. Note that this might be a string object with elements
1017         // other than the actual string value. This is covered by the
1018         // subsequent cases.
1019         Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
1020         Handle<String> str(String::cast(js_value->value()));
1021         Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
1022 
1023         elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1024         elms->set(VALUE_INDEX, *substr);
1025         elms->set(WRITABLE_INDEX, heap->false_value());
1026         elms->set(ENUMERABLE_INDEX,  heap->true_value());
1027         elms->set(CONFIGURABLE_INDEX, heap->false_value());
1028         return *desc;
1029       }
1030 
1031       case JSObject::INTERCEPTED_ELEMENT:
1032       case JSObject::FAST_ELEMENT: {
1033         elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1034         Handle<Object> value = Object::GetElement(obj, index);
1035         RETURN_IF_EMPTY_HANDLE(isolate, value);
1036         elms->set(VALUE_INDEX, *value);
1037         elms->set(WRITABLE_INDEX, heap->true_value());
1038         elms->set(ENUMERABLE_INDEX,  heap->true_value());
1039         elms->set(CONFIGURABLE_INDEX, heap->true_value());
1040         return *desc;
1041       }
1042 
1043       case JSObject::DICTIONARY_ELEMENT: {
1044         Handle<JSObject> holder = obj;
1045         if (obj->IsJSGlobalProxy()) {
1046           Object* proto = obj->GetPrototype();
1047           if (proto->IsNull()) return heap->undefined_value();
1048           ASSERT(proto->IsJSGlobalObject());
1049           holder = Handle<JSObject>(JSObject::cast(proto));
1050         }
1051         FixedArray* elements = FixedArray::cast(holder->elements());
1052         SeededNumberDictionary* dictionary = NULL;
1053         if (elements->map() == heap->non_strict_arguments_elements_map()) {
1054           dictionary = SeededNumberDictionary::cast(elements->get(1));
1055         } else {
1056           dictionary = SeededNumberDictionary::cast(elements);
1057         }
1058         int entry = dictionary->FindEntry(index);
1059         ASSERT(entry != SeededNumberDictionary::kNotFound);
1060         PropertyDetails details = dictionary->DetailsAt(entry);
1061         switch (details.type()) {
1062           case CALLBACKS: {
1063             // This is an accessor property with getter and/or setter.
1064             AccessorPair* accessors =
1065                 AccessorPair::cast(dictionary->ValueAt(entry));
1066             elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1067             if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
1068               elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1069             }
1070             if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
1071               elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1072             }
1073             break;
1074           }
1075           case NORMAL: {
1076             // This is a data property.
1077             elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1078             Handle<Object> value = Object::GetElement(obj, index);
1079             ASSERT(!value.is_null());
1080             elms->set(VALUE_INDEX, *value);
1081             elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
1082             break;
1083           }
1084           default:
1085             UNREACHABLE();
1086             break;
1087         }
1088         elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
1089         elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
1090         return *desc;
1091       }
1092     }
1093   }
1094 
1095   // Use recursive implementation to also traverse hidden prototypes
1096   GetOwnPropertyImplementation(*obj, *name, &result);
1097 
1098   if (!result.IsProperty()) {
1099     return heap->undefined_value();
1100   }
1101 
1102   if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
1103     return heap->false_value();
1104   }
1105 
1106   elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
1107   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
1108 
1109   bool is_js_accessor = (result.type() == CALLBACKS) &&
1110                         (result.GetCallbackObject()->IsAccessorPair());
1111 
1112   if (is_js_accessor) {
1113     // __defineGetter__/__defineSetter__ callback.
1114     elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1115 
1116     AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
1117     if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
1118       elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1119     }
1120     if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
1121       elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1122     }
1123   } else {
1124     elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1125     elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
1126 
1127     PropertyAttributes attrs;
1128     Object* value;
1129     // GetProperty will check access and report any violations.
1130     { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
1131       if (!maybe_value->ToObject(&value)) return maybe_value;
1132     }
1133     elms->set(VALUE_INDEX, value);
1134   }
1135 
1136   return *desc;
1137 }
1138 
1139 
1140 // Returns an array with the property description:
1141 //  if args[1] is not a property on args[0]
1142 //          returns undefined
1143 //  if args[1] is a data property on args[0]
1144 //         [false, value, Writeable, Enumerable, Configurable]
1145 //  if args[1] is an accessor on args[0]
1146 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetOwnProperty)1147 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1148   ASSERT(args.length() == 2);
1149   HandleScope scope(isolate);
1150   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1151   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
1152   return GetOwnProperty(isolate, obj, name);
1153 }
1154 
1155 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PreventExtensions)1156 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1157   ASSERT(args.length() == 1);
1158   CONVERT_ARG_CHECKED(JSObject, obj, 0);
1159   return obj->PreventExtensions();
1160 }
1161 
1162 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsExtensible)1163 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1164   ASSERT(args.length() == 1);
1165   CONVERT_ARG_CHECKED(JSObject, obj, 0);
1166   if (obj->IsJSGlobalProxy()) {
1167     Object* proto = obj->GetPrototype();
1168     if (proto->IsNull()) return isolate->heap()->false_value();
1169     ASSERT(proto->IsJSGlobalObject());
1170     obj = JSObject::cast(proto);
1171   }
1172   return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1173 }
1174 
1175 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpCompile)1176 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1177   HandleScope scope(isolate);
1178   ASSERT(args.length() == 3);
1179   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
1180   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1181   CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
1182   Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
1183   if (result.is_null()) return Failure::Exception();
1184   return *result;
1185 }
1186 
1187 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateApiFunction)1188 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1189   HandleScope scope(isolate);
1190   ASSERT(args.length() == 1);
1191   CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
1192   return *isolate->factory()->CreateApiFunction(data);
1193 }
1194 
1195 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsTemplate)1196 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1197   ASSERT(args.length() == 1);
1198   Object* arg = args[0];
1199   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1200   return isolate->heap()->ToBoolean(result);
1201 }
1202 
1203 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetTemplateField)1204 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1205   ASSERT(args.length() == 2);
1206   CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1207   CONVERT_SMI_ARG_CHECKED(index, 1)
1208   int offset = index * kPointerSize + HeapObject::kHeaderSize;
1209   InstanceType type = templ->map()->instance_type();
1210   RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
1211                  type ==  OBJECT_TEMPLATE_INFO_TYPE);
1212   RUNTIME_ASSERT(offset > 0);
1213   if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1214     RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1215   } else {
1216     RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1217   }
1218   return *HeapObject::RawField(templ, offset);
1219 }
1220 
1221 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DisableAccessChecks)1222 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1223   ASSERT(args.length() == 1);
1224   CONVERT_ARG_CHECKED(HeapObject, object, 0);
1225   Map* old_map = object->map();
1226   bool needs_access_checks = old_map->is_access_check_needed();
1227   if (needs_access_checks) {
1228     // Copy map so it won't interfere constructor's initial map.
1229     Object* new_map;
1230     { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
1231       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1232     }
1233 
1234     Map::cast(new_map)->set_is_access_check_needed(false);
1235     object->set_map(Map::cast(new_map));
1236   }
1237   return isolate->heap()->ToBoolean(needs_access_checks);
1238 }
1239 
1240 
RUNTIME_FUNCTION(MaybeObject *,Runtime_EnableAccessChecks)1241 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1242   ASSERT(args.length() == 1);
1243   CONVERT_ARG_CHECKED(HeapObject, object, 0);
1244   Map* old_map = object->map();
1245   if (!old_map->is_access_check_needed()) {
1246     // Copy map so it won't interfere constructor's initial map.
1247     Object* new_map;
1248     { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
1249       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1250     }
1251 
1252     Map::cast(new_map)->set_is_access_check_needed(true);
1253     object->set_map(Map::cast(new_map));
1254   }
1255   return isolate->heap()->undefined_value();
1256 }
1257 
1258 
ThrowRedeclarationError(Isolate * isolate,const char * type,Handle<String> name)1259 static Failure* ThrowRedeclarationError(Isolate* isolate,
1260                                         const char* type,
1261                                         Handle<String> name) {
1262   HandleScope scope(isolate);
1263   Handle<Object> type_handle =
1264       isolate->factory()->NewStringFromAscii(CStrVector(type));
1265   Handle<Object> args[2] = { type_handle, name };
1266   Handle<Object> error =
1267       isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1268   return isolate->Throw(*error);
1269 }
1270 
1271 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeclareGlobals)1272 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1273   ASSERT(args.length() == 3);
1274   HandleScope scope(isolate);
1275   Handle<GlobalObject> global = Handle<GlobalObject>(
1276       isolate->context()->global());
1277 
1278   Handle<Context> context = args.at<Context>(0);
1279   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
1280   CONVERT_SMI_ARG_CHECKED(flags, 2);
1281 
1282   // Traverse the name/value pairs and set the properties.
1283   int length = pairs->length();
1284   for (int i = 0; i < length; i += 2) {
1285     HandleScope scope(isolate);
1286     Handle<String> name(String::cast(pairs->get(i)));
1287     Handle<Object> value(pairs->get(i + 1), isolate);
1288 
1289     // We have to declare a global const property. To capture we only
1290     // assign to it when evaluating the assignment for "const x =
1291     // <expr>" the initial value is the hole.
1292     bool is_const_property = value->IsTheHole();
1293     bool is_function_declaration = false;
1294     if (value->IsUndefined() || is_const_property) {
1295       // Lookup the property in the global object, and don't set the
1296       // value of the variable if the property is already there.
1297       LookupResult lookup(isolate);
1298       global->Lookup(*name, &lookup);
1299       if (lookup.IsProperty()) {
1300         // We found an existing property. Unless it was an interceptor
1301         // that claims the property is absent, skip this declaration.
1302         if (lookup.type() != INTERCEPTOR) {
1303           continue;
1304         }
1305         PropertyAttributes attributes = global->GetPropertyAttribute(*name);
1306         if (attributes != ABSENT) {
1307           continue;
1308         }
1309         // Fall-through and introduce the absent property by using
1310         // SetProperty.
1311       }
1312     } else {
1313       is_function_declaration = true;
1314       // Copy the function and update its context. Use it as value.
1315       Handle<SharedFunctionInfo> shared =
1316           Handle<SharedFunctionInfo>::cast(value);
1317       Handle<JSFunction> function =
1318           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
1319                                                                 context,
1320                                                                 TENURED);
1321       value = function;
1322     }
1323 
1324     LookupResult lookup(isolate);
1325     global->LocalLookup(*name, &lookup);
1326 
1327     // Compute the property attributes. According to ECMA-262, section
1328     // 13, page 71, the property must be read-only and
1329     // non-deletable. However, neither SpiderMonkey nor KJS creates the
1330     // property as read-only, so we don't either.
1331     int attr = NONE;
1332     if (!DeclareGlobalsEvalFlag::decode(flags)) {
1333       attr |= DONT_DELETE;
1334     }
1335     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
1336     if (is_const_property || (is_native && is_function_declaration)) {
1337       attr |= READ_ONLY;
1338     }
1339 
1340     LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
1341 
1342     // Safari does not allow the invocation of callback setters for
1343     // function declarations. To mimic this behavior, we do not allow
1344     // the invocation of setters for function values. This makes a
1345     // difference for global functions with the same names as event
1346     // handlers such as "function onload() {}". Firefox does call the
1347     // onload setter in those case and Safari does not. We follow
1348     // Safari for compatibility.
1349     if (is_function_declaration) {
1350       if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
1351         // Do not overwrite READ_ONLY properties.
1352         if (lookup.GetAttributes() & READ_ONLY) {
1353           if (language_mode != CLASSIC_MODE) {
1354             Handle<Object> args[] = { name };
1355             return isolate->Throw(*isolate->factory()->NewTypeError(
1356                 "strict_cannot_assign", HandleVector(args, ARRAY_SIZE(args))));
1357           }
1358           continue;
1359         }
1360         // Do not change DONT_DELETE to false from true.
1361         attr |= lookup.GetAttributes() & DONT_DELETE;
1362       }
1363       PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
1364 
1365       RETURN_IF_EMPTY_HANDLE(
1366           isolate,
1367           JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
1368                                                      attributes));
1369     } else {
1370       RETURN_IF_EMPTY_HANDLE(
1371           isolate,
1372           JSReceiver::SetProperty(global, name, value,
1373                                   static_cast<PropertyAttributes>(attr),
1374                                   language_mode == CLASSIC_MODE
1375                                       ? kNonStrictMode : kStrictMode));
1376     }
1377   }
1378 
1379   ASSERT(!isolate->has_pending_exception());
1380   return isolate->heap()->undefined_value();
1381 }
1382 
1383 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeclareContextSlot)1384 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1385   HandleScope scope(isolate);
1386   ASSERT(args.length() == 4);
1387 
1388   // Declarations are always made in a function or global context.  In the
1389   // case of eval code, the context passed is the context of the caller,
1390   // which may be some nested context and not the declaration context.
1391   RUNTIME_ASSERT(args[0]->IsContext());
1392   Handle<Context> context(Context::cast(args[0])->declaration_context());
1393 
1394   Handle<String> name(String::cast(args[1]));
1395   PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
1396   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1397   Handle<Object> initial_value(args[3], isolate);
1398 
1399   int index;
1400   PropertyAttributes attributes;
1401   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
1402   BindingFlags binding_flags;
1403   Handle<Object> holder =
1404       context->Lookup(name, flags, &index, &attributes, &binding_flags);
1405 
1406   if (attributes != ABSENT) {
1407     // The name was declared before; check for conflicting re-declarations.
1408     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1409       // Functions are not read-only.
1410       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1411       const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1412       return ThrowRedeclarationError(isolate, type, name);
1413     }
1414 
1415     // Initialize it if necessary.
1416     if (*initial_value != NULL) {
1417       if (index >= 0) {
1418         ASSERT(holder.is_identical_to(context));
1419         if (((attributes & READ_ONLY) == 0) ||
1420             context->get(index)->IsTheHole()) {
1421           context->set(index, *initial_value);
1422         }
1423       } else {
1424         // Slow case: The property is in the context extension object of a
1425         // function context or the global object of a global context.
1426         Handle<JSObject> object = Handle<JSObject>::cast(holder);
1427         RETURN_IF_EMPTY_HANDLE(
1428             isolate,
1429             JSReceiver::SetProperty(object, name, initial_value, mode,
1430                                     kNonStrictMode));
1431       }
1432     }
1433 
1434   } else {
1435     // The property is not in the function context. It needs to be
1436     // "declared" in the function context's extension context or as a
1437     // property of the the global object.
1438     Handle<JSObject> object;
1439     if (context->has_extension()) {
1440       object = Handle<JSObject>(JSObject::cast(context->extension()));
1441     } else {
1442       // Context extension objects are allocated lazily.
1443       ASSERT(context->IsFunctionContext());
1444       object = isolate->factory()->NewJSObject(
1445           isolate->context_extension_function());
1446       context->set_extension(*object);
1447     }
1448     ASSERT(*object != NULL);
1449 
1450     // Declare the property by setting it to the initial value if provided,
1451     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
1452     // constant declarations).
1453     ASSERT(!object->HasLocalProperty(*name));
1454     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
1455     if (*initial_value != NULL) value = initial_value;
1456     // Declaring a const context slot is a conflicting declaration if
1457     // there is a callback with that name in a prototype. It is
1458     // allowed to introduce const variables in
1459     // JSContextExtensionObjects. They are treated specially in
1460     // SetProperty and no setters are invoked for those since they are
1461     // not real JSObjects.
1462     if (initial_value->IsTheHole() &&
1463         !object->IsJSContextExtensionObject()) {
1464       LookupResult lookup(isolate);
1465       object->Lookup(*name, &lookup);
1466       if (lookup.IsFound() && (lookup.type() == CALLBACKS)) {
1467         return ThrowRedeclarationError(isolate, "const", name);
1468       }
1469     }
1470     RETURN_IF_EMPTY_HANDLE(
1471         isolate,
1472         JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
1473   }
1474 
1475   return isolate->heap()->undefined_value();
1476 }
1477 
1478 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeVarGlobal)1479 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
1480   NoHandleAllocation nha;
1481   // args[0] == name
1482   // args[1] == language_mode
1483   // args[2] == value (optional)
1484 
1485   // Determine if we need to assign to the variable if it already
1486   // exists (based on the number of arguments).
1487   RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
1488   bool assign = args.length() == 3;
1489 
1490   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1491   GlobalObject* global = isolate->context()->global();
1492   RUNTIME_ASSERT(args[1]->IsSmi());
1493   CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
1494   StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
1495       ? kNonStrictMode : kStrictMode;
1496 
1497   // According to ECMA-262, section 12.2, page 62, the property must
1498   // not be deletable.
1499   PropertyAttributes attributes = DONT_DELETE;
1500 
1501   // Lookup the property locally in the global object. If it isn't
1502   // there, there is a property with this name in the prototype chain.
1503   // We follow Safari and Firefox behavior and only set the property
1504   // locally if there is an explicit initialization value that we have
1505   // to assign to the property.
1506   // Note that objects can have hidden prototypes, so we need to traverse
1507   // the whole chain of hidden prototypes to do a 'local' lookup.
1508   Object* object = global;
1509   LookupResult lookup(isolate);
1510   while (object->IsJSObject() &&
1511          JSObject::cast(object)->map()->is_hidden_prototype()) {
1512     JSObject* raw_holder = JSObject::cast(object);
1513     raw_holder->LocalLookup(*name, &lookup);
1514     if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
1515       HandleScope handle_scope(isolate);
1516       Handle<JSObject> holder(raw_holder);
1517       PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
1518       // Update the raw pointer in case it's changed due to GC.
1519       raw_holder = *holder;
1520       if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1521         // Found an interceptor that's not read only.
1522         if (assign) {
1523           return raw_holder->SetProperty(
1524               &lookup, *name, args[2], attributes, strict_mode_flag);
1525         } else {
1526           return isolate->heap()->undefined_value();
1527         }
1528       }
1529     }
1530     object = raw_holder->GetPrototype();
1531   }
1532 
1533   // Reload global in case the loop above performed a GC.
1534   global = isolate->context()->global();
1535   if (assign) {
1536     return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
1537   }
1538   return isolate->heap()->undefined_value();
1539 }
1540 
1541 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeConstGlobal)1542 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
1543   // All constants are declared with an initial value. The name
1544   // of the constant is the first argument and the initial value
1545   // is the second.
1546   RUNTIME_ASSERT(args.length() == 2);
1547   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1548   Handle<Object> value = args.at<Object>(1);
1549 
1550   // Get the current global object from top.
1551   GlobalObject* global = isolate->context()->global();
1552 
1553   // According to ECMA-262, section 12.2, page 62, the property must
1554   // not be deletable. Since it's a const, it must be READ_ONLY too.
1555   PropertyAttributes attributes =
1556       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1557 
1558   // Lookup the property locally in the global object. If it isn't
1559   // there, we add the property and take special precautions to always
1560   // add it as a local property even in case of callbacks in the
1561   // prototype chain (this rules out using SetProperty).
1562   // We use SetLocalPropertyIgnoreAttributes instead
1563   LookupResult lookup(isolate);
1564   global->LocalLookup(*name, &lookup);
1565   if (!lookup.IsProperty()) {
1566     return global->SetLocalPropertyIgnoreAttributes(*name,
1567                                                     *value,
1568                                                     attributes);
1569   }
1570 
1571   if (!lookup.IsReadOnly()) {
1572     // Restore global object from context (in case of GC) and continue
1573     // with setting the value.
1574     HandleScope handle_scope(isolate);
1575     Handle<GlobalObject> global(isolate->context()->global());
1576 
1577     // BUG 1213575: Handle the case where we have to set a read-only
1578     // property through an interceptor and only do it if it's
1579     // uninitialized, e.g. the hole. Nirk...
1580     // Passing non-strict mode because the property is writable.
1581     RETURN_IF_EMPTY_HANDLE(
1582         isolate,
1583         JSReceiver::SetProperty(global, name, value, attributes,
1584                                 kNonStrictMode));
1585     return *value;
1586   }
1587 
1588   // Set the value, but only if we're assigning the initial value to a
1589   // constant. For now, we determine this by checking if the
1590   // current value is the hole.
1591   // Strict mode handling not needed (const is disallowed in strict mode).
1592   PropertyType type = lookup.type();
1593   if (type == FIELD) {
1594     FixedArray* properties = global->properties();
1595     int index = lookup.GetFieldIndex();
1596     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
1597       properties->set(index, *value);
1598     }
1599   } else if (type == NORMAL) {
1600     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
1601         !lookup.IsReadOnly()) {
1602       global->SetNormalizedProperty(&lookup, *value);
1603     }
1604   } else {
1605     // Ignore re-initialization of constants that have already been
1606     // assigned a function value.
1607     ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
1608   }
1609 
1610   // Use the set value as the result of the operation.
1611   return *value;
1612 }
1613 
1614 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeConstContextSlot)1615 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
1616   HandleScope scope(isolate);
1617   ASSERT(args.length() == 3);
1618 
1619   Handle<Object> value(args[0], isolate);
1620   ASSERT(!value->IsTheHole());
1621 
1622   // Initializations are always done in a function or global context.
1623   RUNTIME_ASSERT(args[1]->IsContext());
1624   Handle<Context> context(Context::cast(args[1])->declaration_context());
1625 
1626   Handle<String> name(String::cast(args[2]));
1627 
1628   int index;
1629   PropertyAttributes attributes;
1630   ContextLookupFlags flags = FOLLOW_CHAINS;
1631   BindingFlags binding_flags;
1632   Handle<Object> holder =
1633       context->Lookup(name, flags, &index, &attributes, &binding_flags);
1634 
1635   if (index >= 0) {
1636     ASSERT(holder->IsContext());
1637     // Property was found in a context.  Perform the assignment if we
1638     // found some non-constant or an uninitialized constant.
1639     Handle<Context> context = Handle<Context>::cast(holder);
1640     if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
1641       context->set(index, *value);
1642     }
1643     return *value;
1644   }
1645 
1646   // The property could not be found, we introduce it as a property of the
1647   // global object.
1648   if (attributes == ABSENT) {
1649     Handle<JSObject> global = Handle<JSObject>(
1650         isolate->context()->global());
1651     // Strict mode not needed (const disallowed in strict mode).
1652     RETURN_IF_EMPTY_HANDLE(
1653         isolate,
1654         JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
1655     return *value;
1656   }
1657 
1658   // The property was present in some function's context extension object,
1659   // as a property on the subject of a with, or as a property of the global
1660   // object.
1661   //
1662   // In most situations, eval-introduced consts should still be present in
1663   // the context extension object.  However, because declaration and
1664   // initialization are separate, the property might have been deleted
1665   // before we reach the initialization point.
1666   //
1667   // Example:
1668   //
1669   //    function f() { eval("delete x; const x;"); }
1670   //
1671   // In that case, the initialization behaves like a normal assignment.
1672   Handle<JSObject> object = Handle<JSObject>::cast(holder);
1673 
1674   if (*object == context->extension()) {
1675     // This is the property that was introduced by the const declaration.
1676     // Set it if it hasn't been set before.  NOTE: We cannot use
1677     // GetProperty() to get the current value as it 'unholes' the value.
1678     LookupResult lookup(isolate);
1679     object->LocalLookupRealNamedProperty(*name, &lookup);
1680     ASSERT(lookup.IsFound());  // the property was declared
1681     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
1682 
1683     PropertyType type = lookup.type();
1684     if (type == FIELD) {
1685       FixedArray* properties = object->properties();
1686       int index = lookup.GetFieldIndex();
1687       if (properties->get(index)->IsTheHole()) {
1688         properties->set(index, *value);
1689       }
1690     } else if (type == NORMAL) {
1691       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
1692         object->SetNormalizedProperty(&lookup, *value);
1693       }
1694     } else {
1695       // We should not reach here. Any real, named property should be
1696       // either a field or a dictionary slot.
1697       UNREACHABLE();
1698     }
1699   } else {
1700     // The property was found on some other object.  Set it if it is not a
1701     // read-only property.
1702     if ((attributes & READ_ONLY) == 0) {
1703       // Strict mode not needed (const disallowed in strict mode).
1704       RETURN_IF_EMPTY_HANDLE(
1705           isolate,
1706           JSReceiver::SetProperty(object, name, value, attributes,
1707                                   kNonStrictMode));
1708     }
1709   }
1710 
1711   return *value;
1712 }
1713 
1714 
RUNTIME_FUNCTION(MaybeObject *,Runtime_OptimizeObjectForAddingMultipleProperties)1715 RUNTIME_FUNCTION(MaybeObject*,
1716                  Runtime_OptimizeObjectForAddingMultipleProperties) {
1717   HandleScope scope(isolate);
1718   ASSERT(args.length() == 2);
1719   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1720   CONVERT_SMI_ARG_CHECKED(properties, 1);
1721   if (object->HasFastProperties()) {
1722     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
1723   }
1724   return *object;
1725 }
1726 
1727 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpExec)1728 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
1729   HandleScope scope(isolate);
1730   ASSERT(args.length() == 4);
1731   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
1732   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
1733   // Due to the way the JS calls are constructed this must be less than the
1734   // length of a string, i.e. it is always a Smi.  We check anyway for security.
1735   CONVERT_SMI_ARG_CHECKED(index, 2);
1736   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
1737   RUNTIME_ASSERT(last_match_info->HasFastElements());
1738   RUNTIME_ASSERT(index >= 0);
1739   RUNTIME_ASSERT(index <= subject->length());
1740   isolate->counters()->regexp_entry_runtime()->Increment();
1741   Handle<Object> result = RegExpImpl::Exec(regexp,
1742                                            subject,
1743                                            index,
1744                                            last_match_info);
1745   if (result.is_null()) return Failure::Exception();
1746   return *result;
1747 }
1748 
1749 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpConstructResult)1750 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
1751   ASSERT(args.length() == 3);
1752   CONVERT_SMI_ARG_CHECKED(elements_count, 0);
1753   if (elements_count < 0 ||
1754       elements_count > FixedArray::kMaxLength ||
1755       !Smi::IsValid(elements_count)) {
1756     return isolate->ThrowIllegalOperation();
1757   }
1758   Object* new_object;
1759   { MaybeObject* maybe_new_object =
1760         isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
1761     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1762   }
1763   FixedArray* elements = FixedArray::cast(new_object);
1764   { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
1765       JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
1766     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1767   }
1768   {
1769     AssertNoAllocation no_gc;
1770     HandleScope scope(isolate);
1771     reinterpret_cast<HeapObject*>(new_object)->
1772         set_map(isolate->global_context()->regexp_result_map());
1773   }
1774   JSArray* array = JSArray::cast(new_object);
1775   array->set_properties(isolate->heap()->empty_fixed_array());
1776   array->set_elements(elements);
1777   array->set_length(Smi::FromInt(elements_count));
1778   // Write in-object properties after the length of the array.
1779   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
1780   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
1781   return array;
1782 }
1783 
1784 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpInitializeObject)1785 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
1786   AssertNoAllocation no_alloc;
1787   ASSERT(args.length() == 5);
1788   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1789   CONVERT_ARG_CHECKED(String, source, 1);
1790 
1791   Object* global = args[2];
1792   if (!global->IsTrue()) global = isolate->heap()->false_value();
1793 
1794   Object* ignoreCase = args[3];
1795   if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
1796 
1797   Object* multiline = args[4];
1798   if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
1799 
1800   Map* map = regexp->map();
1801   Object* constructor = map->constructor();
1802   if (constructor->IsJSFunction() &&
1803       JSFunction::cast(constructor)->initial_map() == map) {
1804     // If we still have the original map, set in-object properties directly.
1805     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1806     // Both true and false are immovable immortal objects so no need for write
1807     // barrier.
1808     regexp->InObjectPropertyAtPut(
1809         JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
1810     regexp->InObjectPropertyAtPut(
1811         JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
1812     regexp->InObjectPropertyAtPut(
1813         JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
1814     regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1815                                   Smi::FromInt(0),
1816                                   SKIP_WRITE_BARRIER);  // It's a Smi.
1817     return regexp;
1818   }
1819 
1820   // Map has changed, so use generic, but slower, method.
1821   PropertyAttributes final =
1822       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
1823   PropertyAttributes writable =
1824       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1825   Heap* heap = isolate->heap();
1826   MaybeObject* result;
1827   result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
1828                                                     source,
1829                                                     final);
1830   ASSERT(!result->IsFailure());
1831   result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
1832                                                     global,
1833                                                     final);
1834   ASSERT(!result->IsFailure());
1835   result =
1836       regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
1837                                                ignoreCase,
1838                                                final);
1839   ASSERT(!result->IsFailure());
1840   result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
1841                                                     multiline,
1842                                                     final);
1843   ASSERT(!result->IsFailure());
1844   result =
1845       regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
1846                                                Smi::FromInt(0),
1847                                                writable);
1848   ASSERT(!result->IsFailure());
1849   USE(result);
1850   return regexp;
1851 }
1852 
1853 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FinishArrayPrototypeSetup)1854 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
1855   HandleScope scope(isolate);
1856   ASSERT(args.length() == 1);
1857   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
1858   // This is necessary to enable fast checks for absence of elements
1859   // on Array.prototype and below.
1860   prototype->set_elements(isolate->heap()->empty_fixed_array());
1861   return Smi::FromInt(0);
1862 }
1863 
1864 
InstallBuiltin(Isolate * isolate,Handle<JSObject> holder,const char * name,Builtins::Name builtin_name)1865 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
1866                                          Handle<JSObject> holder,
1867                                          const char* name,
1868                                          Builtins::Name builtin_name) {
1869   Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
1870   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
1871   Handle<JSFunction> optimized =
1872       isolate->factory()->NewFunction(key,
1873                                       JS_OBJECT_TYPE,
1874                                       JSObject::kHeaderSize,
1875                                       code,
1876                                       false);
1877   optimized->shared()->DontAdaptArguments();
1878   JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
1879   return optimized;
1880 }
1881 
1882 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SpecialArrayFunctions)1883 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
1884   HandleScope scope(isolate);
1885   ASSERT(args.length() == 1);
1886   CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
1887 
1888   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
1889   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
1890   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1891   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1892   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1893   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1894   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1895 
1896   return *holder;
1897 }
1898 
1899 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetDefaultReceiver)1900 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
1901   ASSERT(args.length() == 1);
1902   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
1903 
1904   if (!callable->IsJSFunction()) {
1905     HandleScope scope(isolate);
1906     bool threw = false;
1907     Handle<Object> delegate =
1908         Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
1909     if (threw) return Failure::Exception();
1910     callable = JSFunction::cast(*delegate);
1911   }
1912   JSFunction* function = JSFunction::cast(callable);
1913 
1914   SharedFunctionInfo* shared = function->shared();
1915   if (shared->native() || !shared->is_classic_mode()) {
1916     return isolate->heap()->undefined_value();
1917   }
1918   // Returns undefined for strict or native functions, or
1919   // the associated global receiver for "normal" functions.
1920 
1921   Context* global_context =
1922       function->context()->global()->global_context();
1923   return global_context->global()->global_receiver();
1924 }
1925 
1926 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MaterializeRegExpLiteral)1927 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1928   HandleScope scope(isolate);
1929   ASSERT(args.length() == 4);
1930   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
1931   int index = args.smi_at(1);
1932   Handle<String> pattern = args.at<String>(2);
1933   Handle<String> flags = args.at<String>(3);
1934 
1935   // Get the RegExp function from the context in the literals array.
1936   // This is the RegExp function from the context in which the
1937   // function was created.  We do not use the RegExp function from the
1938   // current global context because this might be the RegExp function
1939   // from another context which we should not have access to.
1940   Handle<JSFunction> constructor =
1941       Handle<JSFunction>(
1942           JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
1943   // Compute the regular expression literal.
1944   bool has_pending_exception;
1945   Handle<Object> regexp =
1946       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
1947                                       &has_pending_exception);
1948   if (has_pending_exception) {
1949     ASSERT(isolate->has_pending_exception());
1950     return Failure::Exception();
1951   }
1952   literals->set(index, *regexp);
1953   return *regexp;
1954 }
1955 
1956 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetName)1957 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
1958   NoHandleAllocation ha;
1959   ASSERT(args.length() == 1);
1960 
1961   CONVERT_ARG_CHECKED(JSFunction, f, 0);
1962   return f->shared()->name();
1963 }
1964 
1965 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetName)1966 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
1967   NoHandleAllocation ha;
1968   ASSERT(args.length() == 2);
1969 
1970   CONVERT_ARG_CHECKED(JSFunction, f, 0);
1971   CONVERT_ARG_CHECKED(String, name, 1);
1972   f->shared()->set_name(name);
1973   return isolate->heap()->undefined_value();
1974 }
1975 
1976 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionNameShouldPrintAsAnonymous)1977 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
1978   NoHandleAllocation ha;
1979   ASSERT(args.length() == 1);
1980   CONVERT_ARG_CHECKED(JSFunction, f, 0);
1981   return isolate->heap()->ToBoolean(
1982       f->shared()->name_should_print_as_anonymous());
1983 }
1984 
1985 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionMarkNameShouldPrintAsAnonymous)1986 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
1987   NoHandleAllocation ha;
1988   ASSERT(args.length() == 1);
1989   CONVERT_ARG_CHECKED(JSFunction, f, 0);
1990   f->shared()->set_name_should_print_as_anonymous(true);
1991   return isolate->heap()->undefined_value();
1992 }
1993 
1994 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionRemovePrototype)1995 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
1996   NoHandleAllocation ha;
1997   ASSERT(args.length() == 1);
1998 
1999   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2000   Object* obj = f->RemovePrototype();
2001   if (obj->IsFailure()) return obj;
2002 
2003   return isolate->heap()->undefined_value();
2004 }
2005 
2006 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetScript)2007 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2008   HandleScope scope(isolate);
2009   ASSERT(args.length() == 1);
2010 
2011   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2012   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2013   if (!script->IsScript()) return isolate->heap()->undefined_value();
2014 
2015   return *GetScriptWrapper(Handle<Script>::cast(script));
2016 }
2017 
2018 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetSourceCode)2019 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2020   HandleScope scope(isolate);
2021   ASSERT(args.length() == 1);
2022 
2023   CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2024   Handle<SharedFunctionInfo> shared(f->shared());
2025   return *shared->GetSourceCode();
2026 }
2027 
2028 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetScriptSourcePosition)2029 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2030   NoHandleAllocation ha;
2031   ASSERT(args.length() == 1);
2032 
2033   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2034   int pos = fun->shared()->start_position();
2035   return Smi::FromInt(pos);
2036 }
2037 
2038 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetPositionForOffset)2039 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2040   ASSERT(args.length() == 2);
2041 
2042   CONVERT_ARG_CHECKED(Code, code, 0);
2043   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2044 
2045   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2046 
2047   Address pc = code->address() + offset;
2048   return Smi::FromInt(code->SourcePosition(pc));
2049 }
2050 
2051 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetInstanceClassName)2052 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2053   NoHandleAllocation ha;
2054   ASSERT(args.length() == 2);
2055 
2056   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2057   CONVERT_ARG_CHECKED(String, name, 1);
2058   fun->SetInstanceClassName(name);
2059   return isolate->heap()->undefined_value();
2060 }
2061 
2062 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetLength)2063 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2064   NoHandleAllocation ha;
2065   ASSERT(args.length() == 2);
2066 
2067   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2068   CONVERT_SMI_ARG_CHECKED(length, 1);
2069   fun->shared()->set_length(length);
2070   return isolate->heap()->undefined_value();
2071 }
2072 
2073 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetPrototype)2074 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2075   NoHandleAllocation ha;
2076   ASSERT(args.length() == 2);
2077 
2078   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2079   ASSERT(fun->should_have_prototype());
2080   Object* obj;
2081   { MaybeObject* maybe_obj =
2082         Accessors::FunctionSetPrototype(fun, args[1], NULL);
2083     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2084   }
2085   return args[0];  // return TOS
2086 }
2087 
2088 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetReadOnlyPrototype)2089 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2090   NoHandleAllocation ha;
2091   RUNTIME_ASSERT(args.length() == 1);
2092   CONVERT_ARG_CHECKED(JSFunction, function, 0);
2093 
2094   MaybeObject* maybe_name =
2095       isolate->heap()->AllocateStringFromAscii(CStrVector("prototype"));
2096   String* name;
2097   if (!maybe_name->To(&name)) return maybe_name;
2098 
2099   if (function->HasFastProperties()) {
2100     // Construct a new field descriptor with updated attributes.
2101     DescriptorArray* instance_desc = function->map()->instance_descriptors();
2102     int index = instance_desc->Search(name);
2103     ASSERT(index != DescriptorArray::kNotFound);
2104     PropertyDetails details(instance_desc->GetDetails(index));
2105     CallbacksDescriptor new_desc(name,
2106         instance_desc->GetValue(index),
2107         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2108         details.index());
2109     // Construct a new field descriptors array containing the new descriptor.
2110     Object* descriptors_unchecked;
2111     { MaybeObject* maybe_descriptors_unchecked =
2112         instance_desc->CopyInsert(&new_desc, REMOVE_TRANSITIONS);
2113       if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
2114         return maybe_descriptors_unchecked;
2115       }
2116     }
2117     DescriptorArray* new_descriptors =
2118         DescriptorArray::cast(descriptors_unchecked);
2119     // Create a new map featuring the new field descriptors array.
2120     Object* map_unchecked;
2121     { MaybeObject* maybe_map_unchecked = function->map()->CopyDropDescriptors();
2122       if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
2123         return maybe_map_unchecked;
2124       }
2125     }
2126     Map* new_map = Map::cast(map_unchecked);
2127     new_map->set_instance_descriptors(new_descriptors);
2128     function->set_map(new_map);
2129   } else {  // Dictionary properties.
2130     // Directly manipulate the property details.
2131     int entry = function->property_dictionary()->FindEntry(name);
2132     ASSERT(entry != StringDictionary::kNotFound);
2133     PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2134     PropertyDetails new_details(
2135         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2136         details.type(),
2137         details.index());
2138     function->property_dictionary()->DetailsAtPut(entry, new_details);
2139   }
2140   return function;
2141 }
2142 
2143 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionIsAPIFunction)2144 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2145   NoHandleAllocation ha;
2146   ASSERT(args.length() == 1);
2147 
2148   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2149   return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2150 }
2151 
2152 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionIsBuiltin)2153 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2154   NoHandleAllocation ha;
2155   ASSERT(args.length() == 1);
2156 
2157   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2158   return isolate->heap()->ToBoolean(f->IsBuiltin());
2159 }
2160 
2161 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetCode)2162 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2163   HandleScope scope(isolate);
2164   ASSERT(args.length() == 2);
2165 
2166   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2167   Handle<Object> code = args.at<Object>(1);
2168 
2169   Handle<Context> context(target->context());
2170 
2171   if (!code->IsNull()) {
2172     RUNTIME_ASSERT(code->IsJSFunction());
2173     Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
2174     Handle<SharedFunctionInfo> shared(fun->shared());
2175 
2176     if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
2177       return Failure::Exception();
2178     }
2179     // Since we don't store the source for this we should never
2180     // optimize this.
2181     shared->code()->set_optimizable(false);
2182     // Set the code, scope info, formal parameter count,
2183     // and the length of the target function.
2184     target->shared()->set_code(shared->code());
2185     target->ReplaceCode(shared->code());
2186     target->shared()->set_scope_info(shared->scope_info());
2187     target->shared()->set_length(shared->length());
2188     target->shared()->set_formal_parameter_count(
2189         shared->formal_parameter_count());
2190     // Set the source code of the target function to undefined.
2191     // SetCode is only used for built-in constructors like String,
2192     // Array, and Object, and some web code
2193     // doesn't like seeing source code for constructors.
2194     target->shared()->set_script(isolate->heap()->undefined_value());
2195     target->shared()->code()->set_optimizable(false);
2196     // Clear the optimization hints related to the compiled code as these are no
2197     // longer valid when the code is overwritten.
2198     target->shared()->ClearThisPropertyAssignmentsInfo();
2199     context = Handle<Context>(fun->context());
2200 
2201     // Make sure we get a fresh copy of the literal vector to avoid
2202     // cross context contamination.
2203     int number_of_literals = fun->NumberOfLiterals();
2204     Handle<FixedArray> literals =
2205         isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2206     if (number_of_literals > 0) {
2207       // Insert the object, regexp and array functions in the literals
2208       // array prefix.  These are the functions that will be used when
2209       // creating object, regexp and array literals.
2210       literals->set(JSFunction::kLiteralGlobalContextIndex,
2211                     context->global_context());
2212     }
2213     target->set_literals(*literals);
2214     target->set_next_function_link(isolate->heap()->undefined_value());
2215 
2216     if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) {
2217       isolate->logger()->LogExistingFunction(
2218           shared, Handle<Code>(shared->code()));
2219     }
2220   }
2221 
2222   target->set_context(*context);
2223   return *target;
2224 }
2225 
2226 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetExpectedNumberOfProperties)2227 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2228   HandleScope scope(isolate);
2229   ASSERT(args.length() == 2);
2230   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2231   CONVERT_SMI_ARG_CHECKED(num, 1);
2232   RUNTIME_ASSERT(num >= 0);
2233   SetExpectedNofProperties(function, num);
2234   return isolate->heap()->undefined_value();
2235 }
2236 
2237 
CharFromCode(Isolate * isolate,Object * char_code)2238 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
2239                                                  Object* char_code) {
2240   uint32_t code;
2241   if (char_code->ToArrayIndex(&code)) {
2242     if (code <= 0xffff) {
2243       return isolate->heap()->LookupSingleCharacterStringFromCode(code);
2244     }
2245   }
2246   return isolate->heap()->empty_string();
2247 }
2248 
2249 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringCharCodeAt)2250 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
2251   NoHandleAllocation ha;
2252   ASSERT(args.length() == 2);
2253 
2254   CONVERT_ARG_CHECKED(String, subject, 0);
2255   Object* index = args[1];
2256   RUNTIME_ASSERT(index->IsNumber());
2257 
2258   uint32_t i = 0;
2259   if (index->IsSmi()) {
2260     int value = Smi::cast(index)->value();
2261     if (value < 0) return isolate->heap()->nan_value();
2262     i = value;
2263   } else {
2264     ASSERT(index->IsHeapNumber());
2265     double value = HeapNumber::cast(index)->value();
2266     i = static_cast<uint32_t>(DoubleToInteger(value));
2267   }
2268 
2269   // Flatten the string.  If someone wants to get a char at an index
2270   // in a cons string, it is likely that more indices will be
2271   // accessed.
2272   Object* flat;
2273   { MaybeObject* maybe_flat = subject->TryFlatten();
2274     if (!maybe_flat->ToObject(&flat)) return maybe_flat;
2275   }
2276   subject = String::cast(flat);
2277 
2278   if (i >= static_cast<uint32_t>(subject->length())) {
2279     return isolate->heap()->nan_value();
2280   }
2281 
2282   return Smi::FromInt(subject->Get(i));
2283 }
2284 
2285 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CharFromCode)2286 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
2287   NoHandleAllocation ha;
2288   ASSERT(args.length() == 1);
2289   return CharFromCode(isolate, args[0]);
2290 }
2291 
2292 
2293 class FixedArrayBuilder {
2294  public:
FixedArrayBuilder(Isolate * isolate,int initial_capacity)2295   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
2296       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
2297         length_(0),
2298         has_non_smi_elements_(false) {
2299     // Require a non-zero initial size. Ensures that doubling the size to
2300     // extend the array will work.
2301     ASSERT(initial_capacity > 0);
2302   }
2303 
FixedArrayBuilder(Handle<FixedArray> backing_store)2304   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
2305       : array_(backing_store),
2306         length_(0),
2307         has_non_smi_elements_(false) {
2308     // Require a non-zero initial size. Ensures that doubling the size to
2309     // extend the array will work.
2310     ASSERT(backing_store->length() > 0);
2311   }
2312 
HasCapacity(int elements)2313   bool HasCapacity(int elements) {
2314     int length = array_->length();
2315     int required_length = length_ + elements;
2316     return (length >= required_length);
2317   }
2318 
EnsureCapacity(int elements)2319   void EnsureCapacity(int elements) {
2320     int length = array_->length();
2321     int required_length = length_ + elements;
2322     if (length < required_length) {
2323       int new_length = length;
2324       do {
2325         new_length *= 2;
2326       } while (new_length < required_length);
2327       Handle<FixedArray> extended_array =
2328           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
2329       array_->CopyTo(0, *extended_array, 0, length_);
2330       array_ = extended_array;
2331     }
2332   }
2333 
Add(Object * value)2334   void Add(Object* value) {
2335     ASSERT(!value->IsSmi());
2336     ASSERT(length_ < capacity());
2337     array_->set(length_, value);
2338     length_++;
2339     has_non_smi_elements_ = true;
2340   }
2341 
Add(Smi * value)2342   void Add(Smi* value) {
2343     ASSERT(value->IsSmi());
2344     ASSERT(length_ < capacity());
2345     array_->set(length_, value);
2346     length_++;
2347   }
2348 
array()2349   Handle<FixedArray> array() {
2350     return array_;
2351   }
2352 
length()2353   int length() {
2354     return length_;
2355   }
2356 
capacity()2357   int capacity() {
2358     return array_->length();
2359   }
2360 
ToJSArray()2361   Handle<JSArray> ToJSArray() {
2362     Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_);
2363     result_array->set_length(Smi::FromInt(length_));
2364     return result_array;
2365   }
2366 
ToJSArray(Handle<JSArray> target_array)2367   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
2368     FACTORY->SetContent(target_array, array_);
2369     target_array->set_length(Smi::FromInt(length_));
2370     return target_array;
2371   }
2372 
2373  private:
2374   Handle<FixedArray> array_;
2375   int length_;
2376   bool has_non_smi_elements_;
2377 };
2378 
2379 
2380 // Forward declarations.
2381 const int kStringBuilderConcatHelperLengthBits = 11;
2382 const int kStringBuilderConcatHelperPositionBits = 19;
2383 
2384 template <typename schar>
2385 static inline void StringBuilderConcatHelper(String*,
2386                                              schar*,
2387                                              FixedArray*,
2388                                              int);
2389 
2390 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
2391     StringBuilderSubstringLength;
2392 typedef BitField<int,
2393                  kStringBuilderConcatHelperLengthBits,
2394                  kStringBuilderConcatHelperPositionBits>
2395     StringBuilderSubstringPosition;
2396 
2397 
2398 class ReplacementStringBuilder {
2399  public:
ReplacementStringBuilder(Heap * heap,Handle<String> subject,int estimated_part_count)2400   ReplacementStringBuilder(Heap* heap,
2401                            Handle<String> subject,
2402                            int estimated_part_count)
2403       : heap_(heap),
2404         array_builder_(heap->isolate(), estimated_part_count),
2405         subject_(subject),
2406         character_count_(0),
2407         is_ascii_(subject->IsAsciiRepresentation()) {
2408     // Require a non-zero initial size. Ensures that doubling the size to
2409     // extend the array will work.
2410     ASSERT(estimated_part_count > 0);
2411   }
2412 
AddSubjectSlice(FixedArrayBuilder * builder,int from,int to)2413   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
2414                                      int from,
2415                                      int to) {
2416     ASSERT(from >= 0);
2417     int length = to - from;
2418     ASSERT(length > 0);
2419     if (StringBuilderSubstringLength::is_valid(length) &&
2420         StringBuilderSubstringPosition::is_valid(from)) {
2421       int encoded_slice = StringBuilderSubstringLength::encode(length) |
2422           StringBuilderSubstringPosition::encode(from);
2423       builder->Add(Smi::FromInt(encoded_slice));
2424     } else {
2425       // Otherwise encode as two smis.
2426       builder->Add(Smi::FromInt(-length));
2427       builder->Add(Smi::FromInt(from));
2428     }
2429   }
2430 
2431 
EnsureCapacity(int elements)2432   void EnsureCapacity(int elements) {
2433     array_builder_.EnsureCapacity(elements);
2434   }
2435 
2436 
AddSubjectSlice(int from,int to)2437   void AddSubjectSlice(int from, int to) {
2438     AddSubjectSlice(&array_builder_, from, to);
2439     IncrementCharacterCount(to - from);
2440   }
2441 
2442 
AddString(Handle<String> string)2443   void AddString(Handle<String> string) {
2444     int length = string->length();
2445     ASSERT(length > 0);
2446     AddElement(*string);
2447     if (!string->IsAsciiRepresentation()) {
2448       is_ascii_ = false;
2449     }
2450     IncrementCharacterCount(length);
2451   }
2452 
2453 
ToString()2454   Handle<String> ToString() {
2455     if (array_builder_.length() == 0) {
2456       return heap_->isolate()->factory()->empty_string();
2457     }
2458 
2459     Handle<String> joined_string;
2460     if (is_ascii_) {
2461       Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_);
2462       AssertNoAllocation no_alloc;
2463       char* char_buffer = seq->GetChars();
2464       StringBuilderConcatHelper(*subject_,
2465                                 char_buffer,
2466                                 *array_builder_.array(),
2467                                 array_builder_.length());
2468       joined_string = Handle<String>::cast(seq);
2469     } else {
2470       // Non-ASCII.
2471       Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
2472       AssertNoAllocation no_alloc;
2473       uc16* char_buffer = seq->GetChars();
2474       StringBuilderConcatHelper(*subject_,
2475                                 char_buffer,
2476                                 *array_builder_.array(),
2477                                 array_builder_.length());
2478       joined_string = Handle<String>::cast(seq);
2479     }
2480     return joined_string;
2481   }
2482 
2483 
IncrementCharacterCount(int by)2484   void IncrementCharacterCount(int by) {
2485     if (character_count_ > String::kMaxLength - by) {
2486       V8::FatalProcessOutOfMemory("String.replace result too large.");
2487     }
2488     character_count_ += by;
2489   }
2490 
GetParts()2491   Handle<JSArray> GetParts() {
2492     return array_builder_.ToJSArray();
2493   }
2494 
2495  private:
NewRawAsciiString(int length)2496   Handle<SeqAsciiString> NewRawAsciiString(int length) {
2497     return heap_->isolate()->factory()->NewRawAsciiString(length);
2498   }
2499 
2500 
NewRawTwoByteString(int length)2501   Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
2502     return heap_->isolate()->factory()->NewRawTwoByteString(length);
2503   }
2504 
2505 
AddElement(Object * element)2506   void AddElement(Object* element) {
2507     ASSERT(element->IsSmi() || element->IsString());
2508     ASSERT(array_builder_.capacity() > array_builder_.length());
2509     array_builder_.Add(element);
2510   }
2511 
2512   Heap* heap_;
2513   FixedArrayBuilder array_builder_;
2514   Handle<String> subject_;
2515   int character_count_;
2516   bool is_ascii_;
2517 };
2518 
2519 
2520 class CompiledReplacement {
2521  public:
CompiledReplacement()2522   CompiledReplacement()
2523       : parts_(1), replacement_substrings_(0), simple_hint_(false) {}
2524 
2525   void Compile(Handle<String> replacement,
2526                int capture_count,
2527                int subject_length);
2528 
2529   void Apply(ReplacementStringBuilder* builder,
2530              int match_from,
2531              int match_to,
2532              Handle<JSArray> last_match_info);
2533 
2534   // Number of distinct parts of the replacement pattern.
parts()2535   int parts() {
2536     return parts_.length();
2537   }
2538 
simple_hint()2539   bool simple_hint() {
2540     return simple_hint_;
2541   }
2542 
2543  private:
2544   enum PartType {
2545     SUBJECT_PREFIX = 1,
2546     SUBJECT_SUFFIX,
2547     SUBJECT_CAPTURE,
2548     REPLACEMENT_SUBSTRING,
2549     REPLACEMENT_STRING,
2550 
2551     NUMBER_OF_PART_TYPES
2552   };
2553 
2554   struct ReplacementPart {
SubjectMatchv8::internal::CompiledReplacement::ReplacementPart2555     static inline ReplacementPart SubjectMatch() {
2556       return ReplacementPart(SUBJECT_CAPTURE, 0);
2557     }
SubjectCapturev8::internal::CompiledReplacement::ReplacementPart2558     static inline ReplacementPart SubjectCapture(int capture_index) {
2559       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
2560     }
SubjectPrefixv8::internal::CompiledReplacement::ReplacementPart2561     static inline ReplacementPart SubjectPrefix() {
2562       return ReplacementPart(SUBJECT_PREFIX, 0);
2563     }
SubjectSuffixv8::internal::CompiledReplacement::ReplacementPart2564     static inline ReplacementPart SubjectSuffix(int subject_length) {
2565       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
2566     }
ReplacementStringv8::internal::CompiledReplacement::ReplacementPart2567     static inline ReplacementPart ReplacementString() {
2568       return ReplacementPart(REPLACEMENT_STRING, 0);
2569     }
ReplacementSubStringv8::internal::CompiledReplacement::ReplacementPart2570     static inline ReplacementPart ReplacementSubString(int from, int to) {
2571       ASSERT(from >= 0);
2572       ASSERT(to > from);
2573       return ReplacementPart(-from, to);
2574     }
2575 
2576     // If tag <= 0 then it is the negation of a start index of a substring of
2577     // the replacement pattern, otherwise it's a value from PartType.
ReplacementPartv8::internal::CompiledReplacement::ReplacementPart2578     ReplacementPart(int tag, int data)
2579         : tag(tag), data(data) {
2580       // Must be non-positive or a PartType value.
2581       ASSERT(tag < NUMBER_OF_PART_TYPES);
2582     }
2583     // Either a value of PartType or a non-positive number that is
2584     // the negation of an index into the replacement string.
2585     int tag;
2586     // The data value's interpretation depends on the value of tag:
2587     // tag == SUBJECT_PREFIX ||
2588     // tag == SUBJECT_SUFFIX:  data is unused.
2589     // tag == SUBJECT_CAPTURE: data is the number of the capture.
2590     // tag == REPLACEMENT_SUBSTRING ||
2591     // tag == REPLACEMENT_STRING:    data is index into array of substrings
2592     //                               of the replacement string.
2593     // tag <= 0: Temporary representation of the substring of the replacement
2594     //           string ranging over -tag .. data.
2595     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2596     //           substring objects.
2597     int data;
2598   };
2599 
2600   template<typename Char>
ParseReplacementPattern(ZoneList<ReplacementPart> * parts,Vector<Char> characters,int capture_count,int subject_length)2601   static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2602                                       Vector<Char> characters,
2603                                       int capture_count,
2604                                       int subject_length) {
2605     int length = characters.length();
2606     int last = 0;
2607     for (int i = 0; i < length; i++) {
2608       Char c = characters[i];
2609       if (c == '$') {
2610         int next_index = i + 1;
2611         if (next_index == length) {  // No next character!
2612           break;
2613         }
2614         Char c2 = characters[next_index];
2615         switch (c2) {
2616         case '$':
2617           if (i > last) {
2618             // There is a substring before. Include the first "$".
2619             parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
2620             last = next_index + 1;  // Continue after the second "$".
2621           } else {
2622             // Let the next substring start with the second "$".
2623             last = next_index;
2624           }
2625           i = next_index;
2626           break;
2627         case '`':
2628           if (i > last) {
2629             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2630           }
2631           parts->Add(ReplacementPart::SubjectPrefix());
2632           i = next_index;
2633           last = i + 1;
2634           break;
2635         case '\'':
2636           if (i > last) {
2637             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2638           }
2639           parts->Add(ReplacementPart::SubjectSuffix(subject_length));
2640           i = next_index;
2641           last = i + 1;
2642           break;
2643         case '&':
2644           if (i > last) {
2645             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2646           }
2647           parts->Add(ReplacementPart::SubjectMatch());
2648           i = next_index;
2649           last = i + 1;
2650           break;
2651         case '0':
2652         case '1':
2653         case '2':
2654         case '3':
2655         case '4':
2656         case '5':
2657         case '6':
2658         case '7':
2659         case '8':
2660         case '9': {
2661           int capture_ref = c2 - '0';
2662           if (capture_ref > capture_count) {
2663             i = next_index;
2664             continue;
2665           }
2666           int second_digit_index = next_index + 1;
2667           if (second_digit_index < length) {
2668             // Peek ahead to see if we have two digits.
2669             Char c3 = characters[second_digit_index];
2670             if ('0' <= c3 && c3 <= '9') {  // Double digits.
2671               int double_digit_ref = capture_ref * 10 + c3 - '0';
2672               if (double_digit_ref <= capture_count) {
2673                 next_index = second_digit_index;
2674                 capture_ref = double_digit_ref;
2675               }
2676             }
2677           }
2678           if (capture_ref > 0) {
2679             if (i > last) {
2680               parts->Add(ReplacementPart::ReplacementSubString(last, i));
2681             }
2682             ASSERT(capture_ref <= capture_count);
2683             parts->Add(ReplacementPart::SubjectCapture(capture_ref));
2684             last = next_index + 1;
2685           }
2686           i = next_index;
2687           break;
2688         }
2689         default:
2690           i = next_index;
2691           break;
2692         }
2693       }
2694     }
2695     if (length > last) {
2696       if (last == 0) {
2697         parts->Add(ReplacementPart::ReplacementString());
2698         return true;
2699       } else {
2700         parts->Add(ReplacementPart::ReplacementSubString(last, length));
2701       }
2702     }
2703     return false;
2704   }
2705 
2706   ZoneList<ReplacementPart> parts_;
2707   ZoneList<Handle<String> > replacement_substrings_;
2708   bool simple_hint_;
2709 };
2710 
2711 
Compile(Handle<String> replacement,int capture_count,int subject_length)2712 void CompiledReplacement::Compile(Handle<String> replacement,
2713                                   int capture_count,
2714                                   int subject_length) {
2715   {
2716     AssertNoAllocation no_alloc;
2717     String::FlatContent content = replacement->GetFlatContent();
2718     ASSERT(content.IsFlat());
2719     if (content.IsAscii()) {
2720       simple_hint_ = ParseReplacementPattern(&parts_,
2721                                              content.ToAsciiVector(),
2722                                              capture_count,
2723                                              subject_length);
2724     } else {
2725       ASSERT(content.IsTwoByte());
2726       simple_hint_ = ParseReplacementPattern(&parts_,
2727                                              content.ToUC16Vector(),
2728                                              capture_count,
2729                                              subject_length);
2730     }
2731   }
2732   Isolate* isolate = replacement->GetIsolate();
2733   // Find substrings of replacement string and create them as String objects.
2734   int substring_index = 0;
2735   for (int i = 0, n = parts_.length(); i < n; i++) {
2736     int tag = parts_[i].tag;
2737     if (tag <= 0) {  // A replacement string slice.
2738       int from = -tag;
2739       int to = parts_[i].data;
2740       replacement_substrings_.Add(
2741           isolate->factory()->NewSubString(replacement, from, to));
2742       parts_[i].tag = REPLACEMENT_SUBSTRING;
2743       parts_[i].data = substring_index;
2744       substring_index++;
2745     } else if (tag == REPLACEMENT_STRING) {
2746       replacement_substrings_.Add(replacement);
2747       parts_[i].data = substring_index;
2748       substring_index++;
2749     }
2750   }
2751 }
2752 
2753 
Apply(ReplacementStringBuilder * builder,int match_from,int match_to,Handle<JSArray> last_match_info)2754 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
2755                                 int match_from,
2756                                 int match_to,
2757                                 Handle<JSArray> last_match_info) {
2758   for (int i = 0, n = parts_.length(); i < n; i++) {
2759     ReplacementPart part = parts_[i];
2760     switch (part.tag) {
2761       case SUBJECT_PREFIX:
2762         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2763         break;
2764       case SUBJECT_SUFFIX: {
2765         int subject_length = part.data;
2766         if (match_to < subject_length) {
2767           builder->AddSubjectSlice(match_to, subject_length);
2768         }
2769         break;
2770       }
2771       case SUBJECT_CAPTURE: {
2772         int capture = part.data;
2773         FixedArray* match_info = FixedArray::cast(last_match_info->elements());
2774         int from = RegExpImpl::GetCapture(match_info, capture * 2);
2775         int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
2776         if (from >= 0 && to > from) {
2777           builder->AddSubjectSlice(from, to);
2778         }
2779         break;
2780       }
2781       case REPLACEMENT_SUBSTRING:
2782       case REPLACEMENT_STRING:
2783         builder->AddString(replacement_substrings_[part.data]);
2784         break;
2785       default:
2786         UNREACHABLE();
2787     }
2788   }
2789 }
2790 
2791 
FindAsciiStringIndices(Vector<const char> subject,char pattern,ZoneList<int> * indices,unsigned int limit)2792 void FindAsciiStringIndices(Vector<const char> subject,
2793                             char pattern,
2794                             ZoneList<int>* indices,
2795                             unsigned int limit) {
2796   ASSERT(limit > 0);
2797   // Collect indices of pattern in subject using memchr.
2798   // Stop after finding at most limit values.
2799   const char* subject_start = reinterpret_cast<const char*>(subject.start());
2800   const char* subject_end = subject_start + subject.length();
2801   const char* pos = subject_start;
2802   while (limit > 0) {
2803     pos = reinterpret_cast<const char*>(
2804         memchr(pos, pattern, subject_end - pos));
2805     if (pos == NULL) return;
2806     indices->Add(static_cast<int>(pos - subject_start));
2807     pos++;
2808     limit--;
2809   }
2810 }
2811 
2812 
2813 template <typename SubjectChar, typename PatternChar>
FindStringIndices(Isolate * isolate,Vector<const SubjectChar> subject,Vector<const PatternChar> pattern,ZoneList<int> * indices,unsigned int limit)2814 void FindStringIndices(Isolate* isolate,
2815                        Vector<const SubjectChar> subject,
2816                        Vector<const PatternChar> pattern,
2817                        ZoneList<int>* indices,
2818                        unsigned int limit) {
2819   ASSERT(limit > 0);
2820   // Collect indices of pattern in subject.
2821   // Stop after finding at most limit values.
2822   int pattern_length = pattern.length();
2823   int index = 0;
2824   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2825   while (limit > 0) {
2826     index = search.Search(subject, index);
2827     if (index < 0) return;
2828     indices->Add(index);
2829     index += pattern_length;
2830     limit--;
2831   }
2832 }
2833 
2834 
FindStringIndicesDispatch(Isolate * isolate,String * subject,String * pattern,ZoneList<int> * indices,unsigned int limit)2835 void FindStringIndicesDispatch(Isolate* isolate,
2836                                String* subject,
2837                                String* pattern,
2838                                ZoneList<int>* indices,
2839                                unsigned int limit) {
2840   {
2841     AssertNoAllocation no_gc;
2842     String::FlatContent subject_content = subject->GetFlatContent();
2843     String::FlatContent pattern_content = pattern->GetFlatContent();
2844     ASSERT(subject_content.IsFlat());
2845     ASSERT(pattern_content.IsFlat());
2846     if (subject_content.IsAscii()) {
2847       Vector<const char> subject_vector = subject_content.ToAsciiVector();
2848       if (pattern_content.IsAscii()) {
2849         Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
2850         if (pattern_vector.length() == 1) {
2851           FindAsciiStringIndices(subject_vector,
2852                                  pattern_vector[0],
2853                                  indices,
2854                                  limit);
2855         } else {
2856           FindStringIndices(isolate,
2857                             subject_vector,
2858                             pattern_vector,
2859                             indices,
2860                             limit);
2861         }
2862       } else {
2863         FindStringIndices(isolate,
2864                           subject_vector,
2865                           pattern_content.ToUC16Vector(),
2866                           indices,
2867                           limit);
2868       }
2869     } else {
2870       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
2871       if (pattern_content.IsAscii()) {
2872         FindStringIndices(isolate,
2873                           subject_vector,
2874                           pattern_content.ToAsciiVector(),
2875                           indices,
2876                           limit);
2877       } else {
2878         FindStringIndices(isolate,
2879                           subject_vector,
2880                           pattern_content.ToUC16Vector(),
2881                           indices,
2882                           limit);
2883       }
2884     }
2885   }
2886 }
2887 
2888 
2889 template<typename ResultSeqString>
StringReplaceStringWithString(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> pattern_regexp,Handle<String> replacement)2890 MUST_USE_RESULT static MaybeObject* StringReplaceStringWithString(
2891     Isolate* isolate,
2892     Handle<String> subject,
2893     Handle<JSRegExp> pattern_regexp,
2894     Handle<String> replacement) {
2895   ASSERT(subject->IsFlat());
2896   ASSERT(replacement->IsFlat());
2897 
2898   ZoneScope zone_space(isolate, DELETE_ON_EXIT);
2899   ZoneList<int> indices(8);
2900   ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
2901   String* pattern =
2902       String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
2903   int subject_len = subject->length();
2904   int pattern_len = pattern->length();
2905   int replacement_len = replacement->length();
2906 
2907   FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff);
2908 
2909   int matches = indices.length();
2910   if (matches == 0) return *subject;
2911 
2912   int result_len = (replacement_len - pattern_len) * matches + subject_len;
2913   int subject_pos = 0;
2914   int result_pos = 0;
2915 
2916   Handle<ResultSeqString> result;
2917   if (ResultSeqString::kHasAsciiEncoding) {
2918     result = Handle<ResultSeqString>::cast(
2919         isolate->factory()->NewRawAsciiString(result_len));
2920   } else {
2921     result = Handle<ResultSeqString>::cast(
2922         isolate->factory()->NewRawTwoByteString(result_len));
2923   }
2924 
2925   for (int i = 0; i < matches; i++) {
2926     // Copy non-matched subject content.
2927     if (subject_pos < indices.at(i)) {
2928       String::WriteToFlat(*subject,
2929                           result->GetChars() + result_pos,
2930                           subject_pos,
2931                           indices.at(i));
2932       result_pos += indices.at(i) - subject_pos;
2933     }
2934 
2935     // Replace match.
2936     if (replacement_len > 0) {
2937       String::WriteToFlat(*replacement,
2938                           result->GetChars() + result_pos,
2939                           0,
2940                           replacement_len);
2941       result_pos += replacement_len;
2942     }
2943 
2944     subject_pos = indices.at(i) + pattern_len;
2945   }
2946   // Add remaining subject content at the end.
2947   if (subject_pos < subject_len) {
2948     String::WriteToFlat(*subject,
2949                         result->GetChars() + result_pos,
2950                         subject_pos,
2951                         subject_len);
2952   }
2953   return *result;
2954 }
2955 
2956 
StringReplaceRegExpWithString(Isolate * isolate,String * subject,JSRegExp * regexp,String * replacement,JSArray * last_match_info)2957 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
2958     Isolate* isolate,
2959     String* subject,
2960     JSRegExp* regexp,
2961     String* replacement,
2962     JSArray* last_match_info) {
2963   ASSERT(subject->IsFlat());
2964   ASSERT(replacement->IsFlat());
2965 
2966   HandleScope handles(isolate);
2967 
2968   int length = subject->length();
2969   Handle<String> subject_handle(subject);
2970   Handle<JSRegExp> regexp_handle(regexp);
2971   Handle<String> replacement_handle(replacement);
2972   Handle<JSArray> last_match_info_handle(last_match_info);
2973   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
2974                                           subject_handle,
2975                                           0,
2976                                           last_match_info_handle);
2977   if (match.is_null()) {
2978     return Failure::Exception();
2979   }
2980   if (match->IsNull()) {
2981     return *subject_handle;
2982   }
2983 
2984   int capture_count = regexp_handle->CaptureCount();
2985 
2986   // CompiledReplacement uses zone allocation.
2987   ZoneScope zone(isolate, DELETE_ON_EXIT);
2988   CompiledReplacement compiled_replacement;
2989   compiled_replacement.Compile(replacement_handle,
2990                                capture_count,
2991                                length);
2992 
2993   bool is_global = regexp_handle->GetFlags().is_global();
2994 
2995   // Shortcut for simple non-regexp global replacements
2996   if (is_global &&
2997       regexp_handle->TypeTag() == JSRegExp::ATOM &&
2998       compiled_replacement.simple_hint()) {
2999     if (subject_handle->HasOnlyAsciiChars() &&
3000         replacement_handle->HasOnlyAsciiChars()) {
3001       return StringReplaceStringWithString<SeqAsciiString>(
3002           isolate, subject_handle, regexp_handle, replacement_handle);
3003     } else {
3004       return StringReplaceStringWithString<SeqTwoByteString>(
3005           isolate, subject_handle, regexp_handle, replacement_handle);
3006     }
3007   }
3008 
3009   // Guessing the number of parts that the final result string is built
3010   // from. Global regexps can match any number of times, so we guess
3011   // conservatively.
3012   int expected_parts =
3013       (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
3014   ReplacementStringBuilder builder(isolate->heap(),
3015                                    subject_handle,
3016                                    expected_parts);
3017 
3018   // Index of end of last match.
3019   int prev = 0;
3020 
3021   // Number of parts added by compiled replacement plus preceeding
3022   // string and possibly suffix after last match.  It is possible for
3023   // all components to use two elements when encoded as two smis.
3024   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3025   bool matched = true;
3026   do {
3027     ASSERT(last_match_info_handle->HasFastElements());
3028     // Increase the capacity of the builder before entering local handle-scope,
3029     // so its internal buffer can safely allocate a new handle if it grows.
3030     builder.EnsureCapacity(parts_added_per_loop);
3031 
3032     HandleScope loop_scope(isolate);
3033     int start, end;
3034     {
3035       AssertNoAllocation match_info_array_is_not_in_a_handle;
3036       FixedArray* match_info_array =
3037           FixedArray::cast(last_match_info_handle->elements());
3038 
3039       ASSERT_EQ(capture_count * 2 + 2,
3040                 RegExpImpl::GetLastCaptureCount(match_info_array));
3041       start = RegExpImpl::GetCapture(match_info_array, 0);
3042       end = RegExpImpl::GetCapture(match_info_array, 1);
3043     }
3044 
3045     if (prev < start) {
3046       builder.AddSubjectSlice(prev, start);
3047     }
3048     compiled_replacement.Apply(&builder,
3049                                start,
3050                                end,
3051                                last_match_info_handle);
3052     prev = end;
3053 
3054     // Only continue checking for global regexps.
3055     if (!is_global) break;
3056 
3057     // Continue from where the match ended, unless it was an empty match.
3058     int next = end;
3059     if (start == end) {
3060       next = end + 1;
3061       if (next > length) break;
3062     }
3063 
3064     match = RegExpImpl::Exec(regexp_handle,
3065                              subject_handle,
3066                              next,
3067                              last_match_info_handle);
3068     if (match.is_null()) {
3069       return Failure::Exception();
3070     }
3071     matched = !match->IsNull();
3072   } while (matched);
3073 
3074   if (prev < length) {
3075     builder.AddSubjectSlice(prev, length);
3076   }
3077 
3078   return *(builder.ToString());
3079 }
3080 
3081 
3082 template <typename ResultSeqString>
StringReplaceRegExpWithEmptyString(Isolate * isolate,String * subject,JSRegExp * regexp,JSArray * last_match_info)3083 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
3084     Isolate* isolate,
3085     String* subject,
3086     JSRegExp* regexp,
3087     JSArray* last_match_info) {
3088   ASSERT(subject->IsFlat());
3089 
3090   HandleScope handles(isolate);
3091 
3092   Handle<String> subject_handle(subject);
3093   Handle<JSRegExp> regexp_handle(regexp);
3094 
3095   // Shortcut for simple non-regexp global replacements
3096   if (regexp_handle->GetFlags().is_global() &&
3097       regexp_handle->TypeTag() == JSRegExp::ATOM) {
3098     Handle<String> empty_string_handle(HEAP->empty_string());
3099     if (subject_handle->HasOnlyAsciiChars()) {
3100       return StringReplaceStringWithString<SeqAsciiString>(
3101           isolate, subject_handle, regexp_handle, empty_string_handle);
3102     } else {
3103       return StringReplaceStringWithString<SeqTwoByteString>(
3104           isolate, subject_handle, regexp_handle, empty_string_handle);
3105     }
3106   }
3107 
3108   Handle<JSArray> last_match_info_handle(last_match_info);
3109   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
3110                                           subject_handle,
3111                                           0,
3112                                           last_match_info_handle);
3113   if (match.is_null()) return Failure::Exception();
3114   if (match->IsNull()) return *subject_handle;
3115 
3116   ASSERT(last_match_info_handle->HasFastElements());
3117 
3118   int start, end;
3119   {
3120     AssertNoAllocation match_info_array_is_not_in_a_handle;
3121     FixedArray* match_info_array =
3122         FixedArray::cast(last_match_info_handle->elements());
3123 
3124     start = RegExpImpl::GetCapture(match_info_array, 0);
3125     end = RegExpImpl::GetCapture(match_info_array, 1);
3126   }
3127 
3128   int length = subject_handle->length();
3129   int new_length = length - (end - start);
3130   if (new_length == 0) {
3131     return isolate->heap()->empty_string();
3132   }
3133   Handle<ResultSeqString> answer;
3134   if (ResultSeqString::kHasAsciiEncoding) {
3135     answer = Handle<ResultSeqString>::cast(
3136         isolate->factory()->NewRawAsciiString(new_length));
3137   } else {
3138     answer = Handle<ResultSeqString>::cast(
3139         isolate->factory()->NewRawTwoByteString(new_length));
3140   }
3141 
3142   // If the regexp isn't global, only match once.
3143   if (!regexp_handle->GetFlags().is_global()) {
3144     if (start > 0) {
3145       String::WriteToFlat(*subject_handle,
3146                           answer->GetChars(),
3147                           0,
3148                           start);
3149     }
3150     if (end < length) {
3151       String::WriteToFlat(*subject_handle,
3152                           answer->GetChars() + start,
3153                           end,
3154                           length);
3155     }
3156     return *answer;
3157   }
3158 
3159   int prev = 0;  // Index of end of last match.
3160   int next = 0;  // Start of next search (prev unless last match was empty).
3161   int position = 0;
3162 
3163   do {
3164     if (prev < start) {
3165       // Add substring subject[prev;start] to answer string.
3166       String::WriteToFlat(*subject_handle,
3167                           answer->GetChars() + position,
3168                           prev,
3169                           start);
3170       position += start - prev;
3171     }
3172     prev = end;
3173     next = end;
3174     // Continue from where the match ended, unless it was an empty match.
3175     if (start == end) {
3176       next++;
3177       if (next > length) break;
3178     }
3179     match = RegExpImpl::Exec(regexp_handle,
3180                              subject_handle,
3181                              next,
3182                              last_match_info_handle);
3183     if (match.is_null()) return Failure::Exception();
3184     if (match->IsNull()) break;
3185 
3186     ASSERT(last_match_info_handle->HasFastElements());
3187     HandleScope loop_scope(isolate);
3188     {
3189       AssertNoAllocation match_info_array_is_not_in_a_handle;
3190       FixedArray* match_info_array =
3191           FixedArray::cast(last_match_info_handle->elements());
3192       start = RegExpImpl::GetCapture(match_info_array, 0);
3193       end = RegExpImpl::GetCapture(match_info_array, 1);
3194     }
3195   } while (true);
3196 
3197   if (prev < length) {
3198     // Add substring subject[prev;length] to answer string.
3199     String::WriteToFlat(*subject_handle,
3200                         answer->GetChars() + position,
3201                         prev,
3202                         length);
3203     position += length - prev;
3204   }
3205 
3206   if (position == 0) {
3207     return isolate->heap()->empty_string();
3208   }
3209 
3210   // Shorten string and fill
3211   int string_size = ResultSeqString::SizeFor(position);
3212   int allocated_string_size = ResultSeqString::SizeFor(new_length);
3213   int delta = allocated_string_size - string_size;
3214 
3215   answer->set_length(position);
3216   if (delta == 0) return *answer;
3217 
3218   Address end_of_string = answer->address() + string_size;
3219   isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
3220   if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
3221     MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
3222   }
3223 
3224   return *answer;
3225 }
3226 
3227 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringReplaceRegExpWithString)3228 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
3229   ASSERT(args.length() == 4);
3230 
3231   CONVERT_ARG_CHECKED(String, subject, 0);
3232   if (!subject->IsFlat()) {
3233     Object* flat_subject;
3234     { MaybeObject* maybe_flat_subject = subject->TryFlatten();
3235       if (!maybe_flat_subject->ToObject(&flat_subject)) {
3236         return maybe_flat_subject;
3237       }
3238     }
3239     subject = String::cast(flat_subject);
3240   }
3241 
3242   CONVERT_ARG_CHECKED(String, replacement, 2);
3243   if (!replacement->IsFlat()) {
3244     Object* flat_replacement;
3245     { MaybeObject* maybe_flat_replacement = replacement->TryFlatten();
3246       if (!maybe_flat_replacement->ToObject(&flat_replacement)) {
3247         return maybe_flat_replacement;
3248       }
3249     }
3250     replacement = String::cast(flat_replacement);
3251   }
3252 
3253   CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
3254   CONVERT_ARG_CHECKED(JSArray, last_match_info, 3);
3255 
3256   ASSERT(last_match_info->HasFastElements());
3257 
3258   if (replacement->length() == 0) {
3259     if (subject->HasOnlyAsciiChars()) {
3260       return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
3261           isolate, subject, regexp, last_match_info);
3262     } else {
3263       return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
3264           isolate, subject, regexp, last_match_info);
3265     }
3266   }
3267 
3268   return StringReplaceRegExpWithString(isolate,
3269                                        subject,
3270                                        regexp,
3271                                        replacement,
3272                                        last_match_info);
3273 }
3274 
3275 
StringReplaceOneCharWithString(Isolate * isolate,Handle<String> subject,Handle<String> search,Handle<String> replace,bool * found,int recursion_limit)3276 Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate,
3277                                                        Handle<String> subject,
3278                                                        Handle<String> search,
3279                                                        Handle<String> replace,
3280                                                        bool* found,
3281                                                        int recursion_limit) {
3282   if (recursion_limit == 0) return Handle<String>::null();
3283   if (subject->IsConsString()) {
3284     ConsString* cons = ConsString::cast(*subject);
3285     Handle<String> first = Handle<String>(cons->first());
3286     Handle<String> second = Handle<String>(cons->second());
3287     Handle<String> new_first =
3288         StringReplaceOneCharWithString(isolate,
3289                                        first,
3290                                        search,
3291                                        replace,
3292                                        found,
3293                                        recursion_limit - 1);
3294     if (*found) return isolate->factory()->NewConsString(new_first, second);
3295     if (new_first.is_null()) return new_first;
3296 
3297     Handle<String> new_second =
3298         StringReplaceOneCharWithString(isolate,
3299                                        second,
3300                                        search,
3301                                        replace,
3302                                        found,
3303                                        recursion_limit - 1);
3304     if (*found) return isolate->factory()->NewConsString(first, new_second);
3305     if (new_second.is_null()) return new_second;
3306 
3307     return subject;
3308   } else {
3309     int index = StringMatch(isolate, subject, search, 0);
3310     if (index == -1) return subject;
3311     *found = true;
3312     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
3313     Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
3314     Handle<String> second =
3315         isolate->factory()->NewSubString(subject, index + 1, subject->length());
3316     return isolate->factory()->NewConsString(cons1, second);
3317   }
3318 }
3319 
3320 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringReplaceOneCharWithString)3321 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
3322   ASSERT(args.length() == 3);
3323   HandleScope scope(isolate);
3324   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3325   CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
3326   CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
3327 
3328   // If the cons string tree is too deep, we simply abort the recursion and
3329   // retry with a flattened subject string.
3330   const int kRecursionLimit = 0x1000;
3331   bool found = false;
3332   Handle<String> result =
3333       Runtime::StringReplaceOneCharWithString(isolate,
3334                                               subject,
3335                                               search,
3336                                               replace,
3337                                               &found,
3338                                               kRecursionLimit);
3339   if (!result.is_null()) return *result;
3340   return *Runtime::StringReplaceOneCharWithString(isolate,
3341                                                   FlattenGetString(subject),
3342                                                   search,
3343                                                   replace,
3344                                                   &found,
3345                                                   kRecursionLimit);
3346 }
3347 
3348 
3349 // Perform string match of pattern on subject, starting at start index.
3350 // Caller must ensure that 0 <= start_index <= sub->length(),
3351 // and should check that pat->length() + start_index <= sub->length().
StringMatch(Isolate * isolate,Handle<String> sub,Handle<String> pat,int start_index)3352 int Runtime::StringMatch(Isolate* isolate,
3353                          Handle<String> sub,
3354                          Handle<String> pat,
3355                          int start_index) {
3356   ASSERT(0 <= start_index);
3357   ASSERT(start_index <= sub->length());
3358 
3359   int pattern_length = pat->length();
3360   if (pattern_length == 0) return start_index;
3361 
3362   int subject_length = sub->length();
3363   if (start_index + pattern_length > subject_length) return -1;
3364 
3365   if (!sub->IsFlat()) FlattenString(sub);
3366   if (!pat->IsFlat()) FlattenString(pat);
3367 
3368   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
3369   // Extract flattened substrings of cons strings before determining asciiness.
3370   String::FlatContent seq_sub = sub->GetFlatContent();
3371   String::FlatContent seq_pat = pat->GetFlatContent();
3372 
3373   // dispatch on type of strings
3374   if (seq_pat.IsAscii()) {
3375     Vector<const char> pat_vector = seq_pat.ToAsciiVector();
3376     if (seq_sub.IsAscii()) {
3377       return SearchString(isolate,
3378                           seq_sub.ToAsciiVector(),
3379                           pat_vector,
3380                           start_index);
3381     }
3382     return SearchString(isolate,
3383                         seq_sub.ToUC16Vector(),
3384                         pat_vector,
3385                         start_index);
3386   }
3387   Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
3388   if (seq_sub.IsAscii()) {
3389     return SearchString(isolate,
3390                         seq_sub.ToAsciiVector(),
3391                         pat_vector,
3392                         start_index);
3393   }
3394   return SearchString(isolate,
3395                       seq_sub.ToUC16Vector(),
3396                       pat_vector,
3397                       start_index);
3398 }
3399 
3400 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringIndexOf)3401 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
3402   HandleScope scope(isolate);  // create a new handle scope
3403   ASSERT(args.length() == 3);
3404 
3405   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3406   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3407 
3408   Object* index = args[2];
3409   uint32_t start_index;
3410   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3411 
3412   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
3413   int position =
3414       Runtime::StringMatch(isolate, sub, pat, start_index);
3415   return Smi::FromInt(position);
3416 }
3417 
3418 
3419 template <typename schar, typename pchar>
StringMatchBackwards(Vector<const schar> subject,Vector<const pchar> pattern,int idx)3420 static int StringMatchBackwards(Vector<const schar> subject,
3421                                 Vector<const pchar> pattern,
3422                                 int idx) {
3423   int pattern_length = pattern.length();
3424   ASSERT(pattern_length >= 1);
3425   ASSERT(idx + pattern_length <= subject.length());
3426 
3427   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
3428     for (int i = 0; i < pattern_length; i++) {
3429       uc16 c = pattern[i];
3430       if (c > String::kMaxAsciiCharCode) {
3431         return -1;
3432       }
3433     }
3434   }
3435 
3436   pchar pattern_first_char = pattern[0];
3437   for (int i = idx; i >= 0; i--) {
3438     if (subject[i] != pattern_first_char) continue;
3439     int j = 1;
3440     while (j < pattern_length) {
3441       if (pattern[j] != subject[i+j]) {
3442         break;
3443       }
3444       j++;
3445     }
3446     if (j == pattern_length) {
3447       return i;
3448     }
3449   }
3450   return -1;
3451 }
3452 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringLastIndexOf)3453 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
3454   HandleScope scope(isolate);  // create a new handle scope
3455   ASSERT(args.length() == 3);
3456 
3457   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3458   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3459 
3460   Object* index = args[2];
3461   uint32_t start_index;
3462   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3463 
3464   uint32_t pat_length = pat->length();
3465   uint32_t sub_length = sub->length();
3466 
3467   if (start_index + pat_length > sub_length) {
3468     start_index = sub_length - pat_length;
3469   }
3470 
3471   if (pat_length == 0) {
3472     return Smi::FromInt(start_index);
3473   }
3474 
3475   if (!sub->IsFlat()) FlattenString(sub);
3476   if (!pat->IsFlat()) FlattenString(pat);
3477 
3478   int position = -1;
3479   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
3480 
3481   String::FlatContent sub_content = sub->GetFlatContent();
3482   String::FlatContent pat_content = pat->GetFlatContent();
3483 
3484   if (pat_content.IsAscii()) {
3485     Vector<const char> pat_vector = pat_content.ToAsciiVector();
3486     if (sub_content.IsAscii()) {
3487       position = StringMatchBackwards(sub_content.ToAsciiVector(),
3488                                       pat_vector,
3489                                       start_index);
3490     } else {
3491       position = StringMatchBackwards(sub_content.ToUC16Vector(),
3492                                       pat_vector,
3493                                       start_index);
3494     }
3495   } else {
3496     Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
3497     if (sub_content.IsAscii()) {
3498       position = StringMatchBackwards(sub_content.ToAsciiVector(),
3499                                       pat_vector,
3500                                       start_index);
3501     } else {
3502       position = StringMatchBackwards(sub_content.ToUC16Vector(),
3503                                       pat_vector,
3504                                       start_index);
3505     }
3506   }
3507 
3508   return Smi::FromInt(position);
3509 }
3510 
3511 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringLocaleCompare)3512 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
3513   NoHandleAllocation ha;
3514   ASSERT(args.length() == 2);
3515 
3516   CONVERT_ARG_CHECKED(String, str1, 0);
3517   CONVERT_ARG_CHECKED(String, str2, 1);
3518 
3519   if (str1 == str2) return Smi::FromInt(0);  // Equal.
3520   int str1_length = str1->length();
3521   int str2_length = str2->length();
3522 
3523   // Decide trivial cases without flattening.
3524   if (str1_length == 0) {
3525     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
3526     return Smi::FromInt(-str2_length);
3527   } else {
3528     if (str2_length == 0) return Smi::FromInt(str1_length);
3529   }
3530 
3531   int end = str1_length < str2_length ? str1_length : str2_length;
3532 
3533   // No need to flatten if we are going to find the answer on the first
3534   // character.  At this point we know there is at least one character
3535   // in each string, due to the trivial case handling above.
3536   int d = str1->Get(0) - str2->Get(0);
3537   if (d != 0) return Smi::FromInt(d);
3538 
3539   str1->TryFlatten();
3540   str2->TryFlatten();
3541 
3542   StringInputBuffer& buf1 =
3543       *isolate->runtime_state()->string_locale_compare_buf1();
3544   StringInputBuffer& buf2 =
3545       *isolate->runtime_state()->string_locale_compare_buf2();
3546 
3547   buf1.Reset(str1);
3548   buf2.Reset(str2);
3549 
3550   for (int i = 0; i < end; i++) {
3551     uint16_t char1 = buf1.GetNext();
3552     uint16_t char2 = buf2.GetNext();
3553     if (char1 != char2) return Smi::FromInt(char1 - char2);
3554   }
3555 
3556   return Smi::FromInt(str1_length - str2_length);
3557 }
3558 
3559 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SubString)3560 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
3561   NoHandleAllocation ha;
3562   ASSERT(args.length() == 3);
3563 
3564   CONVERT_ARG_CHECKED(String, value, 0);
3565   int start, end;
3566   // We have a fast integer-only case here to avoid a conversion to double in
3567   // the common case where from and to are Smis.
3568   if (args[1]->IsSmi() && args[2]->IsSmi()) {
3569     CONVERT_SMI_ARG_CHECKED(from_number, 1);
3570     CONVERT_SMI_ARG_CHECKED(to_number, 2);
3571     start = from_number;
3572     end = to_number;
3573   } else {
3574     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
3575     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
3576     start = FastD2I(from_number);
3577     end = FastD2I(to_number);
3578   }
3579   RUNTIME_ASSERT(end >= start);
3580   RUNTIME_ASSERT(start >= 0);
3581   RUNTIME_ASSERT(end <= value->length());
3582   isolate->counters()->sub_string_runtime()->Increment();
3583   return value->SubString(start, end);
3584 }
3585 
3586 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringMatch)3587 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
3588   ASSERT_EQ(3, args.length());
3589 
3590   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3591   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
3592   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
3593   HandleScope handles;
3594 
3595   Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
3596 
3597   if (match.is_null()) {
3598     return Failure::Exception();
3599   }
3600   if (match->IsNull()) {
3601     return isolate->heap()->null_value();
3602   }
3603   int length = subject->length();
3604 
3605   ZoneScope zone_space(isolate, DELETE_ON_EXIT);
3606   ZoneList<int> offsets(8);
3607   int start;
3608   int end;
3609   do {
3610     {
3611       AssertNoAllocation no_alloc;
3612       FixedArray* elements = FixedArray::cast(regexp_info->elements());
3613       start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
3614       end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
3615     }
3616     offsets.Add(start);
3617     offsets.Add(end);
3618     if (start == end) if (++end > length) break;
3619     match = RegExpImpl::Exec(regexp, subject, end, regexp_info);
3620     if (match.is_null()) {
3621       return Failure::Exception();
3622     }
3623   } while (!match->IsNull());
3624   int matches = offsets.length() / 2;
3625   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
3626   Handle<String> substring = isolate->factory()->
3627     NewSubString(subject, offsets.at(0), offsets.at(1));
3628   elements->set(0, *substring);
3629   for (int i = 1; i < matches ; i++) {
3630     int from = offsets.at(i * 2);
3631     int to = offsets.at(i * 2 + 1);
3632     Handle<String> substring = isolate->factory()->
3633         NewProperSubString(subject, from, to);
3634     elements->set(i, *substring);
3635   }
3636   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
3637   result->set_length(Smi::FromInt(matches));
3638   return *result;
3639 }
3640 
3641 
3642 // Two smis before and after the match, for very long strings.
3643 const int kMaxBuilderEntriesPerRegExpMatch = 5;
3644 
3645 
SetLastMatchInfoNoCaptures(Handle<String> subject,Handle<JSArray> last_match_info,int match_start,int match_end)3646 static void SetLastMatchInfoNoCaptures(Handle<String> subject,
3647                                        Handle<JSArray> last_match_info,
3648                                        int match_start,
3649                                        int match_end) {
3650   // Fill last_match_info with a single capture.
3651   last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
3652   AssertNoAllocation no_gc;
3653   FixedArray* elements = FixedArray::cast(last_match_info->elements());
3654   RegExpImpl::SetLastCaptureCount(elements, 2);
3655   RegExpImpl::SetLastInput(elements, *subject);
3656   RegExpImpl::SetLastSubject(elements, *subject);
3657   RegExpImpl::SetCapture(elements, 0, match_start);
3658   RegExpImpl::SetCapture(elements, 1, match_end);
3659 }
3660 
3661 
3662 template <typename SubjectChar, typename PatternChar>
SearchStringMultiple(Isolate * isolate,Vector<const SubjectChar> subject,Vector<const PatternChar> pattern,String * pattern_string,FixedArrayBuilder * builder,int * match_pos)3663 static bool SearchStringMultiple(Isolate* isolate,
3664                                  Vector<const SubjectChar> subject,
3665                                  Vector<const PatternChar> pattern,
3666                                  String* pattern_string,
3667                                  FixedArrayBuilder* builder,
3668                                  int* match_pos) {
3669   int pos = *match_pos;
3670   int subject_length = subject.length();
3671   int pattern_length = pattern.length();
3672   int max_search_start = subject_length - pattern_length;
3673   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3674   while (pos <= max_search_start) {
3675     if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3676       *match_pos = pos;
3677       return false;
3678     }
3679     // Position of end of previous match.
3680     int match_end = pos + pattern_length;
3681     int new_pos = search.Search(subject, match_end);
3682     if (new_pos >= 0) {
3683       // A match.
3684       if (new_pos > match_end) {
3685         ReplacementStringBuilder::AddSubjectSlice(builder,
3686             match_end,
3687             new_pos);
3688       }
3689       pos = new_pos;
3690       builder->Add(pattern_string);
3691     } else {
3692       break;
3693     }
3694   }
3695 
3696   if (pos < max_search_start) {
3697     ReplacementStringBuilder::AddSubjectSlice(builder,
3698                                               pos + pattern_length,
3699                                               subject_length);
3700   }
3701   *match_pos = pos;
3702   return true;
3703 }
3704 
3705 
SearchStringMultiple(Isolate * isolate,Handle<String> subject,Handle<String> pattern,Handle<JSArray> last_match_info,FixedArrayBuilder * builder)3706 static bool SearchStringMultiple(Isolate* isolate,
3707                                  Handle<String> subject,
3708                                  Handle<String> pattern,
3709                                  Handle<JSArray> last_match_info,
3710                                  FixedArrayBuilder* builder) {
3711   ASSERT(subject->IsFlat());
3712   ASSERT(pattern->IsFlat());
3713 
3714   // Treating as if a previous match was before first character.
3715   int match_pos = -pattern->length();
3716 
3717   for (;;) {  // Break when search complete.
3718     builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3719     AssertNoAllocation no_gc;
3720     String::FlatContent subject_content = subject->GetFlatContent();
3721     String::FlatContent pattern_content = pattern->GetFlatContent();
3722     if (subject_content.IsAscii()) {
3723       Vector<const char> subject_vector = subject_content.ToAsciiVector();
3724       if (pattern_content.IsAscii()) {
3725         if (SearchStringMultiple(isolate,
3726                                  subject_vector,
3727                                  pattern_content.ToAsciiVector(),
3728                                  *pattern,
3729                                  builder,
3730                                  &match_pos)) break;
3731       } else {
3732         if (SearchStringMultiple(isolate,
3733                                  subject_vector,
3734                                  pattern_content.ToUC16Vector(),
3735                                  *pattern,
3736                                  builder,
3737                                  &match_pos)) break;
3738       }
3739     } else {
3740       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3741       if (pattern_content.IsAscii()) {
3742         if (SearchStringMultiple(isolate,
3743                                  subject_vector,
3744                                  pattern_content.ToAsciiVector(),
3745                                  *pattern,
3746                                  builder,
3747                                  &match_pos)) break;
3748       } else {
3749         if (SearchStringMultiple(isolate,
3750                                  subject_vector,
3751                                  pattern_content.ToUC16Vector(),
3752                                  *pattern,
3753                                  builder,
3754                                  &match_pos)) break;
3755       }
3756     }
3757   }
3758 
3759   if (match_pos >= 0) {
3760     SetLastMatchInfoNoCaptures(subject,
3761                                last_match_info,
3762                                match_pos,
3763                                match_pos + pattern->length());
3764     return true;
3765   }
3766   return false;  // No matches at all.
3767 }
3768 
3769 
SearchRegExpNoCaptureMultiple(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_array,FixedArrayBuilder * builder)3770 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
3771     Isolate* isolate,
3772     Handle<String> subject,
3773     Handle<JSRegExp> regexp,
3774     Handle<JSArray> last_match_array,
3775     FixedArrayBuilder* builder) {
3776   ASSERT(subject->IsFlat());
3777   int match_start = -1;
3778   int match_end = 0;
3779   int pos = 0;
3780   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3781   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3782 
3783   OffsetsVector registers(required_registers, isolate);
3784   Vector<int32_t> register_vector(registers.vector(), registers.length());
3785   int subject_length = subject->length();
3786   bool first = true;
3787 
3788   for (;;) {  // Break on failure, return on exception.
3789     RegExpImpl::IrregexpResult result =
3790         RegExpImpl::IrregexpExecOnce(regexp,
3791                                      subject,
3792                                      pos,
3793                                      register_vector);
3794     if (result == RegExpImpl::RE_SUCCESS) {
3795       match_start = register_vector[0];
3796       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3797       if (match_end < match_start) {
3798         ReplacementStringBuilder::AddSubjectSlice(builder,
3799                                                   match_end,
3800                                                   match_start);
3801       }
3802       match_end = register_vector[1];
3803       HandleScope loop_scope(isolate);
3804       if (!first) {
3805         builder->Add(*isolate->factory()->NewProperSubString(subject,
3806                                                              match_start,
3807                                                              match_end));
3808       } else {
3809         builder->Add(*isolate->factory()->NewSubString(subject,
3810                                                        match_start,
3811                                                        match_end));
3812       }
3813       if (match_start != match_end) {
3814         pos = match_end;
3815       } else {
3816         pos = match_end + 1;
3817         if (pos > subject_length) break;
3818       }
3819     } else if (result == RegExpImpl::RE_FAILURE) {
3820       break;
3821     } else {
3822       ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3823       return result;
3824     }
3825     first = false;
3826   }
3827 
3828   if (match_start >= 0) {
3829     if (match_end < subject_length) {
3830       ReplacementStringBuilder::AddSubjectSlice(builder,
3831                                                 match_end,
3832                                                 subject_length);
3833     }
3834     SetLastMatchInfoNoCaptures(subject,
3835                                last_match_array,
3836                                match_start,
3837                                match_end);
3838     return RegExpImpl::RE_SUCCESS;
3839   } else {
3840     return RegExpImpl::RE_FAILURE;  // No matches at all.
3841   }
3842 }
3843 
3844 
SearchRegExpMultiple(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_array,FixedArrayBuilder * builder)3845 static RegExpImpl::IrregexpResult SearchRegExpMultiple(
3846     Isolate* isolate,
3847     Handle<String> subject,
3848     Handle<JSRegExp> regexp,
3849     Handle<JSArray> last_match_array,
3850     FixedArrayBuilder* builder) {
3851 
3852   ASSERT(subject->IsFlat());
3853   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3854   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3855 
3856   OffsetsVector registers(required_registers, isolate);
3857   Vector<int32_t> register_vector(registers.vector(), registers.length());
3858 
3859   RegExpImpl::IrregexpResult result =
3860       RegExpImpl::IrregexpExecOnce(regexp,
3861                                    subject,
3862                                    0,
3863                                    register_vector);
3864 
3865   int capture_count = regexp->CaptureCount();
3866   int subject_length = subject->length();
3867 
3868   // Position to search from.
3869   int pos = 0;
3870   // End of previous match. Differs from pos if match was empty.
3871   int match_end = 0;
3872   if (result == RegExpImpl::RE_SUCCESS) {
3873     // Need to keep a copy of the previous match for creating last_match_info
3874     // at the end, so we have two vectors that we swap between.
3875     OffsetsVector registers2(required_registers, isolate);
3876     Vector<int> prev_register_vector(registers2.vector(), registers2.length());
3877     bool first = true;
3878     do {
3879       int match_start = register_vector[0];
3880       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3881       if (match_end < match_start) {
3882         ReplacementStringBuilder::AddSubjectSlice(builder,
3883                                                   match_end,
3884                                                   match_start);
3885       }
3886       match_end = register_vector[1];
3887 
3888       {
3889         // Avoid accumulating new handles inside loop.
3890         HandleScope temp_scope(isolate);
3891         // Arguments array to replace function is match, captures, index and
3892         // subject, i.e., 3 + capture count in total.
3893         Handle<FixedArray> elements =
3894             isolate->factory()->NewFixedArray(3 + capture_count);
3895         Handle<String> match;
3896         if (!first) {
3897           match = isolate->factory()->NewProperSubString(subject,
3898                                                          match_start,
3899                                                          match_end);
3900         } else {
3901           match = isolate->factory()->NewSubString(subject,
3902                                                    match_start,
3903                                                    match_end);
3904         }
3905         elements->set(0, *match);
3906         for (int i = 1; i <= capture_count; i++) {
3907           int start = register_vector[i * 2];
3908           if (start >= 0) {
3909             int end = register_vector[i * 2 + 1];
3910             ASSERT(start <= end);
3911             Handle<String> substring;
3912             if (!first) {
3913               substring = isolate->factory()->NewProperSubString(subject,
3914                                                                  start,
3915                                                                  end);
3916             } else {
3917               substring = isolate->factory()->NewSubString(subject, start, end);
3918             }
3919             elements->set(i, *substring);
3920           } else {
3921             ASSERT(register_vector[i * 2 + 1] < 0);
3922             elements->set(i, isolate->heap()->undefined_value());
3923           }
3924         }
3925         elements->set(capture_count + 1, Smi::FromInt(match_start));
3926         elements->set(capture_count + 2, *subject);
3927         builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
3928       }
3929       // Swap register vectors, so the last successful match is in
3930       // prev_register_vector.
3931       Vector<int32_t> tmp = prev_register_vector;
3932       prev_register_vector = register_vector;
3933       register_vector = tmp;
3934 
3935       if (match_end > match_start) {
3936         pos = match_end;
3937       } else {
3938         pos = match_end + 1;
3939         if (pos > subject_length) {
3940           break;
3941         }
3942       }
3943 
3944       result = RegExpImpl::IrregexpExecOnce(regexp,
3945                                             subject,
3946                                             pos,
3947                                             register_vector);
3948       first = false;
3949     } while (result == RegExpImpl::RE_SUCCESS);
3950 
3951     if (result != RegExpImpl::RE_EXCEPTION) {
3952       // Finished matching, with at least one match.
3953       if (match_end < subject_length) {
3954         ReplacementStringBuilder::AddSubjectSlice(builder,
3955                                                   match_end,
3956                                                   subject_length);
3957       }
3958 
3959       int last_match_capture_count = (capture_count + 1) * 2;
3960       int last_match_array_size =
3961           last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3962       last_match_array->EnsureSize(last_match_array_size);
3963       AssertNoAllocation no_gc;
3964       FixedArray* elements = FixedArray::cast(last_match_array->elements());
3965       RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3966       RegExpImpl::SetLastSubject(elements, *subject);
3967       RegExpImpl::SetLastInput(elements, *subject);
3968       for (int i = 0; i < last_match_capture_count; i++) {
3969         RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
3970       }
3971       return RegExpImpl::RE_SUCCESS;
3972     }
3973   }
3974   // No matches at all, return failure or exception result directly.
3975   return result;
3976 }
3977 
3978 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpExecMultiple)3979 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
3980   ASSERT(args.length() == 4);
3981   HandleScope handles(isolate);
3982 
3983   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
3984   if (!subject->IsFlat()) FlattenString(subject);
3985   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
3986   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
3987   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
3988 
3989   ASSERT(last_match_info->HasFastElements());
3990   ASSERT(regexp->GetFlags().is_global());
3991   Handle<FixedArray> result_elements;
3992   if (result_array->HasFastElements()) {
3993     result_elements =
3994         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3995   }
3996   if (result_elements.is_null() || result_elements->length() < 16) {
3997     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
3998   }
3999   FixedArrayBuilder builder(result_elements);
4000 
4001   if (regexp->TypeTag() == JSRegExp::ATOM) {
4002     Handle<String> pattern(
4003         String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
4004     ASSERT(pattern->IsFlat());
4005     if (SearchStringMultiple(isolate, subject, pattern,
4006                              last_match_info, &builder)) {
4007       return *builder.ToJSArray(result_array);
4008     }
4009     return isolate->heap()->null_value();
4010   }
4011 
4012   ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
4013 
4014   RegExpImpl::IrregexpResult result;
4015   if (regexp->CaptureCount() == 0) {
4016     result = SearchRegExpNoCaptureMultiple(isolate,
4017                                            subject,
4018                                            regexp,
4019                                            last_match_info,
4020                                            &builder);
4021   } else {
4022     result = SearchRegExpMultiple(isolate,
4023                                   subject,
4024                                   regexp,
4025                                   last_match_info,
4026                                   &builder);
4027   }
4028   if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
4029   if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value();
4030   ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
4031   return Failure::Exception();
4032 }
4033 
4034 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToRadixString)4035 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4036   NoHandleAllocation ha;
4037   ASSERT(args.length() == 2);
4038   CONVERT_SMI_ARG_CHECKED(radix, 1);
4039   RUNTIME_ASSERT(2 <= radix && radix <= 36);
4040 
4041   // Fast case where the result is a one character string.
4042   if (args[0]->IsSmi()) {
4043     int value = args.smi_at(0);
4044     if (value >= 0 && value < radix) {
4045       // Character array used for conversion.
4046       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4047       return isolate->heap()->
4048           LookupSingleCharacterStringFromCode(kCharTable[value]);
4049     }
4050   }
4051 
4052   // Slow case.
4053   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4054   if (isnan(value)) {
4055     return *isolate->factory()->nan_symbol();
4056   }
4057   if (isinf(value)) {
4058     if (value < 0) {
4059       return *isolate->factory()->minus_infinity_symbol();
4060     }
4061     return *isolate->factory()->infinity_symbol();
4062   }
4063   char* str = DoubleToRadixCString(value, radix);
4064   MaybeObject* result =
4065       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4066   DeleteArray(str);
4067   return result;
4068 }
4069 
4070 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToFixed)4071 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4072   NoHandleAllocation ha;
4073   ASSERT(args.length() == 2);
4074 
4075   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4076   if (isnan(value)) {
4077     return *isolate->factory()->nan_symbol();
4078   }
4079   if (isinf(value)) {
4080     if (value < 0) {
4081       return *isolate->factory()->minus_infinity_symbol();
4082     }
4083     return *isolate->factory()->infinity_symbol();
4084   }
4085   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4086   int f = FastD2I(f_number);
4087   RUNTIME_ASSERT(f >= 0);
4088   char* str = DoubleToFixedCString(value, f);
4089   MaybeObject* res =
4090       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4091   DeleteArray(str);
4092   return res;
4093 }
4094 
4095 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToExponential)4096 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4097   NoHandleAllocation ha;
4098   ASSERT(args.length() == 2);
4099 
4100   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4101   if (isnan(value)) {
4102     return *isolate->factory()->nan_symbol();
4103   }
4104   if (isinf(value)) {
4105     if (value < 0) {
4106       return *isolate->factory()->minus_infinity_symbol();
4107     }
4108     return *isolate->factory()->infinity_symbol();
4109   }
4110   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4111   int f = FastD2I(f_number);
4112   RUNTIME_ASSERT(f >= -1 && f <= 20);
4113   char* str = DoubleToExponentialCString(value, f);
4114   MaybeObject* res =
4115       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4116   DeleteArray(str);
4117   return res;
4118 }
4119 
4120 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToPrecision)4121 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4122   NoHandleAllocation ha;
4123   ASSERT(args.length() == 2);
4124 
4125   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4126   if (isnan(value)) {
4127     return *isolate->factory()->nan_symbol();
4128   }
4129   if (isinf(value)) {
4130     if (value < 0) {
4131       return *isolate->factory()->minus_infinity_symbol();
4132     }
4133     return *isolate->factory()->infinity_symbol();
4134   }
4135   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4136   int f = FastD2I(f_number);
4137   RUNTIME_ASSERT(f >= 1 && f <= 21);
4138   char* str = DoubleToPrecisionCString(value, f);
4139   MaybeObject* res =
4140       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4141   DeleteArray(str);
4142   return res;
4143 }
4144 
4145 
4146 // Returns a single character string where first character equals
4147 // string->Get(index).
GetCharAt(Handle<String> string,uint32_t index)4148 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4149   if (index < static_cast<uint32_t>(string->length())) {
4150     string->TryFlatten();
4151     return LookupSingleCharacterStringFromCode(
4152         string->Get(index));
4153   }
4154   return Execution::CharAt(string, index);
4155 }
4156 
4157 
GetElementOrCharAt(Isolate * isolate,Handle<Object> object,uint32_t index)4158 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4159                                          Handle<Object> object,
4160                                          uint32_t index) {
4161   // Handle [] indexing on Strings
4162   if (object->IsString()) {
4163     Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4164     if (!result->IsUndefined()) return *result;
4165   }
4166 
4167   // Handle [] indexing on String objects
4168   if (object->IsStringObjectWithCharacterAt(index)) {
4169     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4170     Handle<Object> result =
4171         GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4172     if (!result->IsUndefined()) return *result;
4173   }
4174 
4175   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4176     return object->GetPrototype()->GetElement(index);
4177   }
4178 
4179   return object->GetElement(index);
4180 }
4181 
4182 
GetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key)4183 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4184                                         Handle<Object> object,
4185                                         Handle<Object> key) {
4186   HandleScope scope(isolate);
4187 
4188   if (object->IsUndefined() || object->IsNull()) {
4189     Handle<Object> args[2] = { key, object };
4190     Handle<Object> error =
4191         isolate->factory()->NewTypeError("non_object_property_load",
4192                                          HandleVector(args, 2));
4193     return isolate->Throw(*error);
4194   }
4195 
4196   // Check if the given key is an array index.
4197   uint32_t index;
4198   if (key->ToArrayIndex(&index)) {
4199     return GetElementOrCharAt(isolate, object, index);
4200   }
4201 
4202   // Convert the key to a string - possibly by calling back into JavaScript.
4203   Handle<String> name;
4204   if (key->IsString()) {
4205     name = Handle<String>::cast(key);
4206   } else {
4207     bool has_pending_exception = false;
4208     Handle<Object> converted =
4209         Execution::ToString(key, &has_pending_exception);
4210     if (has_pending_exception) return Failure::Exception();
4211     name = Handle<String>::cast(converted);
4212   }
4213 
4214   // Check if the name is trivially convertible to an index and get
4215   // the element if so.
4216   if (name->AsArrayIndex(&index)) {
4217     return GetElementOrCharAt(isolate, object, index);
4218   } else {
4219     return object->GetProperty(*name);
4220   }
4221 }
4222 
4223 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetProperty)4224 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4225   NoHandleAllocation ha;
4226   ASSERT(args.length() == 2);
4227 
4228   Handle<Object> object = args.at<Object>(0);
4229   Handle<Object> key = args.at<Object>(1);
4230 
4231   return Runtime::GetObjectProperty(isolate, object, key);
4232 }
4233 
4234 
4235 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(MaybeObject *,Runtime_KeyedGetProperty)4236 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4237   NoHandleAllocation ha;
4238   ASSERT(args.length() == 2);
4239 
4240   // Fast cases for getting named properties of the receiver JSObject
4241   // itself.
4242   //
4243   // The global proxy objects has to be excluded since LocalLookup on
4244   // the global proxy object can return a valid result even though the
4245   // global proxy object never has properties.  This is the case
4246   // because the global proxy object forwards everything to its hidden
4247   // prototype including local lookups.
4248   //
4249   // Additionally, we need to make sure that we do not cache results
4250   // for objects that require access checks.
4251   if (args[0]->IsJSObject()) {
4252     if (!args[0]->IsJSGlobalProxy() &&
4253         !args[0]->IsAccessCheckNeeded() &&
4254         args[1]->IsString()) {
4255       JSObject* receiver = JSObject::cast(args[0]);
4256       String* key = String::cast(args[1]);
4257       if (receiver->HasFastProperties()) {
4258         // Attempt to use lookup cache.
4259         Map* receiver_map = receiver->map();
4260         KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4261         int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4262         if (offset != -1) {
4263           Object* value = receiver->FastPropertyAt(offset);
4264           return value->IsTheHole()
4265               ? isolate->heap()->undefined_value()
4266               : value;
4267         }
4268         // Lookup cache miss.  Perform lookup and update the cache if
4269         // appropriate.
4270         LookupResult result(isolate);
4271         receiver->LocalLookup(key, &result);
4272         if (result.IsFound() && result.type() == FIELD) {
4273           int offset = result.GetFieldIndex();
4274           keyed_lookup_cache->Update(receiver_map, key, offset);
4275           return receiver->FastPropertyAt(offset);
4276         }
4277       } else {
4278         // Attempt dictionary lookup.
4279         StringDictionary* dictionary = receiver->property_dictionary();
4280         int entry = dictionary->FindEntry(key);
4281         if ((entry != StringDictionary::kNotFound) &&
4282             (dictionary->DetailsAt(entry).type() == NORMAL)) {
4283           Object* value = dictionary->ValueAt(entry);
4284           if (!receiver->IsGlobalObject()) return value;
4285           value = JSGlobalPropertyCell::cast(value)->value();
4286           if (!value->IsTheHole()) return value;
4287           // If value is the hole do the general lookup.
4288         }
4289       }
4290     } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4291       // JSObject without a string key. If the key is a Smi, check for a
4292       // definite out-of-bounds access to elements, which is a strong indicator
4293       // that subsequent accesses will also call the runtime. Proactively
4294       // transition elements to FAST_ELEMENTS to avoid excessive boxing of
4295       // doubles for those future calls in the case that the elements would
4296       // become FAST_DOUBLE_ELEMENTS.
4297       Handle<JSObject> js_object(args.at<JSObject>(0));
4298       ElementsKind elements_kind = js_object->GetElementsKind();
4299       if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4300           elements_kind == FAST_DOUBLE_ELEMENTS) {
4301         FixedArrayBase* elements = js_object->elements();
4302         if (args.at<Smi>(1)->value() >= elements->length()) {
4303           MaybeObject* maybe_object = TransitionElements(js_object,
4304                                                          FAST_ELEMENTS,
4305                                                          isolate);
4306           if (maybe_object->IsFailure()) return maybe_object;
4307         }
4308       }
4309     }
4310   } else if (args[0]->IsString() && args[1]->IsSmi()) {
4311     // Fast case for string indexing using [] with a smi index.
4312     HandleScope scope(isolate);
4313     Handle<String> str = args.at<String>(0);
4314     int index = args.smi_at(1);
4315     if (index >= 0 && index < str->length()) {
4316       Handle<Object> result = GetCharAt(str, index);
4317       return *result;
4318     }
4319   }
4320 
4321   // Fall back to GetObjectProperty.
4322   return Runtime::GetObjectProperty(isolate,
4323                                     args.at<Object>(0),
4324                                     args.at<Object>(1));
4325 }
4326 
4327 
IsValidAccessor(Handle<Object> obj)4328 static bool IsValidAccessor(Handle<Object> obj) {
4329   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4330 }
4331 
4332 
4333 // Implements part of 8.12.9 DefineOwnProperty.
4334 // There are 3 cases that lead here:
4335 // Step 4b - define a new accessor property.
4336 // Steps 9c & 12 - replace an existing data property with an accessor property.
4337 // Step 12 - update an existing accessor property with an accessor or generic
4338 //           descriptor.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DefineOrRedefineAccessorProperty)4339 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4340   ASSERT(args.length() == 5);
4341   HandleScope scope(isolate);
4342   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4343   RUNTIME_ASSERT(!obj->IsNull());
4344   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4345   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4346   RUNTIME_ASSERT(IsValidAccessor(getter));
4347   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4348   RUNTIME_ASSERT(IsValidAccessor(setter));
4349   CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4350   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4351   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4352 
4353   bool fast = obj->HasFastProperties();
4354   JSObject::DefineAccessor(obj, name, getter, setter, attr);
4355   if (fast) JSObject::TransformToFastProperties(obj, 0);
4356   return isolate->heap()->undefined_value();
4357 }
4358 
4359 // Implements part of 8.12.9 DefineOwnProperty.
4360 // There are 3 cases that lead here:
4361 // Step 4a - define a new data property.
4362 // Steps 9b & 12 - replace an existing accessor property with a data property.
4363 // Step 12 - update an existing data property with a data or generic
4364 //           descriptor.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DefineOrRedefineDataProperty)4365 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4366   ASSERT(args.length() == 4);
4367   HandleScope scope(isolate);
4368   CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4369   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4370   CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4371   CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4372   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4373   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4374 
4375   LookupResult result(isolate);
4376   js_object->LocalLookupRealNamedProperty(*name, &result);
4377 
4378   // Special case for callback properties.
4379   if (result.IsFound() && result.type() == CALLBACKS) {
4380     Object* callback = result.GetCallbackObject();
4381     // To be compatible with Safari we do not change the value on API objects
4382     // in Object.defineProperty(). Firefox disagrees here, and actually changes
4383     // the value.
4384     if (callback->IsAccessorInfo()) {
4385       return isolate->heap()->undefined_value();
4386     }
4387     // Avoid redefining foreign callback as data property, just use the stored
4388     // setter to update the value instead.
4389     // TODO(mstarzinger): So far this only works if property attributes don't
4390     // change, this should be fixed once we cleanup the underlying code.
4391     if (callback->IsForeign() && result.GetAttributes() == attr) {
4392       return js_object->SetPropertyWithCallback(callback,
4393                                                 *name,
4394                                                 *obj_value,
4395                                                 result.holder(),
4396                                                 kStrictMode);
4397     }
4398   }
4399 
4400   // Take special care when attributes are different and there is already
4401   // a property. For simplicity we normalize the property which enables us
4402   // to not worry about changing the instance_descriptor and creating a new
4403   // map. The current version of SetObjectProperty does not handle attributes
4404   // correctly in the case where a property is a field and is reset with
4405   // new attributes.
4406   if (result.IsProperty() &&
4407       (attr != result.GetAttributes() || result.type() == CALLBACKS)) {
4408     // New attributes - normalize to avoid writing to instance descriptor
4409     if (js_object->IsJSGlobalProxy()) {
4410       // Since the result is a property, the prototype will exist so
4411       // we don't have to check for null.
4412       js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
4413     }
4414     JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
4415     // Use IgnoreAttributes version since a readonly property may be
4416     // overridden and SetProperty does not allow this.
4417     return js_object->SetLocalPropertyIgnoreAttributes(*name,
4418                                                        *obj_value,
4419                                                        attr);
4420   }
4421 
4422   return Runtime::ForceSetObjectProperty(isolate,
4423                                          js_object,
4424                                          name,
4425                                          obj_value,
4426                                          attr);
4427 }
4428 
4429 
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr,StrictModeFlag strict_mode)4430 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
4431                                         Handle<Object> object,
4432                                         Handle<Object> key,
4433                                         Handle<Object> value,
4434                                         PropertyAttributes attr,
4435                                         StrictModeFlag strict_mode) {
4436   SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
4437   HandleScope scope(isolate);
4438 
4439   if (object->IsUndefined() || object->IsNull()) {
4440     Handle<Object> args[2] = { key, object };
4441     Handle<Object> error =
4442         isolate->factory()->NewTypeError("non_object_property_store",
4443                                          HandleVector(args, 2));
4444     return isolate->Throw(*error);
4445   }
4446 
4447   if (object->IsJSProxy()) {
4448     bool has_pending_exception = false;
4449     Handle<Object> name = Execution::ToString(key, &has_pending_exception);
4450     if (has_pending_exception) return Failure::Exception();
4451     return JSProxy::cast(*object)->SetProperty(
4452         String::cast(*name), *value, attr, strict_mode);
4453   }
4454 
4455   // If the object isn't a JavaScript object, we ignore the store.
4456   if (!object->IsJSObject()) return *value;
4457 
4458   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4459 
4460   // Check if the given key is an array index.
4461   uint32_t index;
4462   if (key->ToArrayIndex(&index)) {
4463     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4464     // of a string using [] notation.  We need to support this too in
4465     // JavaScript.
4466     // In the case of a String object we just need to redirect the assignment to
4467     // the underlying string if the index is in range.  Since the underlying
4468     // string does nothing with the assignment then we can ignore such
4469     // assignments.
4470     if (js_object->IsStringObjectWithCharacterAt(index)) {
4471       return *value;
4472     }
4473 
4474     Handle<Object> result = JSObject::SetElement(
4475         js_object, index, value, attr, strict_mode, set_mode);
4476     if (result.is_null()) return Failure::Exception();
4477     return *value;
4478   }
4479 
4480   if (key->IsString()) {
4481     Handle<Object> result;
4482     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4483       result = JSObject::SetElement(
4484           js_object, index, value, attr, strict_mode, set_mode);
4485     } else {
4486       Handle<String> key_string = Handle<String>::cast(key);
4487       key_string->TryFlatten();
4488       result = JSReceiver::SetProperty(
4489           js_object, key_string, value, attr, strict_mode);
4490     }
4491     if (result.is_null()) return Failure::Exception();
4492     return *value;
4493   }
4494 
4495   // Call-back into JavaScript to convert the key to a string.
4496   bool has_pending_exception = false;
4497   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4498   if (has_pending_exception) return Failure::Exception();
4499   Handle<String> name = Handle<String>::cast(converted);
4500 
4501   if (name->AsArrayIndex(&index)) {
4502     return js_object->SetElement(
4503         index, *value, attr, strict_mode, true, set_mode);
4504   } else {
4505     return js_object->SetProperty(*name, *value, attr, strict_mode);
4506   }
4507 }
4508 
4509 
ForceSetObjectProperty(Isolate * isolate,Handle<JSObject> js_object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr)4510 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
4511                                              Handle<JSObject> js_object,
4512                                              Handle<Object> key,
4513                                              Handle<Object> value,
4514                                              PropertyAttributes attr) {
4515   HandleScope scope(isolate);
4516 
4517   // Check if the given key is an array index.
4518   uint32_t index;
4519   if (key->ToArrayIndex(&index)) {
4520     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4521     // of a string using [] notation.  We need to support this too in
4522     // JavaScript.
4523     // In the case of a String object we just need to redirect the assignment to
4524     // the underlying string if the index is in range.  Since the underlying
4525     // string does nothing with the assignment then we can ignore such
4526     // assignments.
4527     if (js_object->IsStringObjectWithCharacterAt(index)) {
4528       return *value;
4529     }
4530 
4531     return js_object->SetElement(
4532         index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4533   }
4534 
4535   if (key->IsString()) {
4536     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4537       return js_object->SetElement(
4538           index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4539     } else {
4540       Handle<String> key_string = Handle<String>::cast(key);
4541       key_string->TryFlatten();
4542       return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4543                                                          *value,
4544                                                          attr);
4545     }
4546   }
4547 
4548   // Call-back into JavaScript to convert the key to a string.
4549   bool has_pending_exception = false;
4550   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4551   if (has_pending_exception) return Failure::Exception();
4552   Handle<String> name = Handle<String>::cast(converted);
4553 
4554   if (name->AsArrayIndex(&index)) {
4555     return js_object->SetElement(
4556         index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4557   } else {
4558     return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4559   }
4560 }
4561 
4562 
ForceDeleteObjectProperty(Isolate * isolate,Handle<JSReceiver> receiver,Handle<Object> key)4563 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
4564                                                 Handle<JSReceiver> receiver,
4565                                                 Handle<Object> key) {
4566   HandleScope scope(isolate);
4567 
4568   // Check if the given key is an array index.
4569   uint32_t index;
4570   if (key->ToArrayIndex(&index)) {
4571     // In Firefox/SpiderMonkey, Safari and Opera you can access the
4572     // characters of a string using [] notation.  In the case of a
4573     // String object we just need to redirect the deletion to the
4574     // underlying string if the index is in range.  Since the
4575     // underlying string does nothing with the deletion, we can ignore
4576     // such deletions.
4577     if (receiver->IsStringObjectWithCharacterAt(index)) {
4578       return isolate->heap()->true_value();
4579     }
4580 
4581     return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
4582   }
4583 
4584   Handle<String> key_string;
4585   if (key->IsString()) {
4586     key_string = Handle<String>::cast(key);
4587   } else {
4588     // Call-back into JavaScript to convert the key to a string.
4589     bool has_pending_exception = false;
4590     Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4591     if (has_pending_exception) return Failure::Exception();
4592     key_string = Handle<String>::cast(converted);
4593   }
4594 
4595   key_string->TryFlatten();
4596   return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
4597 }
4598 
4599 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetProperty)4600 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
4601   NoHandleAllocation ha;
4602   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
4603 
4604   Handle<Object> object = args.at<Object>(0);
4605   Handle<Object> key = args.at<Object>(1);
4606   Handle<Object> value = args.at<Object>(2);
4607   CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
4608   RUNTIME_ASSERT(
4609       (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4610   // Compute attributes.
4611   PropertyAttributes attributes =
4612       static_cast<PropertyAttributes>(unchecked_attributes);
4613 
4614   StrictModeFlag strict_mode = kNonStrictMode;
4615   if (args.length() == 5) {
4616     CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
4617     strict_mode = strict_mode_flag;
4618   }
4619 
4620   return Runtime::SetObjectProperty(isolate,
4621                                     object,
4622                                     key,
4623                                     value,
4624                                     attributes,
4625                                     strict_mode);
4626 }
4627 
4628 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TransitionElementsSmiToDouble)4629 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
4630   NoHandleAllocation ha;
4631   RUNTIME_ASSERT(args.length() == 1);
4632   Handle<Object> object = args.at<Object>(0);
4633   return TransitionElements(object, FAST_DOUBLE_ELEMENTS, isolate);
4634 }
4635 
4636 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TransitionElementsDoubleToObject)4637 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) {
4638   NoHandleAllocation ha;
4639   RUNTIME_ASSERT(args.length() == 1);
4640   Handle<Object> object = args.at<Object>(0);
4641   return TransitionElements(object, FAST_ELEMENTS, isolate);
4642 }
4643 
4644 
4645 // Set the native flag on the function.
4646 // This is used to decide if we should transform null and undefined
4647 // into the global object when doing call and apply.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetNativeFlag)4648 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
4649   NoHandleAllocation ha;
4650   RUNTIME_ASSERT(args.length() == 1);
4651 
4652   Handle<Object> object = args.at<Object>(0);
4653 
4654   if (object->IsJSFunction()) {
4655     JSFunction* func = JSFunction::cast(*object);
4656     func->shared()->set_native(true);
4657   }
4658   return isolate->heap()->undefined_value();
4659 }
4660 
4661 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StoreArrayLiteralElement)4662 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
4663   RUNTIME_ASSERT(args.length() == 5);
4664   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
4665   CONVERT_SMI_ARG_CHECKED(store_index, 1);
4666   Handle<Object> value = args.at<Object>(2);
4667   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
4668   CONVERT_SMI_ARG_CHECKED(literal_index, 4);
4669   HandleScope scope;
4670 
4671   Object* raw_boilerplate_object = literals->get(literal_index);
4672   Handle<JSArray> boilerplate_object(JSArray::cast(raw_boilerplate_object));
4673 #if DEBUG
4674   ElementsKind elements_kind = object->GetElementsKind();
4675 #endif
4676   ASSERT(elements_kind <= FAST_DOUBLE_ELEMENTS);
4677   // Smis should never trigger transitions.
4678   ASSERT(!value->IsSmi());
4679 
4680   if (value->IsNumber()) {
4681     ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS);
4682     JSObject::TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS);
4683     JSObject::TransitionElementsKind(boilerplate_object, FAST_DOUBLE_ELEMENTS);
4684     ASSERT(object->GetElementsKind() == FAST_DOUBLE_ELEMENTS);
4685     FixedDoubleArray* double_array =
4686         FixedDoubleArray::cast(object->elements());
4687     HeapNumber* number = HeapNumber::cast(*value);
4688     double_array->set(store_index, number->Number());
4689   } else {
4690     ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4691            elements_kind == FAST_DOUBLE_ELEMENTS);
4692     JSObject::TransitionElementsKind(object, FAST_ELEMENTS);
4693     JSObject::TransitionElementsKind(boilerplate_object, FAST_ELEMENTS);
4694     FixedArray* object_array =
4695         FixedArray::cast(object->elements());
4696     object_array->set(store_index, *value);
4697   }
4698   return *object;
4699 }
4700 
4701 
4702 // Set a local property, even if it is READ_ONLY.  If the property does not
4703 // exist, it will be added with attributes NONE.
RUNTIME_FUNCTION(MaybeObject *,Runtime_IgnoreAttributesAndSetProperty)4704 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
4705   NoHandleAllocation ha;
4706   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
4707   CONVERT_ARG_CHECKED(JSObject, object, 0);
4708   CONVERT_ARG_CHECKED(String, name, 1);
4709   // Compute attributes.
4710   PropertyAttributes attributes = NONE;
4711   if (args.length() == 4) {
4712     CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
4713     // Only attribute bits should be set.
4714     RUNTIME_ASSERT(
4715         (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4716     attributes = static_cast<PropertyAttributes>(unchecked_value);
4717   }
4718 
4719   return object->
4720       SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
4721 }
4722 
4723 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteProperty)4724 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
4725   NoHandleAllocation ha;
4726   ASSERT(args.length() == 3);
4727 
4728   CONVERT_ARG_CHECKED(JSReceiver, object, 0);
4729   CONVERT_ARG_CHECKED(String, key, 1);
4730   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
4731   return object->DeleteProperty(key, (strict_mode == kStrictMode)
4732                                       ? JSReceiver::STRICT_DELETION
4733                                       : JSReceiver::NORMAL_DELETION);
4734 }
4735 
4736 
HasLocalPropertyImplementation(Isolate * isolate,Handle<JSObject> object,Handle<String> key)4737 static Object* HasLocalPropertyImplementation(Isolate* isolate,
4738                                               Handle<JSObject> object,
4739                                               Handle<String> key) {
4740   if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
4741   // Handle hidden prototypes.  If there's a hidden prototype above this thing
4742   // then we have to check it for properties, because they are supposed to
4743   // look like they are on this object.
4744   Handle<Object> proto(object->GetPrototype());
4745   if (proto->IsJSObject() &&
4746       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
4747     return HasLocalPropertyImplementation(isolate,
4748                                           Handle<JSObject>::cast(proto),
4749                                           key);
4750   }
4751   return isolate->heap()->false_value();
4752 }
4753 
4754 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasLocalProperty)4755 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
4756   NoHandleAllocation ha;
4757   ASSERT(args.length() == 2);
4758   CONVERT_ARG_CHECKED(String, key, 1);
4759 
4760   uint32_t index;
4761   const bool key_is_array_index = key->AsArrayIndex(&index);
4762 
4763   Object* obj = args[0];
4764   // Only JS objects can have properties.
4765   if (obj->IsJSObject()) {
4766     JSObject* object = JSObject::cast(obj);
4767     // Fast case: either the key is a real named property or it is not
4768     // an array index and there are no interceptors or hidden
4769     // prototypes.
4770     if (object->HasRealNamedProperty(key)) return isolate->heap()->true_value();
4771     Map* map = object->map();
4772     if (!key_is_array_index &&
4773         !map->has_named_interceptor() &&
4774         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
4775       return isolate->heap()->false_value();
4776     }
4777     // Slow case.
4778     HandleScope scope(isolate);
4779     return HasLocalPropertyImplementation(isolate,
4780                                           Handle<JSObject>(object),
4781                                           Handle<String>(key));
4782   } else if (obj->IsString() && key_is_array_index) {
4783     // Well, there is one exception:  Handle [] on strings.
4784     String* string = String::cast(obj);
4785     if (index < static_cast<uint32_t>(string->length())) {
4786       return isolate->heap()->true_value();
4787     }
4788   }
4789   return isolate->heap()->false_value();
4790 }
4791 
4792 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasProperty)4793 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
4794   NoHandleAllocation na;
4795   ASSERT(args.length() == 2);
4796   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4797   CONVERT_ARG_CHECKED(String, key, 1);
4798 
4799   bool result = receiver->HasProperty(key);
4800   if (isolate->has_pending_exception()) return Failure::Exception();
4801   return isolate->heap()->ToBoolean(result);
4802 }
4803 
4804 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasElement)4805 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
4806   NoHandleAllocation na;
4807   ASSERT(args.length() == 2);
4808   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4809   CONVERT_SMI_ARG_CHECKED(index, 1);
4810 
4811   bool result = receiver->HasElement(index);
4812   if (isolate->has_pending_exception()) return Failure::Exception();
4813   return isolate->heap()->ToBoolean(result);
4814 }
4815 
4816 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsPropertyEnumerable)4817 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
4818   NoHandleAllocation ha;
4819   ASSERT(args.length() == 2);
4820 
4821   CONVERT_ARG_CHECKED(JSObject, object, 0);
4822   CONVERT_ARG_CHECKED(String, key, 1);
4823 
4824   uint32_t index;
4825   if (key->AsArrayIndex(&index)) {
4826     JSObject::LocalElementType type = object->HasLocalElement(index);
4827     switch (type) {
4828       case JSObject::UNDEFINED_ELEMENT:
4829       case JSObject::STRING_CHARACTER_ELEMENT:
4830         return isolate->heap()->false_value();
4831       case JSObject::INTERCEPTED_ELEMENT:
4832       case JSObject::FAST_ELEMENT:
4833         return isolate->heap()->true_value();
4834       case JSObject::DICTIONARY_ELEMENT: {
4835         if (object->IsJSGlobalProxy()) {
4836           Object* proto = object->GetPrototype();
4837           if (proto->IsNull()) {
4838             return isolate->heap()->false_value();
4839           }
4840           ASSERT(proto->IsJSGlobalObject());
4841           object = JSObject::cast(proto);
4842         }
4843         FixedArray* elements = FixedArray::cast(object->elements());
4844         SeededNumberDictionary* dictionary = NULL;
4845         if (elements->map() ==
4846             isolate->heap()->non_strict_arguments_elements_map()) {
4847           dictionary = SeededNumberDictionary::cast(elements->get(1));
4848         } else {
4849           dictionary = SeededNumberDictionary::cast(elements);
4850         }
4851         int entry = dictionary->FindEntry(index);
4852         ASSERT(entry != SeededNumberDictionary::kNotFound);
4853         PropertyDetails details = dictionary->DetailsAt(entry);
4854         return isolate->heap()->ToBoolean(!details.IsDontEnum());
4855       }
4856     }
4857   }
4858 
4859   PropertyAttributes att = object->GetLocalPropertyAttribute(key);
4860   return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
4861 }
4862 
4863 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPropertyNames)4864 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
4865   HandleScope scope(isolate);
4866   ASSERT(args.length() == 1);
4867   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
4868   bool threw = false;
4869   Handle<JSArray> result = GetKeysFor(object, &threw);
4870   if (threw) return Failure::Exception();
4871   return *result;
4872 }
4873 
4874 
4875 // Returns either a FixedArray as Runtime_GetPropertyNames,
4876 // or, if the given object has an enum cache that contains
4877 // all enumerable properties of the object and its prototypes
4878 // have none, the map of the object. This is used to speed up
4879 // the check for deletions during a for-in.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPropertyNamesFast)4880 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
4881   ASSERT(args.length() == 1);
4882 
4883   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
4884 
4885   if (raw_object->IsSimpleEnum()) return raw_object->map();
4886 
4887   HandleScope scope(isolate);
4888   Handle<JSReceiver> object(raw_object);
4889   bool threw = false;
4890   Handle<FixedArray> content =
4891       GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
4892   if (threw) return Failure::Exception();
4893 
4894   // Test again, since cache may have been built by preceding call.
4895   if (object->IsSimpleEnum()) return object->map();
4896 
4897   return *content;
4898 }
4899 
4900 
4901 // Find the length of the prototype chain that is to to handled as one. If a
4902 // prototype object is hidden it is to be viewed as part of the the object it
4903 // is prototype for.
LocalPrototypeChainLength(JSObject * obj)4904 static int LocalPrototypeChainLength(JSObject* obj) {
4905   int count = 1;
4906   Object* proto = obj->GetPrototype();
4907   while (proto->IsJSObject() &&
4908          JSObject::cast(proto)->map()->is_hidden_prototype()) {
4909     count++;
4910     proto = JSObject::cast(proto)->GetPrototype();
4911   }
4912   return count;
4913 }
4914 
4915 
4916 // Return the names of the local named properties.
4917 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLocalPropertyNames)4918 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
4919   HandleScope scope(isolate);
4920   ASSERT(args.length() == 1);
4921   if (!args[0]->IsJSObject()) {
4922     return isolate->heap()->undefined_value();
4923   }
4924   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4925 
4926   // Skip the global proxy as it has no properties and always delegates to the
4927   // real global object.
4928   if (obj->IsJSGlobalProxy()) {
4929     // Only collect names if access is permitted.
4930     if (obj->IsAccessCheckNeeded() &&
4931         !isolate->MayNamedAccess(*obj,
4932                                  isolate->heap()->undefined_value(),
4933                                  v8::ACCESS_KEYS)) {
4934       isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
4935       return *isolate->factory()->NewJSArray(0);
4936     }
4937     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
4938   }
4939 
4940   // Find the number of objects making up this.
4941   int length = LocalPrototypeChainLength(*obj);
4942 
4943   // Find the number of local properties for each of the objects.
4944   ScopedVector<int> local_property_count(length);
4945   int total_property_count = 0;
4946   Handle<JSObject> jsproto = obj;
4947   for (int i = 0; i < length; i++) {
4948     // Only collect names if access is permitted.
4949     if (jsproto->IsAccessCheckNeeded() &&
4950         !isolate->MayNamedAccess(*jsproto,
4951                                  isolate->heap()->undefined_value(),
4952                                  v8::ACCESS_KEYS)) {
4953       isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
4954       return *isolate->factory()->NewJSArray(0);
4955     }
4956     int n;
4957     n = jsproto->NumberOfLocalProperties();
4958     local_property_count[i] = n;
4959     total_property_count += n;
4960     if (i < length - 1) {
4961       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4962     }
4963   }
4964 
4965   // Allocate an array with storage for all the property names.
4966   Handle<FixedArray> names =
4967       isolate->factory()->NewFixedArray(total_property_count);
4968 
4969   // Get the property names.
4970   jsproto = obj;
4971   int proto_with_hidden_properties = 0;
4972   int next_copy_index = 0;
4973   for (int i = 0; i < length; i++) {
4974     jsproto->GetLocalPropertyNames(*names, next_copy_index);
4975     next_copy_index += local_property_count[i];
4976     if (jsproto->HasHiddenProperties()) {
4977       proto_with_hidden_properties++;
4978     }
4979     if (i < length - 1) {
4980       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4981     }
4982   }
4983 
4984   // Filter out name of hidden propeties object.
4985   if (proto_with_hidden_properties > 0) {
4986     Handle<FixedArray> old_names = names;
4987     names = isolate->factory()->NewFixedArray(
4988         names->length() - proto_with_hidden_properties);
4989     int dest_pos = 0;
4990     for (int i = 0; i < total_property_count; i++) {
4991       Object* name = old_names->get(i);
4992       if (name == isolate->heap()->hidden_symbol()) {
4993         continue;
4994       }
4995       names->set(dest_pos++, name);
4996     }
4997   }
4998 
4999   return *isolate->factory()->NewJSArrayWithElements(names);
5000 }
5001 
5002 
5003 // Return the names of the local indexed properties.
5004 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLocalElementNames)5005 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5006   HandleScope scope(isolate);
5007   ASSERT(args.length() == 1);
5008   if (!args[0]->IsJSObject()) {
5009     return isolate->heap()->undefined_value();
5010   }
5011   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5012 
5013   int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5014   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5015   obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5016   return *isolate->factory()->NewJSArrayWithElements(names);
5017 }
5018 
5019 
5020 // Return information on whether an object has a named or indexed interceptor.
5021 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetInterceptorInfo)5022 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5023   HandleScope scope(isolate);
5024   ASSERT(args.length() == 1);
5025   if (!args[0]->IsJSObject()) {
5026     return Smi::FromInt(0);
5027   }
5028   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5029 
5030   int result = 0;
5031   if (obj->HasNamedInterceptor()) result |= 2;
5032   if (obj->HasIndexedInterceptor()) result |= 1;
5033 
5034   return Smi::FromInt(result);
5035 }
5036 
5037 
5038 // Return property names from named interceptor.
5039 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetNamedInterceptorPropertyNames)5040 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5041   HandleScope scope(isolate);
5042   ASSERT(args.length() == 1);
5043   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5044 
5045   if (obj->HasNamedInterceptor()) {
5046     v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5047     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5048   }
5049   return isolate->heap()->undefined_value();
5050 }
5051 
5052 
5053 // Return element names from indexed interceptor.
5054 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetIndexedInterceptorElementNames)5055 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5056   HandleScope scope(isolate);
5057   ASSERT(args.length() == 1);
5058   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5059 
5060   if (obj->HasIndexedInterceptor()) {
5061     v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5062     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5063   }
5064   return isolate->heap()->undefined_value();
5065 }
5066 
5067 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LocalKeys)5068 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5069   ASSERT_EQ(args.length(), 1);
5070   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5071   HandleScope scope(isolate);
5072   Handle<JSObject> object(raw_object);
5073 
5074   if (object->IsJSGlobalProxy()) {
5075     // Do access checks before going to the global object.
5076     if (object->IsAccessCheckNeeded() &&
5077         !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5078                              v8::ACCESS_KEYS)) {
5079       isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5080       return *isolate->factory()->NewJSArray(0);
5081     }
5082 
5083     Handle<Object> proto(object->GetPrototype());
5084     // If proxy is detached we simply return an empty array.
5085     if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5086     object = Handle<JSObject>::cast(proto);
5087   }
5088 
5089   bool threw = false;
5090   Handle<FixedArray> contents =
5091       GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5092   if (threw) return Failure::Exception();
5093 
5094   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5095   // property array and since the result is mutable we have to create
5096   // a fresh clone on each invocation.
5097   int length = contents->length();
5098   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5099   for (int i = 0; i < length; i++) {
5100     Object* entry = contents->get(i);
5101     if (entry->IsString()) {
5102       copy->set(i, entry);
5103     } else {
5104       ASSERT(entry->IsNumber());
5105       HandleScope scope(isolate);
5106       Handle<Object> entry_handle(entry, isolate);
5107       Handle<Object> entry_str =
5108           isolate->factory()->NumberToString(entry_handle);
5109       copy->set(i, *entry_str);
5110     }
5111   }
5112   return *isolate->factory()->NewJSArrayWithElements(copy);
5113 }
5114 
5115 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetArgumentsProperty)5116 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5117   NoHandleAllocation ha;
5118   ASSERT(args.length() == 1);
5119 
5120   // Compute the frame holding the arguments.
5121   JavaScriptFrameIterator it(isolate);
5122   it.AdvanceToArgumentsFrame();
5123   JavaScriptFrame* frame = it.frame();
5124 
5125   // Get the actual number of provided arguments.
5126   const uint32_t n = frame->ComputeParametersCount();
5127 
5128   // Try to convert the key to an index. If successful and within
5129   // index return the the argument from the frame.
5130   uint32_t index;
5131   if (args[0]->ToArrayIndex(&index) && index < n) {
5132     return frame->GetParameter(index);
5133   }
5134 
5135   // Convert the key to a string.
5136   HandleScope scope(isolate);
5137   bool exception = false;
5138   Handle<Object> converted =
5139       Execution::ToString(args.at<Object>(0), &exception);
5140   if (exception) return Failure::Exception();
5141   Handle<String> key = Handle<String>::cast(converted);
5142 
5143   // Try to convert the string key into an array index.
5144   if (key->AsArrayIndex(&index)) {
5145     if (index < n) {
5146       return frame->GetParameter(index);
5147     } else {
5148       return isolate->initial_object_prototype()->GetElement(index);
5149     }
5150   }
5151 
5152   // Handle special arguments properties.
5153   if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
5154   if (key->Equals(isolate->heap()->callee_symbol())) {
5155     Object* function = frame->function();
5156     if (function->IsJSFunction() &&
5157         !JSFunction::cast(function)->shared()->is_classic_mode()) {
5158       return isolate->Throw(*isolate->factory()->NewTypeError(
5159           "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5160     }
5161     return function;
5162   }
5163 
5164   // Lookup in the initial Object.prototype object.
5165   return isolate->initial_object_prototype()->GetProperty(*key);
5166 }
5167 
5168 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToFastProperties)5169 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5170   ASSERT(args.length() == 1);
5171   Object* object = args[0];
5172   return (object->IsJSObject() && !object->IsGlobalObject())
5173       ? JSObject::cast(object)->TransformToFastProperties(0)
5174       : object;
5175 }
5176 
5177 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToSlowProperties)5178 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToSlowProperties) {
5179   ASSERT(args.length() == 1);
5180   Object* obj = args[0];
5181   return (obj->IsJSObject() && !obj->IsJSGlobalProxy())
5182       ? JSObject::cast(obj)->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0)
5183       : obj;
5184 }
5185 
5186 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToBool)5187 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5188   NoHandleAllocation ha;
5189   ASSERT(args.length() == 1);
5190 
5191   return args[0]->ToBoolean();
5192 }
5193 
5194 
5195 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
5196 // Possible optimizations: put the type string into the oddballs.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Typeof)5197 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
5198   NoHandleAllocation ha;
5199 
5200   Object* obj = args[0];
5201   if (obj->IsNumber()) return isolate->heap()->number_symbol();
5202   HeapObject* heap_obj = HeapObject::cast(obj);
5203 
5204   // typeof an undetectable object is 'undefined'
5205   if (heap_obj->map()->is_undetectable()) {
5206     return isolate->heap()->undefined_symbol();
5207   }
5208 
5209   InstanceType instance_type = heap_obj->map()->instance_type();
5210   if (instance_type < FIRST_NONSTRING_TYPE) {
5211     return isolate->heap()->string_symbol();
5212   }
5213 
5214   switch (instance_type) {
5215     case ODDBALL_TYPE:
5216       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
5217         return isolate->heap()->boolean_symbol();
5218       }
5219       if (heap_obj->IsNull()) {
5220         return FLAG_harmony_typeof
5221             ? isolate->heap()->null_symbol()
5222             : isolate->heap()->object_symbol();
5223       }
5224       ASSERT(heap_obj->IsUndefined());
5225       return isolate->heap()->undefined_symbol();
5226     case JS_FUNCTION_TYPE:
5227     case JS_FUNCTION_PROXY_TYPE:
5228       return isolate->heap()->function_symbol();
5229     default:
5230       // For any kind of object not handled above, the spec rule for
5231       // host objects gives that it is okay to return "object"
5232       return isolate->heap()->object_symbol();
5233   }
5234 }
5235 
5236 
AreDigits(const char * s,int from,int to)5237 static bool AreDigits(const char*s, int from, int to) {
5238   for (int i = from; i < to; i++) {
5239     if (s[i] < '0' || s[i] > '9') return false;
5240   }
5241 
5242   return true;
5243 }
5244 
5245 
ParseDecimalInteger(const char * s,int from,int to)5246 static int ParseDecimalInteger(const char*s, int from, int to) {
5247   ASSERT(to - from < 10);  // Overflow is not possible.
5248   ASSERT(from < to);
5249   int d = s[from] - '0';
5250 
5251   for (int i = from + 1; i < to; i++) {
5252     d = 10 * d + (s[i] - '0');
5253   }
5254 
5255   return d;
5256 }
5257 
5258 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToNumber)5259 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
5260   NoHandleAllocation ha;
5261   ASSERT(args.length() == 1);
5262   CONVERT_ARG_CHECKED(String, subject, 0);
5263   subject->TryFlatten();
5264 
5265   // Fast case: short integer or some sorts of junk values.
5266   int len = subject->length();
5267   if (subject->IsSeqAsciiString()) {
5268     if (len == 0) return Smi::FromInt(0);
5269 
5270     char const* data = SeqAsciiString::cast(subject)->GetChars();
5271     bool minus = (data[0] == '-');
5272     int start_pos = (minus ? 1 : 0);
5273 
5274     if (start_pos == len) {
5275       return isolate->heap()->nan_value();
5276     } else if (data[start_pos] > '9') {
5277       // Fast check for a junk value. A valid string may start from a
5278       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
5279       // the 'I' character ('Infinity'). All of that have codes not greater than
5280       // '9' except 'I'.
5281       if (data[start_pos] != 'I') {
5282         return isolate->heap()->nan_value();
5283       }
5284     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
5285       // The maximal/minimal smi has 10 digits. If the string has less digits we
5286       // know it will fit into the smi-data type.
5287       int d = ParseDecimalInteger(data, start_pos, len);
5288       if (minus) {
5289         if (d == 0) return isolate->heap()->minus_zero_value();
5290         d = -d;
5291       } else if (!subject->HasHashCode() &&
5292                  len <= String::kMaxArrayIndexSize &&
5293                  (len == 1 || data[0] != '0')) {
5294         // String hash is not calculated yet but all the data are present.
5295         // Update the hash field to speed up sequential convertions.
5296         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
5297 #ifdef DEBUG
5298         subject->Hash();  // Force hash calculation.
5299         ASSERT_EQ(static_cast<int>(subject->hash_field()),
5300                   static_cast<int>(hash));
5301 #endif
5302         subject->set_hash_field(hash);
5303       }
5304       return Smi::FromInt(d);
5305     }
5306   }
5307 
5308   // Slower case.
5309   return isolate->heap()->NumberFromDouble(
5310       StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
5311 }
5312 
5313 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringFromCharCodeArray)5314 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringFromCharCodeArray) {
5315   NoHandleAllocation ha;
5316   ASSERT(args.length() == 1);
5317 
5318   CONVERT_ARG_CHECKED(JSArray, codes, 0);
5319   int length = Smi::cast(codes->length())->value();
5320 
5321   // Check if the string can be ASCII.
5322   int i;
5323   for (i = 0; i < length; i++) {
5324     Object* element;
5325     { MaybeObject* maybe_element = codes->GetElement(i);
5326       // We probably can't get an exception here, but just in order to enforce
5327       // the checking of inputs in the runtime calls we check here.
5328       if (!maybe_element->ToObject(&element)) return maybe_element;
5329     }
5330     CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5331     if ((chr & 0xffff) > String::kMaxAsciiCharCode)
5332       break;
5333   }
5334 
5335   MaybeObject* maybe_object = NULL;
5336   if (i == length) {  // The string is ASCII.
5337     maybe_object = isolate->heap()->AllocateRawAsciiString(length);
5338   } else {  // The string is not ASCII.
5339     maybe_object = isolate->heap()->AllocateRawTwoByteString(length);
5340   }
5341 
5342   Object* object = NULL;
5343   if (!maybe_object->ToObject(&object)) return maybe_object;
5344   String* result = String::cast(object);
5345   for (int i = 0; i < length; i++) {
5346     Object* element;
5347     { MaybeObject* maybe_element = codes->GetElement(i);
5348       if (!maybe_element->ToObject(&element)) return maybe_element;
5349     }
5350     CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5351     result->Set(i, chr & 0xffff);
5352   }
5353   return result;
5354 }
5355 
5356 
5357 // kNotEscaped is generated by the following:
5358 //
5359 // #!/bin/perl
5360 // for (my $i = 0; $i < 256; $i++) {
5361 //   print "\n" if $i % 16 == 0;
5362 //   my $c = chr($i);
5363 //   my $escaped = 1;
5364 //   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
5365 //   print $escaped ? "0, " : "1, ";
5366 // }
5367 
5368 
IsNotEscaped(uint16_t character)5369 static bool IsNotEscaped(uint16_t character) {
5370   // Only for 8 bit characters, the rest are always escaped (in a different way)
5371   ASSERT(character < 256);
5372   static const char kNotEscaped[256] = {
5373     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5374     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5375     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
5376     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
5377     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5378     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
5379     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5380     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
5381     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5382     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5383     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5384     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5385     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5386     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5387     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5388     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5389   };
5390   return kNotEscaped[character] != 0;
5391 }
5392 
5393 
RUNTIME_FUNCTION(MaybeObject *,Runtime_URIEscape)5394 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
5395   const char hex_chars[] = "0123456789ABCDEF";
5396   NoHandleAllocation ha;
5397   ASSERT(args.length() == 1);
5398   CONVERT_ARG_CHECKED(String, source, 0);
5399 
5400   source->TryFlatten();
5401 
5402   int escaped_length = 0;
5403   int length = source->length();
5404   {
5405     Access<StringInputBuffer> buffer(
5406         isolate->runtime_state()->string_input_buffer());
5407     buffer->Reset(source);
5408     while (buffer->has_more()) {
5409       uint16_t character = buffer->GetNext();
5410       if (character >= 256) {
5411         escaped_length += 6;
5412       } else if (IsNotEscaped(character)) {
5413         escaped_length++;
5414       } else {
5415         escaped_length += 3;
5416       }
5417       // We don't allow strings that are longer than a maximal length.
5418       ASSERT(String::kMaxLength < 0x7fffffff - 6);  // Cannot overflow.
5419       if (escaped_length > String::kMaxLength) {
5420         isolate->context()->mark_out_of_memory();
5421         return Failure::OutOfMemoryException();
5422       }
5423     }
5424   }
5425   // No length change implies no change.  Return original string if no change.
5426   if (escaped_length == length) {
5427     return source;
5428   }
5429   Object* o;
5430   { MaybeObject* maybe_o =
5431         isolate->heap()->AllocateRawAsciiString(escaped_length);
5432     if (!maybe_o->ToObject(&o)) return maybe_o;
5433   }
5434   String* destination = String::cast(o);
5435   int dest_position = 0;
5436 
5437   Access<StringInputBuffer> buffer(
5438       isolate->runtime_state()->string_input_buffer());
5439   buffer->Rewind();
5440   while (buffer->has_more()) {
5441     uint16_t chr = buffer->GetNext();
5442     if (chr >= 256) {
5443       destination->Set(dest_position, '%');
5444       destination->Set(dest_position+1, 'u');
5445       destination->Set(dest_position+2, hex_chars[chr >> 12]);
5446       destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
5447       destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
5448       destination->Set(dest_position+5, hex_chars[chr & 0xf]);
5449       dest_position += 6;
5450     } else if (IsNotEscaped(chr)) {
5451       destination->Set(dest_position, chr);
5452       dest_position++;
5453     } else {
5454       destination->Set(dest_position, '%');
5455       destination->Set(dest_position+1, hex_chars[chr >> 4]);
5456       destination->Set(dest_position+2, hex_chars[chr & 0xf]);
5457       dest_position += 3;
5458     }
5459   }
5460   return destination;
5461 }
5462 
5463 
TwoDigitHex(uint16_t character1,uint16_t character2)5464 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
5465   static const signed char kHexValue['g'] = {
5466     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5467     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5468     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5469     0,  1,  2,   3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
5470     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5471     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5472     -1, 10, 11, 12, 13, 14, 15 };
5473 
5474   if (character1 > 'f') return -1;
5475   int hi = kHexValue[character1];
5476   if (hi == -1) return -1;
5477   if (character2 > 'f') return -1;
5478   int lo = kHexValue[character2];
5479   if (lo == -1) return -1;
5480   return (hi << 4) + lo;
5481 }
5482 
5483 
Unescape(String * source,int i,int length,int * step)5484 static inline int Unescape(String* source,
5485                            int i,
5486                            int length,
5487                            int* step) {
5488   uint16_t character = source->Get(i);
5489   int32_t hi = 0;
5490   int32_t lo = 0;
5491   if (character == '%' &&
5492       i <= length - 6 &&
5493       source->Get(i + 1) == 'u' &&
5494       (hi = TwoDigitHex(source->Get(i + 2),
5495                         source->Get(i + 3))) != -1 &&
5496       (lo = TwoDigitHex(source->Get(i + 4),
5497                         source->Get(i + 5))) != -1) {
5498     *step = 6;
5499     return (hi << 8) + lo;
5500   } else if (character == '%' &&
5501       i <= length - 3 &&
5502       (lo = TwoDigitHex(source->Get(i + 1),
5503                         source->Get(i + 2))) != -1) {
5504     *step = 3;
5505     return lo;
5506   } else {
5507     *step = 1;
5508     return character;
5509   }
5510 }
5511 
5512 
RUNTIME_FUNCTION(MaybeObject *,Runtime_URIUnescape)5513 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
5514   NoHandleAllocation ha;
5515   ASSERT(args.length() == 1);
5516   CONVERT_ARG_CHECKED(String, source, 0);
5517 
5518   source->TryFlatten();
5519 
5520   bool ascii = true;
5521   int length = source->length();
5522 
5523   int unescaped_length = 0;
5524   for (int i = 0; i < length; unescaped_length++) {
5525     int step;
5526     if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
5527       ascii = false;
5528     }
5529     i += step;
5530   }
5531 
5532   // No length change implies no change.  Return original string if no change.
5533   if (unescaped_length == length)
5534     return source;
5535 
5536   Object* o;
5537   { MaybeObject* maybe_o =
5538         ascii ?
5539         isolate->heap()->AllocateRawAsciiString(unescaped_length) :
5540         isolate->heap()->AllocateRawTwoByteString(unescaped_length);
5541     if (!maybe_o->ToObject(&o)) return maybe_o;
5542   }
5543   String* destination = String::cast(o);
5544 
5545   int dest_position = 0;
5546   for (int i = 0; i < length; dest_position++) {
5547     int step;
5548     destination->Set(dest_position, Unescape(source, i, length, &step));
5549     i += step;
5550   }
5551   return destination;
5552 }
5553 
5554 
5555 static const unsigned int kQuoteTableLength = 128u;
5556 
5557 static const int kJsonQuotesCharactersPerEntry = 8;
5558 static const char* const JsonQuotes =
5559     "\\u0000  \\u0001  \\u0002  \\u0003  "
5560     "\\u0004  \\u0005  \\u0006  \\u0007  "
5561     "\\b      \\t      \\n      \\u000b  "
5562     "\\f      \\r      \\u000e  \\u000f  "
5563     "\\u0010  \\u0011  \\u0012  \\u0013  "
5564     "\\u0014  \\u0015  \\u0016  \\u0017  "
5565     "\\u0018  \\u0019  \\u001a  \\u001b  "
5566     "\\u001c  \\u001d  \\u001e  \\u001f  "
5567     "        !       \\\"      #       "
5568     "$       %       &       '       "
5569     "(       )       *       +       "
5570     ",       -       .       /       "
5571     "0       1       2       3       "
5572     "4       5       6       7       "
5573     "8       9       :       ;       "
5574     "<       =       >       ?       "
5575     "@       A       B       C       "
5576     "D       E       F       G       "
5577     "H       I       J       K       "
5578     "L       M       N       O       "
5579     "P       Q       R       S       "
5580     "T       U       V       W       "
5581     "X       Y       Z       [       "
5582     "\\\\      ]       ^       _       "
5583     "`       a       b       c       "
5584     "d       e       f       g       "
5585     "h       i       j       k       "
5586     "l       m       n       o       "
5587     "p       q       r       s       "
5588     "t       u       v       w       "
5589     "x       y       z       {       "
5590     "|       }       ~       \177       ";
5591 
5592 
5593 // For a string that is less than 32k characters it should always be
5594 // possible to allocate it in new space.
5595 static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
5596 
5597 
5598 // Doing JSON quoting cannot make the string more than this many times larger.
5599 static const int kJsonQuoteWorstCaseBlowup = 6;
5600 
5601 static const int kSpaceForQuotesAndComma = 3;
5602 static const int kSpaceForBrackets = 2;
5603 
5604 // Covers the entire ASCII range (all other characters are unchanged by JSON
5605 // quoting).
5606 static const byte JsonQuoteLengths[kQuoteTableLength] = {
5607     6, 6, 6, 6, 6, 6, 6, 6,
5608     2, 2, 2, 6, 2, 2, 6, 6,
5609     6, 6, 6, 6, 6, 6, 6, 6,
5610     6, 6, 6, 6, 6, 6, 6, 6,
5611     1, 1, 2, 1, 1, 1, 1, 1,
5612     1, 1, 1, 1, 1, 1, 1, 1,
5613     1, 1, 1, 1, 1, 1, 1, 1,
5614     1, 1, 1, 1, 1, 1, 1, 1,
5615     1, 1, 1, 1, 1, 1, 1, 1,
5616     1, 1, 1, 1, 1, 1, 1, 1,
5617     1, 1, 1, 1, 1, 1, 1, 1,
5618     1, 1, 1, 1, 2, 1, 1, 1,
5619     1, 1, 1, 1, 1, 1, 1, 1,
5620     1, 1, 1, 1, 1, 1, 1, 1,
5621     1, 1, 1, 1, 1, 1, 1, 1,
5622     1, 1, 1, 1, 1, 1, 1, 1,
5623 };
5624 
5625 
5626 template <typename StringType>
5627 MaybeObject* AllocateRawString(Isolate* isolate, int length);
5628 
5629 
5630 template <>
AllocateRawString(Isolate * isolate,int length)5631 MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
5632   return isolate->heap()->AllocateRawTwoByteString(length);
5633 }
5634 
5635 
5636 template <>
AllocateRawString(Isolate * isolate,int length)5637 MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) {
5638   return isolate->heap()->AllocateRawAsciiString(length);
5639 }
5640 
5641 
5642 template <typename Char, typename StringType, bool comma>
SlowQuoteJsonString(Isolate * isolate,Vector<const Char> characters)5643 static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
5644                                         Vector<const Char> characters) {
5645   int length = characters.length();
5646   const Char* read_cursor = characters.start();
5647   const Char* end = read_cursor + length;
5648   const int kSpaceForQuotes = 2 + (comma ? 1 :0);
5649   int quoted_length = kSpaceForQuotes;
5650   while (read_cursor < end) {
5651     Char c = *(read_cursor++);
5652     if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5653       quoted_length++;
5654     } else {
5655       quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
5656     }
5657   }
5658   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5659                                                          quoted_length);
5660   Object* new_object;
5661   if (!new_alloc->ToObject(&new_object)) {
5662     return new_alloc;
5663   }
5664   StringType* new_string = StringType::cast(new_object);
5665 
5666   Char* write_cursor = reinterpret_cast<Char*>(
5667       new_string->address() + SeqString::kHeaderSize);
5668   if (comma) *(write_cursor++) = ',';
5669   *(write_cursor++) = '"';
5670 
5671   read_cursor = characters.start();
5672   while (read_cursor < end) {
5673     Char c = *(read_cursor++);
5674     if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5675       *(write_cursor++) = c;
5676     } else {
5677       int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5678       const char* replacement = JsonQuotes +
5679           static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5680       for (int i = 0; i < len; i++) {
5681         *write_cursor++ = *replacement++;
5682       }
5683     }
5684   }
5685   *(write_cursor++) = '"';
5686   return new_string;
5687 }
5688 
5689 
5690 template <typename SinkChar, typename SourceChar>
WriteQuoteJsonString(Isolate * isolate,SinkChar * write_cursor,Vector<const SourceChar> characters)5691 static inline SinkChar* WriteQuoteJsonString(
5692     Isolate* isolate,
5693     SinkChar* write_cursor,
5694     Vector<const SourceChar> characters) {
5695   // SinkChar is only char if SourceChar is guaranteed to be char.
5696   ASSERT(sizeof(SinkChar) >= sizeof(SourceChar));
5697   const SourceChar* read_cursor = characters.start();
5698   const SourceChar* end = read_cursor + characters.length();
5699   *(write_cursor++) = '"';
5700   while (read_cursor < end) {
5701     SourceChar c = *(read_cursor++);
5702     if (sizeof(SourceChar) > 1u &&
5703         static_cast<unsigned>(c) >= kQuoteTableLength) {
5704       *(write_cursor++) = static_cast<SinkChar>(c);
5705     } else {
5706       int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5707       const char* replacement = JsonQuotes +
5708           static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5709       write_cursor[0] = replacement[0];
5710       if (len > 1) {
5711         write_cursor[1] = replacement[1];
5712         if (len > 2) {
5713           ASSERT(len == 6);
5714           write_cursor[2] = replacement[2];
5715           write_cursor[3] = replacement[3];
5716           write_cursor[4] = replacement[4];
5717           write_cursor[5] = replacement[5];
5718         }
5719       }
5720       write_cursor += len;
5721     }
5722   }
5723   *(write_cursor++) = '"';
5724   return write_cursor;
5725 }
5726 
5727 
5728 template <typename Char, typename StringType, bool comma>
QuoteJsonString(Isolate * isolate,Vector<const Char> characters)5729 static MaybeObject* QuoteJsonString(Isolate* isolate,
5730                                     Vector<const Char> characters) {
5731   int length = characters.length();
5732   isolate->counters()->quote_json_char_count()->Increment(length);
5733   int worst_case_length =
5734         length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
5735   if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5736     return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5737   }
5738 
5739   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5740                                                          worst_case_length);
5741   Object* new_object;
5742   if (!new_alloc->ToObject(&new_object)) {
5743     return new_alloc;
5744   }
5745   if (!isolate->heap()->new_space()->Contains(new_object)) {
5746     // Even if our string is small enough to fit in new space we still have to
5747     // handle it being allocated in old space as may happen in the third
5748     // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
5749     // CEntryStub::GenerateCore.
5750     return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5751   }
5752   StringType* new_string = StringType::cast(new_object);
5753   ASSERT(isolate->heap()->new_space()->Contains(new_string));
5754 
5755   Char* write_cursor = reinterpret_cast<Char*>(
5756       new_string->address() + SeqString::kHeaderSize);
5757   if (comma) *(write_cursor++) = ',';
5758   write_cursor = WriteQuoteJsonString<Char, Char>(isolate,
5759                                                   write_cursor,
5760                                                   characters);
5761   int final_length = static_cast<int>(
5762       write_cursor - reinterpret_cast<Char*>(
5763           new_string->address() + SeqString::kHeaderSize));
5764   isolate->heap()->new_space()->
5765       template ShrinkStringAtAllocationBoundary<StringType>(
5766           new_string, final_length);
5767   return new_string;
5768 }
5769 
5770 
RUNTIME_FUNCTION(MaybeObject *,Runtime_QuoteJSONString)5771 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
5772   NoHandleAllocation ha;
5773   CONVERT_ARG_CHECKED(String, str, 0);
5774   if (!str->IsFlat()) {
5775     MaybeObject* try_flatten = str->TryFlatten();
5776     Object* flat;
5777     if (!try_flatten->ToObject(&flat)) {
5778       return try_flatten;
5779     }
5780     str = String::cast(flat);
5781     ASSERT(str->IsFlat());
5782   }
5783   String::FlatContent flat = str->GetFlatContent();
5784   ASSERT(flat.IsFlat());
5785   if (flat.IsTwoByte()) {
5786     return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
5787                                                           flat.ToUC16Vector());
5788   } else {
5789     return QuoteJsonString<char, SeqAsciiString, false>(isolate,
5790                                                         flat.ToAsciiVector());
5791   }
5792 }
5793 
5794 
RUNTIME_FUNCTION(MaybeObject *,Runtime_QuoteJSONStringComma)5795 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
5796   NoHandleAllocation ha;
5797   CONVERT_ARG_CHECKED(String, str, 0);
5798   if (!str->IsFlat()) {
5799     MaybeObject* try_flatten = str->TryFlatten();
5800     Object* flat;
5801     if (!try_flatten->ToObject(&flat)) {
5802       return try_flatten;
5803     }
5804     str = String::cast(flat);
5805     ASSERT(str->IsFlat());
5806   }
5807   String::FlatContent flat = str->GetFlatContent();
5808   if (flat.IsTwoByte()) {
5809     return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
5810                                                          flat.ToUC16Vector());
5811   } else {
5812     return QuoteJsonString<char, SeqAsciiString, true>(isolate,
5813                                                        flat.ToAsciiVector());
5814   }
5815 }
5816 
5817 
5818 template <typename Char, typename StringType>
QuoteJsonStringArray(Isolate * isolate,FixedArray * array,int worst_case_length)5819 static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
5820                                          FixedArray* array,
5821                                          int worst_case_length) {
5822   int length = array->length();
5823 
5824   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5825                                                          worst_case_length);
5826   Object* new_object;
5827   if (!new_alloc->ToObject(&new_object)) {
5828     return new_alloc;
5829   }
5830   if (!isolate->heap()->new_space()->Contains(new_object)) {
5831     // Even if our string is small enough to fit in new space we still have to
5832     // handle it being allocated in old space as may happen in the third
5833     // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
5834     // CEntryStub::GenerateCore.
5835     return isolate->heap()->undefined_value();
5836   }
5837   AssertNoAllocation no_gc;
5838   StringType* new_string = StringType::cast(new_object);
5839   ASSERT(isolate->heap()->new_space()->Contains(new_string));
5840 
5841   Char* write_cursor = reinterpret_cast<Char*>(
5842       new_string->address() + SeqString::kHeaderSize);
5843   *(write_cursor++) = '[';
5844   for (int i = 0; i < length; i++) {
5845     if (i != 0) *(write_cursor++) = ',';
5846     String* str = String::cast(array->get(i));
5847     String::FlatContent content = str->GetFlatContent();
5848     ASSERT(content.IsFlat());
5849     if (content.IsTwoByte()) {
5850       write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
5851                                                       write_cursor,
5852                                                       content.ToUC16Vector());
5853     } else {
5854       write_cursor = WriteQuoteJsonString<Char, char>(isolate,
5855                                                       write_cursor,
5856                                                       content.ToAsciiVector());
5857     }
5858   }
5859   *(write_cursor++) = ']';
5860 
5861   int final_length = static_cast<int>(
5862       write_cursor - reinterpret_cast<Char*>(
5863           new_string->address() + SeqString::kHeaderSize));
5864   isolate->heap()->new_space()->
5865       template ShrinkStringAtAllocationBoundary<StringType>(
5866           new_string, final_length);
5867   return new_string;
5868 }
5869 
5870 
RUNTIME_FUNCTION(MaybeObject *,Runtime_QuoteJSONStringArray)5871 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
5872   NoHandleAllocation ha;
5873   ASSERT(args.length() == 1);
5874   CONVERT_ARG_CHECKED(JSArray, array, 0);
5875 
5876   if (!array->HasFastElements()) return isolate->heap()->undefined_value();
5877   FixedArray* elements = FixedArray::cast(array->elements());
5878   int n = elements->length();
5879   bool ascii = true;
5880   int total_length = 0;
5881 
5882   for (int i = 0; i < n; i++) {
5883     Object* elt = elements->get(i);
5884     if (!elt->IsString()) return isolate->heap()->undefined_value();
5885     String* element = String::cast(elt);
5886     if (!element->IsFlat()) return isolate->heap()->undefined_value();
5887     total_length += element->length();
5888     if (ascii && element->IsTwoByteRepresentation()) {
5889       ascii = false;
5890     }
5891   }
5892 
5893   int worst_case_length =
5894       kSpaceForBrackets + n * kSpaceForQuotesAndComma
5895       + total_length * kJsonQuoteWorstCaseBlowup;
5896 
5897   if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5898     return isolate->heap()->undefined_value();
5899   }
5900 
5901   if (ascii) {
5902     return QuoteJsonStringArray<char, SeqAsciiString>(isolate,
5903                                                       elements,
5904                                                       worst_case_length);
5905   } else {
5906     return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
5907                                                         elements,
5908                                                         worst_case_length);
5909   }
5910 }
5911 
5912 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringParseInt)5913 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
5914   NoHandleAllocation ha;
5915 
5916   CONVERT_ARG_CHECKED(String, s, 0);
5917   CONVERT_SMI_ARG_CHECKED(radix, 1);
5918 
5919   s->TryFlatten();
5920 
5921   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
5922   double value = StringToInt(isolate->unicode_cache(), s, radix);
5923   return isolate->heap()->NumberFromDouble(value);
5924 }
5925 
5926 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringParseFloat)5927 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
5928   NoHandleAllocation ha;
5929   CONVERT_ARG_CHECKED(String, str, 0);
5930 
5931   // ECMA-262 section 15.1.2.3, empty string is NaN
5932   double value = StringToDouble(isolate->unicode_cache(),
5933                                 str, ALLOW_TRAILING_JUNK, OS::nan_value());
5934 
5935   // Create a number object from the value.
5936   return isolate->heap()->NumberFromDouble(value);
5937 }
5938 
5939 
5940 template <class Converter>
ConvertCaseHelper(Isolate * isolate,String * s,int length,int input_string_length,unibrow::Mapping<Converter,128> * mapping)5941 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
5942     Isolate* isolate,
5943     String* s,
5944     int length,
5945     int input_string_length,
5946     unibrow::Mapping<Converter, 128>* mapping) {
5947   // We try this twice, once with the assumption that the result is no longer
5948   // than the input and, if that assumption breaks, again with the exact
5949   // length.  This may not be pretty, but it is nicer than what was here before
5950   // and I hereby claim my vaffel-is.
5951   //
5952   // Allocate the resulting string.
5953   //
5954   // NOTE: This assumes that the upper/lower case of an ASCII
5955   // character is also ASCII.  This is currently the case, but it
5956   // might break in the future if we implement more context and locale
5957   // dependent upper/lower conversions.
5958   Object* o;
5959   { MaybeObject* maybe_o = s->IsAsciiRepresentation()
5960         ? isolate->heap()->AllocateRawAsciiString(length)
5961         : isolate->heap()->AllocateRawTwoByteString(length);
5962     if (!maybe_o->ToObject(&o)) return maybe_o;
5963   }
5964   String* result = String::cast(o);
5965   bool has_changed_character = false;
5966 
5967   // Convert all characters to upper case, assuming that they will fit
5968   // in the buffer
5969   Access<StringInputBuffer> buffer(
5970       isolate->runtime_state()->string_input_buffer());
5971   buffer->Reset(s);
5972   unibrow::uchar chars[Converter::kMaxWidth];
5973   // We can assume that the string is not empty
5974   uc32 current = buffer->GetNext();
5975   for (int i = 0; i < length;) {
5976     bool has_next = buffer->has_more();
5977     uc32 next = has_next ? buffer->GetNext() : 0;
5978     int char_length = mapping->get(current, next, chars);
5979     if (char_length == 0) {
5980       // The case conversion of this character is the character itself.
5981       result->Set(i, current);
5982       i++;
5983     } else if (char_length == 1) {
5984       // Common case: converting the letter resulted in one character.
5985       ASSERT(static_cast<uc32>(chars[0]) != current);
5986       result->Set(i, chars[0]);
5987       has_changed_character = true;
5988       i++;
5989     } else if (length == input_string_length) {
5990       // We've assumed that the result would be as long as the
5991       // input but here is a character that converts to several
5992       // characters.  No matter, we calculate the exact length
5993       // of the result and try the whole thing again.
5994       //
5995       // Note that this leaves room for optimization.  We could just
5996       // memcpy what we already have to the result string.  Also,
5997       // the result string is the last object allocated we could
5998       // "realloc" it and probably, in the vast majority of cases,
5999       // extend the existing string to be able to hold the full
6000       // result.
6001       int next_length = 0;
6002       if (has_next) {
6003         next_length = mapping->get(next, 0, chars);
6004         if (next_length == 0) next_length = 1;
6005       }
6006       int current_length = i + char_length + next_length;
6007       while (buffer->has_more()) {
6008         current = buffer->GetNext();
6009         // NOTE: we use 0 as the next character here because, while
6010         // the next character may affect what a character converts to,
6011         // it does not in any case affect the length of what it convert
6012         // to.
6013         int char_length = mapping->get(current, 0, chars);
6014         if (char_length == 0) char_length = 1;
6015         current_length += char_length;
6016         if (current_length > Smi::kMaxValue) {
6017           isolate->context()->mark_out_of_memory();
6018           return Failure::OutOfMemoryException();
6019         }
6020       }
6021       // Try again with the real length.
6022       return Smi::FromInt(current_length);
6023     } else {
6024       for (int j = 0; j < char_length; j++) {
6025         result->Set(i, chars[j]);
6026         i++;
6027       }
6028       has_changed_character = true;
6029     }
6030     current = next;
6031   }
6032   if (has_changed_character) {
6033     return result;
6034   } else {
6035     // If we didn't actually change anything in doing the conversion
6036     // we simple return the result and let the converted string
6037     // become garbage; there is no reason to keep two identical strings
6038     // alive.
6039     return s;
6040   }
6041 }
6042 
6043 
6044 namespace {
6045 
6046 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6047 
6048 
6049 // Given a word and two range boundaries returns a word with high bit
6050 // set in every byte iff the corresponding input byte was strictly in
6051 // the range (m, n). All the other bits in the result are cleared.
6052 // This function is only useful when it can be inlined and the
6053 // boundaries are statically known.
6054 // Requires: all bytes in the input word and the boundaries must be
6055 // ASCII (less than 0x7F).
AsciiRangeMask(uintptr_t w,char m,char n)6056 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6057   // Every byte in an ASCII string is less than or equal to 0x7F.
6058   ASSERT((w & (kOneInEveryByte * 0x7F)) == w);
6059   // Use strict inequalities since in edge cases the function could be
6060   // further simplified.
6061   ASSERT(0 < m && m < n && n < 0x7F);
6062   // Has high bit set in every w byte less than n.
6063   uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6064   // Has high bit set in every w byte greater than m.
6065   uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6066   return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6067 }
6068 
6069 
6070 enum AsciiCaseConversion {
6071   ASCII_TO_LOWER,
6072   ASCII_TO_UPPER
6073 };
6074 
6075 
6076 template <AsciiCaseConversion dir>
6077 struct FastAsciiConverter {
Convertv8::internal::__anonc05715030111::FastAsciiConverter6078   static bool Convert(char* dst, char* src, int length) {
6079 #ifdef DEBUG
6080     char* saved_dst = dst;
6081     char* saved_src = src;
6082 #endif
6083     // We rely on the distance between upper and lower case letters
6084     // being a known power of 2.
6085     ASSERT('a' - 'A' == (1 << 5));
6086     // Boundaries for the range of input characters than require conversion.
6087     const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
6088     const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
6089     bool changed = false;
6090     char* const limit = src + length;
6091 #ifdef V8_HOST_CAN_READ_UNALIGNED
6092     // Process the prefix of the input that requires no conversion one
6093     // (machine) word at a time.
6094     while (src <= limit - sizeof(uintptr_t)) {
6095       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6096       if (AsciiRangeMask(w, lo, hi) != 0) {
6097         changed = true;
6098         break;
6099       }
6100       *reinterpret_cast<uintptr_t*>(dst) = w;
6101       src += sizeof(uintptr_t);
6102       dst += sizeof(uintptr_t);
6103     }
6104     // Process the remainder of the input performing conversion when
6105     // required one word at a time.
6106     while (src <= limit - sizeof(uintptr_t)) {
6107       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6108       uintptr_t m = AsciiRangeMask(w, lo, hi);
6109       // The mask has high (7th) bit set in every byte that needs
6110       // conversion and we know that the distance between cases is
6111       // 1 << 5.
6112       *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6113       src += sizeof(uintptr_t);
6114       dst += sizeof(uintptr_t);
6115     }
6116 #endif
6117     // Process the last few bytes of the input (or the whole input if
6118     // unaligned access is not supported).
6119     while (src < limit) {
6120       char c = *src;
6121       if (lo < c && c < hi) {
6122         c ^= (1 << 5);
6123         changed = true;
6124       }
6125       *dst = c;
6126       ++src;
6127       ++dst;
6128     }
6129 #ifdef DEBUG
6130     CheckConvert(saved_dst, saved_src, length, changed);
6131 #endif
6132     return changed;
6133   }
6134 
6135 #ifdef DEBUG
CheckConvertv8::internal::__anonc05715030111::FastAsciiConverter6136   static void CheckConvert(char* dst, char* src, int length, bool changed) {
6137     bool expected_changed = false;
6138     for (int i = 0; i < length; i++) {
6139       if (dst[i] == src[i]) continue;
6140       expected_changed = true;
6141       if (dir == ASCII_TO_LOWER) {
6142         ASSERT('A' <= src[i] && src[i] <= 'Z');
6143         ASSERT(dst[i] == src[i] + ('a' - 'A'));
6144       } else {
6145         ASSERT(dir == ASCII_TO_UPPER);
6146         ASSERT('a' <= src[i] && src[i] <= 'z');
6147         ASSERT(dst[i] == src[i] - ('a' - 'A'));
6148       }
6149     }
6150     ASSERT(expected_changed == changed);
6151   }
6152 #endif
6153 };
6154 
6155 
6156 struct ToLowerTraits {
6157   typedef unibrow::ToLowercase UnibrowConverter;
6158 
6159   typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6160 };
6161 
6162 
6163 struct ToUpperTraits {
6164   typedef unibrow::ToUppercase UnibrowConverter;
6165 
6166   typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6167 };
6168 
6169 }  // namespace
6170 
6171 
6172 template <typename ConvertTraits>
ConvertCase(Arguments args,Isolate * isolate,unibrow::Mapping<typename ConvertTraits::UnibrowConverter,128> * mapping)6173 MUST_USE_RESULT static MaybeObject* ConvertCase(
6174     Arguments args,
6175     Isolate* isolate,
6176     unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
6177   NoHandleAllocation ha;
6178   CONVERT_ARG_CHECKED(String, s, 0);
6179   s = s->TryFlattenGetString();
6180 
6181   const int length = s->length();
6182   // Assume that the string is not empty; we need this assumption later
6183   if (length == 0) return s;
6184 
6185   // Simpler handling of ASCII strings.
6186   //
6187   // NOTE: This assumes that the upper/lower case of an ASCII
6188   // character is also ASCII.  This is currently the case, but it
6189   // might break in the future if we implement more context and locale
6190   // dependent upper/lower conversions.
6191   if (s->IsSeqAsciiString()) {
6192     Object* o;
6193     { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length);
6194       if (!maybe_o->ToObject(&o)) return maybe_o;
6195     }
6196     SeqAsciiString* result = SeqAsciiString::cast(o);
6197     bool has_changed_character = ConvertTraits::AsciiConverter::Convert(
6198         result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length);
6199     return has_changed_character ? result : s;
6200   }
6201 
6202   Object* answer;
6203   { MaybeObject* maybe_answer =
6204         ConvertCaseHelper(isolate, s, length, length, mapping);
6205     if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6206   }
6207   if (answer->IsSmi()) {
6208     // Retry with correct length.
6209     { MaybeObject* maybe_answer =
6210           ConvertCaseHelper(isolate,
6211                             s, Smi::cast(answer)->value(), length, mapping);
6212       if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6213     }
6214   }
6215   return answer;
6216 }
6217 
6218 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToLowerCase)6219 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6220   return ConvertCase<ToLowerTraits>(
6221       args, isolate, isolate->runtime_state()->to_lower_mapping());
6222 }
6223 
6224 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToUpperCase)6225 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6226   return ConvertCase<ToUpperTraits>(
6227       args, isolate, isolate->runtime_state()->to_upper_mapping());
6228 }
6229 
6230 
IsTrimWhiteSpace(unibrow::uchar c)6231 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6232   return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6233 }
6234 
6235 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringTrim)6236 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6237   NoHandleAllocation ha;
6238   ASSERT(args.length() == 3);
6239 
6240   CONVERT_ARG_CHECKED(String, s, 0);
6241   CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6242   CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6243 
6244   s->TryFlatten();
6245   int length = s->length();
6246 
6247   int left = 0;
6248   if (trimLeft) {
6249     while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6250       left++;
6251     }
6252   }
6253 
6254   int right = length;
6255   if (trimRight) {
6256     while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6257       right--;
6258     }
6259   }
6260   return s->SubString(left, right);
6261 }
6262 
6263 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringSplit)6264 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6265   ASSERT(args.length() == 3);
6266   HandleScope handle_scope(isolate);
6267   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6268   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6269   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6270 
6271   int subject_length = subject->length();
6272   int pattern_length = pattern->length();
6273   RUNTIME_ASSERT(pattern_length > 0);
6274 
6275   if (limit == 0xffffffffu) {
6276     Handle<Object> cached_answer(StringSplitCache::Lookup(
6277         isolate->heap()->string_split_cache(),
6278         *subject,
6279         *pattern));
6280     if (*cached_answer != Smi::FromInt(0)) {
6281       Handle<JSArray> result =
6282           isolate->factory()->NewJSArrayWithElements(
6283               Handle<FixedArray>::cast(cached_answer));
6284       return *result;
6285     }
6286   }
6287 
6288   // The limit can be very large (0xffffffffu), but since the pattern
6289   // isn't empty, we can never create more parts than ~half the length
6290   // of the subject.
6291 
6292   if (!subject->IsFlat()) FlattenString(subject);
6293 
6294   static const int kMaxInitialListCapacity = 16;
6295 
6296   ZoneScope scope(isolate, DELETE_ON_EXIT);
6297 
6298   // Find (up to limit) indices of separator and end-of-string in subject
6299   int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6300   ZoneList<int> indices(initial_capacity);
6301   if (!pattern->IsFlat()) FlattenString(pattern);
6302 
6303   FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit);
6304 
6305   if (static_cast<uint32_t>(indices.length()) < limit) {
6306     indices.Add(subject_length);
6307   }
6308 
6309   // The list indices now contains the end of each part to create.
6310 
6311   // Create JSArray of substrings separated by separator.
6312   int part_count = indices.length();
6313 
6314   Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6315   MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
6316   if (maybe_result->IsFailure()) return maybe_result;
6317   result->set_length(Smi::FromInt(part_count));
6318 
6319   ASSERT(result->HasFastElements());
6320 
6321   if (part_count == 1 && indices.at(0) == subject_length) {
6322     FixedArray::cast(result->elements())->set(0, *subject);
6323     return *result;
6324   }
6325 
6326   Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6327   int part_start = 0;
6328   for (int i = 0; i < part_count; i++) {
6329     HandleScope local_loop_handle;
6330     int part_end = indices.at(i);
6331     Handle<String> substring =
6332         isolate->factory()->NewProperSubString(subject, part_start, part_end);
6333     elements->set(i, *substring);
6334     part_start = part_end + pattern_length;
6335   }
6336 
6337   if (limit == 0xffffffffu) {
6338     if (result->HasFastElements()) {
6339       StringSplitCache::Enter(isolate->heap(),
6340                               isolate->heap()->string_split_cache(),
6341                               *subject,
6342                               *pattern,
6343                               *elements);
6344     }
6345   }
6346 
6347   return *result;
6348 }
6349 
6350 
6351 // Copies ASCII characters to the given fixed array looking up
6352 // one-char strings in the cache. Gives up on the first char that is
6353 // not in the cache and fills the remainder with smi zeros. Returns
6354 // the length of the successfully copied prefix.
CopyCachedAsciiCharsToArray(Heap * heap,const char * chars,FixedArray * elements,int length)6355 static int CopyCachedAsciiCharsToArray(Heap* heap,
6356                                        const char* chars,
6357                                        FixedArray* elements,
6358                                        int length) {
6359   AssertNoAllocation no_gc;
6360   FixedArray* ascii_cache = heap->single_character_string_cache();
6361   Object* undefined = heap->undefined_value();
6362   int i;
6363   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6364   for (i = 0; i < length; ++i) {
6365     Object* value = ascii_cache->get(chars[i]);
6366     if (value == undefined) break;
6367     elements->set(i, value, mode);
6368   }
6369   if (i < length) {
6370     ASSERT(Smi::FromInt(0) == 0);
6371     memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6372   }
6373 #ifdef DEBUG
6374   for (int j = 0; j < length; ++j) {
6375     Object* element = elements->get(j);
6376     ASSERT(element == Smi::FromInt(0) ||
6377            (element->IsString() && String::cast(element)->LooksValid()));
6378   }
6379 #endif
6380   return i;
6381 }
6382 
6383 
6384 // Converts a String to JSArray.
6385 // For example, "foo" => ["f", "o", "o"].
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToArray)6386 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6387   HandleScope scope(isolate);
6388   ASSERT(args.length() == 2);
6389   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6390   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6391 
6392   s = FlattenGetString(s);
6393   const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6394 
6395   Handle<FixedArray> elements;
6396   int position = 0;
6397   if (s->IsFlat() && s->IsAsciiRepresentation()) {
6398     // Try using cached chars where possible.
6399     Object* obj;
6400     { MaybeObject* maybe_obj =
6401           isolate->heap()->AllocateUninitializedFixedArray(length);
6402       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6403     }
6404     elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6405     String::FlatContent content = s->GetFlatContent();
6406     if (content.IsAscii()) {
6407       Vector<const char> chars = content.ToAsciiVector();
6408       // Note, this will initialize all elements (not only the prefix)
6409       // to prevent GC from seeing partially initialized array.
6410       position = CopyCachedAsciiCharsToArray(isolate->heap(),
6411                                              chars.start(),
6412                                              *elements,
6413                                              length);
6414     } else {
6415       MemsetPointer(elements->data_start(),
6416                     isolate->heap()->undefined_value(),
6417                     length);
6418     }
6419   } else {
6420     elements = isolate->factory()->NewFixedArray(length);
6421   }
6422   for (int i = position; i < length; ++i) {
6423     Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
6424     elements->set(i, *str);
6425   }
6426 
6427 #ifdef DEBUG
6428   for (int i = 0; i < length; ++i) {
6429     ASSERT(String::cast(elements->get(i))->length() == 1);
6430   }
6431 #endif
6432 
6433   return *isolate->factory()->NewJSArrayWithElements(elements);
6434 }
6435 
6436 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewStringWrapper)6437 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6438   NoHandleAllocation ha;
6439   ASSERT(args.length() == 1);
6440   CONVERT_ARG_CHECKED(String, value, 0);
6441   return value->ToObject();
6442 }
6443 
6444 
IsUpperCaseChar(RuntimeState * runtime_state,uint16_t ch)6445 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6446   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6447   int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6448   return char_length == 0;
6449 }
6450 
6451 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToString)6452 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6453   NoHandleAllocation ha;
6454   ASSERT(args.length() == 1);
6455 
6456   Object* number = args[0];
6457   RUNTIME_ASSERT(number->IsNumber());
6458 
6459   return isolate->heap()->NumberToString(number);
6460 }
6461 
6462 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToStringSkipCache)6463 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6464   NoHandleAllocation ha;
6465   ASSERT(args.length() == 1);
6466 
6467   Object* number = args[0];
6468   RUNTIME_ASSERT(number->IsNumber());
6469 
6470   return isolate->heap()->NumberToString(number, false);
6471 }
6472 
6473 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToInteger)6474 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6475   NoHandleAllocation ha;
6476   ASSERT(args.length() == 1);
6477 
6478   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6479 
6480   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6481   if (number > 0 && number <= Smi::kMaxValue) {
6482     return Smi::FromInt(static_cast<int>(number));
6483   }
6484   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6485 }
6486 
6487 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToIntegerMapMinusZero)6488 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6489   NoHandleAllocation ha;
6490   ASSERT(args.length() == 1);
6491 
6492   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6493 
6494   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6495   if (number > 0 && number <= Smi::kMaxValue) {
6496     return Smi::FromInt(static_cast<int>(number));
6497   }
6498 
6499   double double_value = DoubleToInteger(number);
6500   // Map both -0 and +0 to +0.
6501   if (double_value == 0) double_value = 0;
6502 
6503   return isolate->heap()->NumberFromDouble(double_value);
6504 }
6505 
6506 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToJSUint32)6507 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6508   NoHandleAllocation ha;
6509   ASSERT(args.length() == 1);
6510 
6511   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6512   return isolate->heap()->NumberFromUint32(number);
6513 }
6514 
6515 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToJSInt32)6516 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6517   NoHandleAllocation ha;
6518   ASSERT(args.length() == 1);
6519 
6520   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6521 
6522   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6523   if (number > 0 && number <= Smi::kMaxValue) {
6524     return Smi::FromInt(static_cast<int>(number));
6525   }
6526   return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6527 }
6528 
6529 
6530 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
6531 // a small integer.
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToSmi)6532 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6533   NoHandleAllocation ha;
6534   ASSERT(args.length() == 1);
6535 
6536   Object* obj = args[0];
6537   if (obj->IsSmi()) {
6538     return obj;
6539   }
6540   if (obj->IsHeapNumber()) {
6541     double value = HeapNumber::cast(obj)->value();
6542     int int_value = FastD2I(value);
6543     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6544       return Smi::FromInt(int_value);
6545     }
6546   }
6547   return isolate->heap()->nan_value();
6548 }
6549 
6550 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AllocateHeapNumber)6551 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6552   NoHandleAllocation ha;
6553   ASSERT(args.length() == 0);
6554   return isolate->heap()->AllocateHeapNumber(0);
6555 }
6556 
6557 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAdd)6558 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6559   NoHandleAllocation ha;
6560   ASSERT(args.length() == 2);
6561 
6562   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6563   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6564   return isolate->heap()->NumberFromDouble(x + y);
6565 }
6566 
6567 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberSub)6568 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6569   NoHandleAllocation ha;
6570   ASSERT(args.length() == 2);
6571 
6572   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6573   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6574   return isolate->heap()->NumberFromDouble(x - y);
6575 }
6576 
6577 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberMul)6578 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6579   NoHandleAllocation ha;
6580   ASSERT(args.length() == 2);
6581 
6582   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6583   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6584   return isolate->heap()->NumberFromDouble(x * y);
6585 }
6586 
6587 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberUnaryMinus)6588 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6589   NoHandleAllocation ha;
6590   ASSERT(args.length() == 1);
6591 
6592   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6593   return isolate->heap()->NumberFromDouble(-x);
6594 }
6595 
6596 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAlloc)6597 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6598   NoHandleAllocation ha;
6599   ASSERT(args.length() == 0);
6600 
6601   return isolate->heap()->NumberFromDouble(9876543210.0);
6602 }
6603 
6604 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberDiv)6605 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6606   NoHandleAllocation ha;
6607   ASSERT(args.length() == 2);
6608 
6609   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6610   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6611   return isolate->heap()->NumberFromDouble(x / y);
6612 }
6613 
6614 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberMod)6615 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6616   NoHandleAllocation ha;
6617   ASSERT(args.length() == 2);
6618 
6619   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6620   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6621 
6622   x = modulo(x, y);
6623   // NumberFromDouble may return a Smi instead of a Number object
6624   return isolate->heap()->NumberFromDouble(x);
6625 }
6626 
6627 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringAdd)6628 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6629   NoHandleAllocation ha;
6630   ASSERT(args.length() == 2);
6631   CONVERT_ARG_CHECKED(String, str1, 0);
6632   CONVERT_ARG_CHECKED(String, str2, 1);
6633   isolate->counters()->string_add_runtime()->Increment();
6634   return isolate->heap()->AllocateConsString(str1, str2);
6635 }
6636 
6637 
6638 template <typename sinkchar>
StringBuilderConcatHelper(String * special,sinkchar * sink,FixedArray * fixed_array,int array_length)6639 static inline void StringBuilderConcatHelper(String* special,
6640                                              sinkchar* sink,
6641                                              FixedArray* fixed_array,
6642                                              int array_length) {
6643   int position = 0;
6644   for (int i = 0; i < array_length; i++) {
6645     Object* element = fixed_array->get(i);
6646     if (element->IsSmi()) {
6647       // Smi encoding of position and length.
6648       int encoded_slice = Smi::cast(element)->value();
6649       int pos;
6650       int len;
6651       if (encoded_slice > 0) {
6652         // Position and length encoded in one smi.
6653         pos = StringBuilderSubstringPosition::decode(encoded_slice);
6654         len = StringBuilderSubstringLength::decode(encoded_slice);
6655       } else {
6656         // Position and length encoded in two smis.
6657         Object* obj = fixed_array->get(++i);
6658         ASSERT(obj->IsSmi());
6659         pos = Smi::cast(obj)->value();
6660         len = -encoded_slice;
6661       }
6662       String::WriteToFlat(special,
6663                           sink + position,
6664                           pos,
6665                           pos + len);
6666       position += len;
6667     } else {
6668       String* string = String::cast(element);
6669       int element_length = string->length();
6670       String::WriteToFlat(string, sink + position, 0, element_length);
6671       position += element_length;
6672     }
6673   }
6674 }
6675 
6676 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringBuilderConcat)6677 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
6678   NoHandleAllocation ha;
6679   ASSERT(args.length() == 3);
6680   CONVERT_ARG_CHECKED(JSArray, array, 0);
6681   if (!args[1]->IsSmi()) {
6682     isolate->context()->mark_out_of_memory();
6683     return Failure::OutOfMemoryException();
6684   }
6685   int array_length = args.smi_at(1);
6686   CONVERT_ARG_CHECKED(String, special, 2);
6687 
6688   // This assumption is used by the slice encoding in one or two smis.
6689   ASSERT(Smi::kMaxValue >= String::kMaxLength);
6690 
6691   MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
6692   if (maybe_result->IsFailure()) return maybe_result;
6693 
6694   int special_length = special->length();
6695   if (!array->HasFastElements()) {
6696     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6697   }
6698   FixedArray* fixed_array = FixedArray::cast(array->elements());
6699   if (fixed_array->length() < array_length) {
6700     array_length = fixed_array->length();
6701   }
6702 
6703   if (array_length == 0) {
6704     return isolate->heap()->empty_string();
6705   } else if (array_length == 1) {
6706     Object* first = fixed_array->get(0);
6707     if (first->IsString()) return first;
6708   }
6709 
6710   bool ascii = special->HasOnlyAsciiChars();
6711   int position = 0;
6712   for (int i = 0; i < array_length; i++) {
6713     int increment = 0;
6714     Object* elt = fixed_array->get(i);
6715     if (elt->IsSmi()) {
6716       // Smi encoding of position and length.
6717       int smi_value = Smi::cast(elt)->value();
6718       int pos;
6719       int len;
6720       if (smi_value > 0) {
6721         // Position and length encoded in one smi.
6722         pos = StringBuilderSubstringPosition::decode(smi_value);
6723         len = StringBuilderSubstringLength::decode(smi_value);
6724       } else {
6725         // Position and length encoded in two smis.
6726         len = -smi_value;
6727         // Get the position and check that it is a positive smi.
6728         i++;
6729         if (i >= array_length) {
6730           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6731         }
6732         Object* next_smi = fixed_array->get(i);
6733         if (!next_smi->IsSmi()) {
6734           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6735         }
6736         pos = Smi::cast(next_smi)->value();
6737         if (pos < 0) {
6738           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6739         }
6740       }
6741       ASSERT(pos >= 0);
6742       ASSERT(len >= 0);
6743       if (pos > special_length || len > special_length - pos) {
6744         return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6745       }
6746       increment = len;
6747     } else if (elt->IsString()) {
6748       String* element = String::cast(elt);
6749       int element_length = element->length();
6750       increment = element_length;
6751       if (ascii && !element->HasOnlyAsciiChars()) {
6752         ascii = false;
6753       }
6754     } else {
6755       ASSERT(!elt->IsTheHole());
6756       return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6757     }
6758     if (increment > String::kMaxLength - position) {
6759       isolate->context()->mark_out_of_memory();
6760       return Failure::OutOfMemoryException();
6761     }
6762     position += increment;
6763   }
6764 
6765   int length = position;
6766   Object* object;
6767 
6768   if (ascii) {
6769     { MaybeObject* maybe_object =
6770           isolate->heap()->AllocateRawAsciiString(length);
6771       if (!maybe_object->ToObject(&object)) return maybe_object;
6772     }
6773     SeqAsciiString* answer = SeqAsciiString::cast(object);
6774     StringBuilderConcatHelper(special,
6775                               answer->GetChars(),
6776                               fixed_array,
6777                               array_length);
6778     return answer;
6779   } else {
6780     { MaybeObject* maybe_object =
6781           isolate->heap()->AllocateRawTwoByteString(length);
6782       if (!maybe_object->ToObject(&object)) return maybe_object;
6783     }
6784     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6785     StringBuilderConcatHelper(special,
6786                               answer->GetChars(),
6787                               fixed_array,
6788                               array_length);
6789     return answer;
6790   }
6791 }
6792 
6793 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringBuilderJoin)6794 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
6795   NoHandleAllocation ha;
6796   ASSERT(args.length() == 3);
6797   CONVERT_ARG_CHECKED(JSArray, array, 0);
6798   if (!args[1]->IsSmi()) {
6799     isolate->context()->mark_out_of_memory();
6800     return Failure::OutOfMemoryException();
6801   }
6802   int array_length = args.smi_at(1);
6803   CONVERT_ARG_CHECKED(String, separator, 2);
6804 
6805   if (!array->HasFastElements()) {
6806     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6807   }
6808   FixedArray* fixed_array = FixedArray::cast(array->elements());
6809   if (fixed_array->length() < array_length) {
6810     array_length = fixed_array->length();
6811   }
6812 
6813   if (array_length == 0) {
6814     return isolate->heap()->empty_string();
6815   } else if (array_length == 1) {
6816     Object* first = fixed_array->get(0);
6817     if (first->IsString()) return first;
6818   }
6819 
6820   int separator_length = separator->length();
6821   int max_nof_separators =
6822       (String::kMaxLength + separator_length - 1) / separator_length;
6823   if (max_nof_separators < (array_length - 1)) {
6824       isolate->context()->mark_out_of_memory();
6825       return Failure::OutOfMemoryException();
6826   }
6827   int length = (array_length - 1) * separator_length;
6828   for (int i = 0; i < array_length; i++) {
6829     Object* element_obj = fixed_array->get(i);
6830     if (!element_obj->IsString()) {
6831       // TODO(1161): handle this case.
6832       return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6833     }
6834     String* element = String::cast(element_obj);
6835     int increment = element->length();
6836     if (increment > String::kMaxLength - length) {
6837       isolate->context()->mark_out_of_memory();
6838       return Failure::OutOfMemoryException();
6839     }
6840     length += increment;
6841   }
6842 
6843   Object* object;
6844   { MaybeObject* maybe_object =
6845         isolate->heap()->AllocateRawTwoByteString(length);
6846     if (!maybe_object->ToObject(&object)) return maybe_object;
6847   }
6848   SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6849 
6850   uc16* sink = answer->GetChars();
6851 #ifdef DEBUG
6852   uc16* end = sink + length;
6853 #endif
6854 
6855   String* first = String::cast(fixed_array->get(0));
6856   int first_length = first->length();
6857   String::WriteToFlat(first, sink, 0, first_length);
6858   sink += first_length;
6859 
6860   for (int i = 1; i < array_length; i++) {
6861     ASSERT(sink + separator_length <= end);
6862     String::WriteToFlat(separator, sink, 0, separator_length);
6863     sink += separator_length;
6864 
6865     String* element = String::cast(fixed_array->get(i));
6866     int element_length = element->length();
6867     ASSERT(sink + element_length <= end);
6868     String::WriteToFlat(element, sink, 0, element_length);
6869     sink += element_length;
6870   }
6871   ASSERT(sink == end);
6872 
6873   ASSERT(!answer->HasOnlyAsciiChars());  // Use %_FastAsciiArrayJoin instead.
6874   return answer;
6875 }
6876 
6877 template <typename Char>
JoinSparseArrayWithSeparator(FixedArray * elements,int elements_length,uint32_t array_length,String * separator,Vector<Char> buffer)6878 static void JoinSparseArrayWithSeparator(FixedArray* elements,
6879                                          int elements_length,
6880                                          uint32_t array_length,
6881                                          String* separator,
6882                                          Vector<Char> buffer) {
6883   int previous_separator_position = 0;
6884   int separator_length = separator->length();
6885   int cursor = 0;
6886   for (int i = 0; i < elements_length; i += 2) {
6887     int position = NumberToInt32(elements->get(i));
6888     String* string = String::cast(elements->get(i + 1));
6889     int string_length = string->length();
6890     if (string->length() > 0) {
6891       while (previous_separator_position < position) {
6892         String::WriteToFlat<Char>(separator, &buffer[cursor],
6893                                   0, separator_length);
6894         cursor += separator_length;
6895         previous_separator_position++;
6896       }
6897       String::WriteToFlat<Char>(string, &buffer[cursor],
6898                                 0, string_length);
6899       cursor += string->length();
6900     }
6901   }
6902   if (separator_length > 0) {
6903     // Array length must be representable as a signed 32-bit number,
6904     // otherwise the total string length would have been too large.
6905     ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
6906     int last_array_index = static_cast<int>(array_length - 1);
6907     while (previous_separator_position < last_array_index) {
6908       String::WriteToFlat<Char>(separator, &buffer[cursor],
6909                                 0, separator_length);
6910       cursor += separator_length;
6911       previous_separator_position++;
6912     }
6913   }
6914   ASSERT(cursor <= buffer.length());
6915 }
6916 
6917 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SparseJoinWithSeparator)6918 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
6919   NoHandleAllocation ha;
6920   ASSERT(args.length() == 3);
6921   CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
6922   RUNTIME_ASSERT(elements_array->HasFastElements() ||
6923                  elements_array->HasFastSmiOnlyElements());
6924   CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
6925   CONVERT_ARG_CHECKED(String, separator, 2);
6926   // elements_array is fast-mode JSarray of alternating positions
6927   // (increasing order) and strings.
6928   // array_length is length of original array (used to add separators);
6929   // separator is string to put between elements. Assumed to be non-empty.
6930 
6931   // Find total length of join result.
6932   int string_length = 0;
6933   bool is_ascii = separator->IsAsciiRepresentation();
6934   int max_string_length;
6935   if (is_ascii) {
6936     max_string_length = SeqAsciiString::kMaxLength;
6937   } else {
6938     max_string_length = SeqTwoByteString::kMaxLength;
6939   }
6940   bool overflow = false;
6941   CONVERT_NUMBER_CHECKED(int, elements_length,
6942                          Int32, elements_array->length());
6943   RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
6944   FixedArray* elements = FixedArray::cast(elements_array->elements());
6945   for (int i = 0; i < elements_length; i += 2) {
6946     RUNTIME_ASSERT(elements->get(i)->IsNumber());
6947     RUNTIME_ASSERT(elements->get(i + 1)->IsString());
6948     String* string = String::cast(elements->get(i + 1));
6949     int length = string->length();
6950     if (is_ascii && !string->IsAsciiRepresentation()) {
6951       is_ascii = false;
6952       max_string_length = SeqTwoByteString::kMaxLength;
6953     }
6954     if (length > max_string_length ||
6955         max_string_length - length < string_length) {
6956       overflow = true;
6957       break;
6958     }
6959     string_length += length;
6960   }
6961   int separator_length = separator->length();
6962   if (!overflow && separator_length > 0) {
6963     if (array_length <= 0x7fffffffu) {
6964       int separator_count = static_cast<int>(array_length) - 1;
6965       int remaining_length = max_string_length - string_length;
6966       if ((remaining_length / separator_length) >= separator_count) {
6967         string_length += separator_length * (array_length - 1);
6968       } else {
6969         // Not room for the separators within the maximal string length.
6970         overflow = true;
6971       }
6972     } else {
6973       // Nonempty separator and at least 2^31-1 separators necessary
6974       // means that the string is too large to create.
6975       STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
6976       overflow = true;
6977     }
6978   }
6979   if (overflow) {
6980     // Throw OutOfMemory exception for creating too large a string.
6981     V8::FatalProcessOutOfMemory("Array join result too large.");
6982   }
6983 
6984   if (is_ascii) {
6985     MaybeObject* result_allocation =
6986         isolate->heap()->AllocateRawAsciiString(string_length);
6987     if (result_allocation->IsFailure()) return result_allocation;
6988     SeqAsciiString* result_string =
6989         SeqAsciiString::cast(result_allocation->ToObjectUnchecked());
6990     JoinSparseArrayWithSeparator<char>(elements,
6991                                        elements_length,
6992                                        array_length,
6993                                        separator,
6994                                        Vector<char>(result_string->GetChars(),
6995                                                     string_length));
6996     return result_string;
6997   } else {
6998     MaybeObject* result_allocation =
6999         isolate->heap()->AllocateRawTwoByteString(string_length);
7000     if (result_allocation->IsFailure()) return result_allocation;
7001     SeqTwoByteString* result_string =
7002         SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7003     JoinSparseArrayWithSeparator<uc16>(elements,
7004                                        elements_length,
7005                                        array_length,
7006                                        separator,
7007                                        Vector<uc16>(result_string->GetChars(),
7008                                                     string_length));
7009     return result_string;
7010   }
7011 }
7012 
7013 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberOr)7014 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7015   NoHandleAllocation ha;
7016   ASSERT(args.length() == 2);
7017 
7018   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7019   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7020   return isolate->heap()->NumberFromInt32(x | y);
7021 }
7022 
7023 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAnd)7024 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7025   NoHandleAllocation ha;
7026   ASSERT(args.length() == 2);
7027 
7028   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7029   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7030   return isolate->heap()->NumberFromInt32(x & y);
7031 }
7032 
7033 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberXor)7034 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7035   NoHandleAllocation ha;
7036   ASSERT(args.length() == 2);
7037 
7038   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7039   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7040   return isolate->heap()->NumberFromInt32(x ^ y);
7041 }
7042 
7043 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberNot)7044 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
7045   NoHandleAllocation ha;
7046   ASSERT(args.length() == 1);
7047 
7048   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7049   return isolate->heap()->NumberFromInt32(~x);
7050 }
7051 
7052 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberShl)7053 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7054   NoHandleAllocation ha;
7055   ASSERT(args.length() == 2);
7056 
7057   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7058   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7059   return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7060 }
7061 
7062 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberShr)7063 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7064   NoHandleAllocation ha;
7065   ASSERT(args.length() == 2);
7066 
7067   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7068   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7069   return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7070 }
7071 
7072 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberSar)7073 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7074   NoHandleAllocation ha;
7075   ASSERT(args.length() == 2);
7076 
7077   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7078   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7079   return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7080 }
7081 
7082 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberEquals)7083 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7084   NoHandleAllocation ha;
7085   ASSERT(args.length() == 2);
7086 
7087   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7088   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7089   if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
7090   if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
7091   if (x == y) return Smi::FromInt(EQUAL);
7092   Object* result;
7093   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7094     result = Smi::FromInt(EQUAL);
7095   } else {
7096     result = Smi::FromInt(NOT_EQUAL);
7097   }
7098   return result;
7099 }
7100 
7101 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringEquals)7102 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7103   NoHandleAllocation ha;
7104   ASSERT(args.length() == 2);
7105 
7106   CONVERT_ARG_CHECKED(String, x, 0);
7107   CONVERT_ARG_CHECKED(String, y, 1);
7108 
7109   bool not_equal = !x->Equals(y);
7110   // This is slightly convoluted because the value that signifies
7111   // equality is 0 and inequality is 1 so we have to negate the result
7112   // from String::Equals.
7113   ASSERT(not_equal == 0 || not_equal == 1);
7114   STATIC_CHECK(EQUAL == 0);
7115   STATIC_CHECK(NOT_EQUAL == 1);
7116   return Smi::FromInt(not_equal);
7117 }
7118 
7119 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberCompare)7120 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7121   NoHandleAllocation ha;
7122   ASSERT(args.length() == 3);
7123 
7124   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7125   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7126   if (isnan(x) || isnan(y)) return args[2];
7127   if (x == y) return Smi::FromInt(EQUAL);
7128   if (isless(x, y)) return Smi::FromInt(LESS);
7129   return Smi::FromInt(GREATER);
7130 }
7131 
7132 
7133 // Compare two Smis as if they were converted to strings and then
7134 // compared lexicographically.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SmiLexicographicCompare)7135 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7136   NoHandleAllocation ha;
7137   ASSERT(args.length() == 2);
7138   CONVERT_SMI_ARG_CHECKED(x_value, 0);
7139   CONVERT_SMI_ARG_CHECKED(y_value, 1);
7140 
7141   // If the integers are equal so are the string representations.
7142   if (x_value == y_value) return Smi::FromInt(EQUAL);
7143 
7144   // If one of the integers is zero the normal integer order is the
7145   // same as the lexicographic order of the string representations.
7146   if (x_value == 0 || y_value == 0)
7147     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7148 
7149   // If only one of the integers is negative the negative number is
7150   // smallest because the char code of '-' is less than the char code
7151   // of any digit.  Otherwise, we make both values positive.
7152 
7153   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7154   // architectures using 32-bit Smis.
7155   uint32_t x_scaled = x_value;
7156   uint32_t y_scaled = y_value;
7157   if (x_value < 0 || y_value < 0) {
7158     if (y_value >= 0) return Smi::FromInt(LESS);
7159     if (x_value >= 0) return Smi::FromInt(GREATER);
7160     x_scaled = -x_value;
7161     y_scaled = -y_value;
7162   }
7163 
7164   static const uint32_t kPowersOf10[] = {
7165     1, 10, 100, 1000, 10*1000, 100*1000,
7166     1000*1000, 10*1000*1000, 100*1000*1000,
7167     1000*1000*1000
7168   };
7169 
7170   // If the integers have the same number of decimal digits they can be
7171   // compared directly as the numeric order is the same as the
7172   // lexicographic order.  If one integer has fewer digits, it is scaled
7173   // by some power of 10 to have the same number of digits as the longer
7174   // integer.  If the scaled integers are equal it means the shorter
7175   // integer comes first in the lexicographic order.
7176 
7177   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7178   int x_log2 = IntegerLog2(x_scaled);
7179   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7180   x_log10 -= x_scaled < kPowersOf10[x_log10];
7181 
7182   int y_log2 = IntegerLog2(y_scaled);
7183   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7184   y_log10 -= y_scaled < kPowersOf10[y_log10];
7185 
7186   int tie = EQUAL;
7187 
7188   if (x_log10 < y_log10) {
7189     // X has fewer digits.  We would like to simply scale up X but that
7190     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7191     // be scaled up to 9_000_000_000. So we scale up by the next
7192     // smallest power and scale down Y to drop one digit. It is OK to
7193     // drop one digit from the longer integer since the final digit is
7194     // past the length of the shorter integer.
7195     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7196     y_scaled /= 10;
7197     tie = LESS;
7198   } else if (y_log10 < x_log10) {
7199     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7200     x_scaled /= 10;
7201     tie = GREATER;
7202   }
7203 
7204   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7205   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7206   return Smi::FromInt(tie);
7207 }
7208 
7209 
StringInputBufferCompare(RuntimeState * state,String * x,String * y)7210 static Object* StringInputBufferCompare(RuntimeState* state,
7211                                         String* x,
7212                                         String* y) {
7213   StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
7214   StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
7215   bufx.Reset(x);
7216   bufy.Reset(y);
7217   while (bufx.has_more() && bufy.has_more()) {
7218     int d = bufx.GetNext() - bufy.GetNext();
7219     if (d < 0) return Smi::FromInt(LESS);
7220     else if (d > 0) return Smi::FromInt(GREATER);
7221   }
7222 
7223   // x is (non-trivial) prefix of y:
7224   if (bufy.has_more()) return Smi::FromInt(LESS);
7225   // y is prefix of x:
7226   return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
7227 }
7228 
7229 
FlatStringCompare(String * x,String * y)7230 static Object* FlatStringCompare(String* x, String* y) {
7231   ASSERT(x->IsFlat());
7232   ASSERT(y->IsFlat());
7233   Object* equal_prefix_result = Smi::FromInt(EQUAL);
7234   int prefix_length = x->length();
7235   if (y->length() < prefix_length) {
7236     prefix_length = y->length();
7237     equal_prefix_result = Smi::FromInt(GREATER);
7238   } else if (y->length() > prefix_length) {
7239     equal_prefix_result = Smi::FromInt(LESS);
7240   }
7241   int r;
7242   String::FlatContent x_content = x->GetFlatContent();
7243   String::FlatContent y_content = y->GetFlatContent();
7244   if (x_content.IsAscii()) {
7245     Vector<const char> x_chars = x_content.ToAsciiVector();
7246     if (y_content.IsAscii()) {
7247       Vector<const char> y_chars = y_content.ToAsciiVector();
7248       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7249     } else {
7250       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7251       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7252     }
7253   } else {
7254     Vector<const uc16> x_chars = x_content.ToUC16Vector();
7255     if (y_content.IsAscii()) {
7256       Vector<const char> y_chars = y_content.ToAsciiVector();
7257       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7258     } else {
7259       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7260       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7261     }
7262   }
7263   Object* result;
7264   if (r == 0) {
7265     result = equal_prefix_result;
7266   } else {
7267     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7268   }
7269   ASSERT(result ==
7270       StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y));
7271   return result;
7272 }
7273 
7274 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringCompare)7275 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7276   NoHandleAllocation ha;
7277   ASSERT(args.length() == 2);
7278 
7279   CONVERT_ARG_CHECKED(String, x, 0);
7280   CONVERT_ARG_CHECKED(String, y, 1);
7281 
7282   isolate->counters()->string_compare_runtime()->Increment();
7283 
7284   // A few fast case tests before we flatten.
7285   if (x == y) return Smi::FromInt(EQUAL);
7286   if (y->length() == 0) {
7287     if (x->length() == 0) return Smi::FromInt(EQUAL);
7288     return Smi::FromInt(GREATER);
7289   } else if (x->length() == 0) {
7290     return Smi::FromInt(LESS);
7291   }
7292 
7293   int d = x->Get(0) - y->Get(0);
7294   if (d < 0) return Smi::FromInt(LESS);
7295   else if (d > 0) return Smi::FromInt(GREATER);
7296 
7297   Object* obj;
7298   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7299     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7300   }
7301   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7302     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7303   }
7304 
7305   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7306       : StringInputBufferCompare(isolate->runtime_state(), x, y);
7307 }
7308 
7309 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_acos)7310 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7311   NoHandleAllocation ha;
7312   ASSERT(args.length() == 1);
7313   isolate->counters()->math_acos()->Increment();
7314 
7315   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7316   return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7317 }
7318 
7319 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_asin)7320 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7321   NoHandleAllocation ha;
7322   ASSERT(args.length() == 1);
7323   isolate->counters()->math_asin()->Increment();
7324 
7325   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7326   return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7327 }
7328 
7329 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_atan)7330 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7331   NoHandleAllocation ha;
7332   ASSERT(args.length() == 1);
7333   isolate->counters()->math_atan()->Increment();
7334 
7335   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7336   return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7337 }
7338 
7339 
7340 static const double kPiDividedBy4 = 0.78539816339744830962;
7341 
7342 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_atan2)7343 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7344   NoHandleAllocation ha;
7345   ASSERT(args.length() == 2);
7346   isolate->counters()->math_atan2()->Increment();
7347 
7348   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7349   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7350   double result;
7351   if (isinf(x) && isinf(y)) {
7352     // Make sure that the result in case of two infinite arguments
7353     // is a multiple of Pi / 4. The sign of the result is determined
7354     // by the first argument (x) and the sign of the second argument
7355     // determines the multiplier: one or three.
7356     int multiplier = (x < 0) ? -1 : 1;
7357     if (y < 0) multiplier *= 3;
7358     result = multiplier * kPiDividedBy4;
7359   } else {
7360     result = atan2(x, y);
7361   }
7362   return isolate->heap()->AllocateHeapNumber(result);
7363 }
7364 
7365 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_ceil)7366 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7367   NoHandleAllocation ha;
7368   ASSERT(args.length() == 1);
7369   isolate->counters()->math_ceil()->Increment();
7370 
7371   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7372   return isolate->heap()->NumberFromDouble(ceiling(x));
7373 }
7374 
7375 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_cos)7376 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7377   NoHandleAllocation ha;
7378   ASSERT(args.length() == 1);
7379   isolate->counters()->math_cos()->Increment();
7380 
7381   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7382   return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7383 }
7384 
7385 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_exp)7386 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7387   NoHandleAllocation ha;
7388   ASSERT(args.length() == 1);
7389   isolate->counters()->math_exp()->Increment();
7390 
7391   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7392   return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x);
7393 }
7394 
7395 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_floor)7396 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7397   NoHandleAllocation ha;
7398   ASSERT(args.length() == 1);
7399   isolate->counters()->math_floor()->Increment();
7400 
7401   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7402   return isolate->heap()->NumberFromDouble(floor(x));
7403 }
7404 
7405 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_log)7406 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7407   NoHandleAllocation ha;
7408   ASSERT(args.length() == 1);
7409   isolate->counters()->math_log()->Increment();
7410 
7411   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7412   return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7413 }
7414 
7415 // Slow version of Math.pow.  We check for fast paths for special cases.
7416 // Used if SSE2/VFP3 is not available.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_pow)7417 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7418   NoHandleAllocation ha;
7419   ASSERT(args.length() == 2);
7420   isolate->counters()->math_pow()->Increment();
7421 
7422   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7423 
7424   // If the second argument is a smi, it is much faster to call the
7425   // custom powi() function than the generic pow().
7426   if (args[1]->IsSmi()) {
7427     int y = args.smi_at(1);
7428     return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7429   }
7430 
7431   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7432   int y_int = static_cast<int>(y);
7433   double result;
7434   if (y == y_int) {
7435     result = power_double_int(x, y_int);  // Returns 1 if exponent is 0.
7436   } else  if (y == 0.5) {
7437     result = (isinf(x)) ? V8_INFINITY
7438                         : fast_sqrt(x + 0.0);  // Convert -0 to +0.
7439   } else if (y == -0.5) {
7440     result = (isinf(x)) ? 0
7441                         : 1.0 / fast_sqrt(x + 0.0);  // Convert -0 to +0.
7442   } else {
7443     result = power_double_double(x, y);
7444   }
7445   if (isnan(result)) return isolate->heap()->nan_value();
7446   return isolate->heap()->AllocateHeapNumber(result);
7447 }
7448 
7449 // Fast version of Math.pow if we know that y is not an integer and y is not
7450 // -0.5 or 0.5.  Used as slow case from full codegen.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_pow_cfunction)7451 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7452   NoHandleAllocation ha;
7453   ASSERT(args.length() == 2);
7454   isolate->counters()->math_pow()->Increment();
7455 
7456   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7457   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7458   if (y == 0) {
7459     return Smi::FromInt(1);
7460   } else {
7461     double result = power_double_double(x, y);
7462     if (isnan(result)) return isolate->heap()->nan_value();
7463     return isolate->heap()->AllocateHeapNumber(result);
7464   }
7465 }
7466 
7467 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RoundNumber)7468 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7469   NoHandleAllocation ha;
7470   ASSERT(args.length() == 1);
7471   isolate->counters()->math_round()->Increment();
7472 
7473   if (!args[0]->IsHeapNumber()) {
7474     // Must be smi. Return the argument unchanged for all the other types
7475     // to make fuzz-natives test happy.
7476     return args[0];
7477   }
7478 
7479   HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7480 
7481   double value = number->value();
7482   int exponent = number->get_exponent();
7483   int sign = number->get_sign();
7484 
7485   if (exponent < -1) {
7486     // Number in range ]-0.5..0.5[. These always round to +/-zero.
7487     if (sign) return isolate->heap()->minus_zero_value();
7488     return Smi::FromInt(0);
7489   }
7490 
7491   // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7492   // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7493   // argument holds for 32-bit smis).
7494   if (!sign && exponent < kSmiValueSize - 2) {
7495     return Smi::FromInt(static_cast<int>(value + 0.5));
7496   }
7497 
7498   // If the magnitude is big enough, there's no place for fraction part. If we
7499   // try to add 0.5 to this number, 1.0 will be added instead.
7500   if (exponent >= 52) {
7501     return number;
7502   }
7503 
7504   if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7505 
7506   // Do not call NumberFromDouble() to avoid extra checks.
7507   return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7508 }
7509 
7510 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_sin)7511 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7512   NoHandleAllocation ha;
7513   ASSERT(args.length() == 1);
7514   isolate->counters()->math_sin()->Increment();
7515 
7516   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7517   return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7518 }
7519 
7520 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_sqrt)7521 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7522   NoHandleAllocation ha;
7523   ASSERT(args.length() == 1);
7524   isolate->counters()->math_sqrt()->Increment();
7525 
7526   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7527   return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7528 }
7529 
7530 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_tan)7531 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7532   NoHandleAllocation ha;
7533   ASSERT(args.length() == 1);
7534   isolate->counters()->math_tan()->Increment();
7535 
7536   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7537   return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7538 }
7539 
7540 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateMakeDay)7541 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7542   NoHandleAllocation ha;
7543   ASSERT(args.length() == 2);
7544 
7545   CONVERT_SMI_ARG_CHECKED(year, 0);
7546   CONVERT_SMI_ARG_CHECKED(month, 1);
7547 
7548   return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7549 }
7550 
7551 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateSetValue)7552 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7553   HandleScope scope(isolate);
7554   ASSERT(args.length() == 3);
7555 
7556   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7557   CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7558   CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7559 
7560   DateCache* date_cache = isolate->date_cache();
7561 
7562   Object* value = NULL;
7563   bool is_value_nan = false;
7564   if (isnan(time)) {
7565     value = isolate->heap()->nan_value();
7566     is_value_nan = true;
7567   } else if (!is_utc &&
7568              (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7569               time > DateCache::kMaxTimeBeforeUTCInMs)) {
7570     value = isolate->heap()->nan_value();
7571     is_value_nan = true;
7572   } else {
7573     time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7574     if (time < -DateCache::kMaxTimeInMs ||
7575         time > DateCache::kMaxTimeInMs) {
7576       value = isolate->heap()->nan_value();
7577       is_value_nan = true;
7578     } else  {
7579       MaybeObject* maybe_result =
7580           isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7581       if (!maybe_result->ToObject(&value)) return maybe_result;
7582     }
7583   }
7584   date->SetValue(value, is_value_nan);
7585   return value;
7586 }
7587 
7588 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewArgumentsFast)7589 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7590   HandleScope scope(isolate);
7591   ASSERT(args.length() == 3);
7592 
7593   Handle<JSFunction> callee = args.at<JSFunction>(0);
7594   Object** parameters = reinterpret_cast<Object**>(args[1]);
7595   const int argument_count = Smi::cast(args[2])->value();
7596 
7597   Handle<JSObject> result =
7598       isolate->factory()->NewArgumentsObject(callee, argument_count);
7599   // Allocate the elements if needed.
7600   int parameter_count = callee->shared()->formal_parameter_count();
7601   if (argument_count > 0) {
7602     if (parameter_count > 0) {
7603       int mapped_count = Min(argument_count, parameter_count);
7604       Handle<FixedArray> parameter_map =
7605           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7606       parameter_map->set_map(
7607           isolate->heap()->non_strict_arguments_elements_map());
7608 
7609       Handle<Map> old_map(result->map());
7610       Handle<Map> new_map =
7611           isolate->factory()->CopyMapDropTransitions(old_map);
7612       new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7613 
7614       result->set_map(*new_map);
7615       result->set_elements(*parameter_map);
7616 
7617       // Store the context and the arguments array at the beginning of the
7618       // parameter map.
7619       Handle<Context> context(isolate->context());
7620       Handle<FixedArray> arguments =
7621           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7622       parameter_map->set(0, *context);
7623       parameter_map->set(1, *arguments);
7624 
7625       // Loop over the actual parameters backwards.
7626       int index = argument_count - 1;
7627       while (index >= mapped_count) {
7628         // These go directly in the arguments array and have no
7629         // corresponding slot in the parameter map.
7630         arguments->set(index, *(parameters - index - 1));
7631         --index;
7632       }
7633 
7634       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7635       while (index >= 0) {
7636         // Detect duplicate names to the right in the parameter list.
7637         Handle<String> name(scope_info->ParameterName(index));
7638         int context_local_count = scope_info->ContextLocalCount();
7639         bool duplicate = false;
7640         for (int j = index + 1; j < parameter_count; ++j) {
7641           if (scope_info->ParameterName(j) == *name) {
7642             duplicate = true;
7643             break;
7644           }
7645         }
7646 
7647         if (duplicate) {
7648           // This goes directly in the arguments array with a hole in the
7649           // parameter map.
7650           arguments->set(index, *(parameters - index - 1));
7651           parameter_map->set_the_hole(index + 2);
7652         } else {
7653           // The context index goes in the parameter map with a hole in the
7654           // arguments array.
7655           int context_index = -1;
7656           for (int j = 0; j < context_local_count; ++j) {
7657             if (scope_info->ContextLocalName(j) == *name) {
7658               context_index = j;
7659               break;
7660             }
7661           }
7662           ASSERT(context_index >= 0);
7663           arguments->set_the_hole(index);
7664           parameter_map->set(index + 2, Smi::FromInt(
7665               Context::MIN_CONTEXT_SLOTS + context_index));
7666         }
7667 
7668         --index;
7669       }
7670     } else {
7671       // If there is no aliasing, the arguments object elements are not
7672       // special in any way.
7673       Handle<FixedArray> elements =
7674           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7675       result->set_elements(*elements);
7676       for (int i = 0; i < argument_count; ++i) {
7677         elements->set(i, *(parameters - i - 1));
7678       }
7679     }
7680   }
7681   return *result;
7682 }
7683 
7684 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewStrictArgumentsFast)7685 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7686   NoHandleAllocation ha;
7687   ASSERT(args.length() == 3);
7688 
7689   JSFunction* callee = JSFunction::cast(args[0]);
7690   Object** parameters = reinterpret_cast<Object**>(args[1]);
7691   const int length = args.smi_at(2);
7692 
7693   Object* result;
7694   { MaybeObject* maybe_result =
7695         isolate->heap()->AllocateArgumentsObject(callee, length);
7696     if (!maybe_result->ToObject(&result)) return maybe_result;
7697   }
7698   // Allocate the elements if needed.
7699   if (length > 0) {
7700     // Allocate the fixed array.
7701     Object* obj;
7702     { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7703       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7704     }
7705 
7706     AssertNoAllocation no_gc;
7707     FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7708     array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
7709     array->set_length(length);
7710 
7711     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7712     for (int i = 0; i < length; i++) {
7713       array->set(i, *--parameters, mode);
7714     }
7715     JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7716   }
7717   return result;
7718 }
7719 
7720 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewClosure)7721 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7722   HandleScope scope(isolate);
7723   ASSERT(args.length() == 3);
7724   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
7725   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
7726   CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
7727 
7728   // The caller ensures that we pretenure closures that are assigned
7729   // directly to properties.
7730   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7731   Handle<JSFunction> result =
7732       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7733                                                             context,
7734                                                             pretenure_flag);
7735   return *result;
7736 }
7737 
7738 
7739 // Find the arguments of the JavaScript function invocation that called
7740 // into C++ code. Collect these in a newly allocated array of handles (possibly
7741 // prefixed by a number of empty handles).
GetCallerArguments(int prefix_argc,int * total_argc)7742 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
7743     int prefix_argc,
7744     int* total_argc) {
7745   // Find frame containing arguments passed to the caller.
7746   JavaScriptFrameIterator it;
7747   JavaScriptFrame* frame = it.frame();
7748   List<JSFunction*> functions(2);
7749   frame->GetFunctions(&functions);
7750   if (functions.length() > 1) {
7751     int inlined_jsframe_index = functions.length() - 1;
7752     JSFunction* inlined_function = functions[inlined_jsframe_index];
7753     Vector<SlotRef> args_slots =
7754         SlotRef::ComputeSlotMappingForArguments(
7755             frame,
7756             inlined_jsframe_index,
7757             inlined_function->shared()->formal_parameter_count());
7758 
7759     int args_count = args_slots.length();
7760 
7761     *total_argc = prefix_argc + args_count;
7762     SmartArrayPointer<Handle<Object> > param_data(
7763         NewArray<Handle<Object> >(*total_argc));
7764     for (int i = 0; i < args_count; i++) {
7765       Handle<Object> val = args_slots[i].GetValue();
7766       param_data[prefix_argc + i] = val;
7767     }
7768 
7769     args_slots.Dispose();
7770 
7771     return param_data;
7772   } else {
7773     it.AdvanceToArgumentsFrame();
7774     frame = it.frame();
7775     int args_count = frame->ComputeParametersCount();
7776 
7777     *total_argc = prefix_argc + args_count;
7778     SmartArrayPointer<Handle<Object> > param_data(
7779         NewArray<Handle<Object> >(*total_argc));
7780     for (int i = 0; i < args_count; i++) {
7781       Handle<Object> val = Handle<Object>(frame->GetParameter(i));
7782       param_data[prefix_argc + i] = val;
7783     }
7784     return param_data;
7785   }
7786 }
7787 
7788 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionBindArguments)7789 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
7790   HandleScope scope(isolate);
7791   ASSERT(args.length() == 4);
7792   CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
7793   RUNTIME_ASSERT(args[3]->IsNumber());
7794   Handle<Object> bindee = args.at<Object>(1);
7795 
7796   // TODO(lrn): Create bound function in C++ code from premade shared info.
7797   bound_function->shared()->set_bound(true);
7798   // Get all arguments of calling function (Function.prototype.bind).
7799   int argc = 0;
7800   SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(0, &argc);
7801   // Don't count the this-arg.
7802   if (argc > 0) {
7803     ASSERT(*arguments[0] == args[2]);
7804     argc--;
7805   } else {
7806     ASSERT(args[2]->IsUndefined());
7807   }
7808   // Initialize array of bindings (function, this, and any existing arguments
7809   // if the function was already bound).
7810   Handle<FixedArray> new_bindings;
7811   int i;
7812   if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
7813     Handle<FixedArray> old_bindings(
7814         JSFunction::cast(*bindee)->function_bindings());
7815     new_bindings =
7816         isolate->factory()->NewFixedArray(old_bindings->length() + argc);
7817     bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex));
7818     i = 0;
7819     for (int n = old_bindings->length(); i < n; i++) {
7820       new_bindings->set(i, old_bindings->get(i));
7821     }
7822   } else {
7823     int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
7824     new_bindings = isolate->factory()->NewFixedArray(array_size);
7825     new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
7826     new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
7827     i = 2;
7828   }
7829   // Copy arguments, skipping the first which is "this_arg".
7830   for (int j = 0; j < argc; j++, i++) {
7831     new_bindings->set(i, *arguments[j + 1]);
7832   }
7833   new_bindings->set_map_no_write_barrier(
7834       isolate->heap()->fixed_cow_array_map());
7835   bound_function->set_function_bindings(*new_bindings);
7836 
7837   // Update length.
7838   Handle<String> length_symbol = isolate->factory()->length_symbol();
7839   Handle<Object> new_length(args.at<Object>(3));
7840   PropertyAttributes attr =
7841       static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
7842   ForceSetProperty(bound_function, length_symbol, new_length, attr);
7843   return *bound_function;
7844 }
7845 
7846 
RUNTIME_FUNCTION(MaybeObject *,Runtime_BoundFunctionGetBindings)7847 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
7848   HandleScope handles(isolate);
7849   ASSERT(args.length() == 1);
7850   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
7851   if (callable->IsJSFunction()) {
7852     Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
7853     if (function->shared()->bound()) {
7854       Handle<FixedArray> bindings(function->function_bindings());
7855       ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
7856       return *isolate->factory()->NewJSArrayWithElements(bindings);
7857     }
7858   }
7859   return isolate->heap()->undefined_value();
7860 }
7861 
7862 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewObjectFromBound)7863 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
7864   HandleScope scope(isolate);
7865   ASSERT(args.length() == 1);
7866   // First argument is a function to use as a constructor.
7867   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
7868   RUNTIME_ASSERT(function->shared()->bound());
7869 
7870   // The argument is a bound function. Extract its bound arguments
7871   // and callable.
7872   Handle<FixedArray> bound_args =
7873       Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
7874   int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
7875   Handle<Object> bound_function(
7876       JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)));
7877   ASSERT(!bound_function->IsJSFunction() ||
7878          !Handle<JSFunction>::cast(bound_function)->shared()->bound());
7879 
7880   int total_argc = 0;
7881   SmartArrayPointer<Handle<Object> > param_data =
7882       GetCallerArguments(bound_argc, &total_argc);
7883   for (int i = 0; i < bound_argc; i++) {
7884     param_data[i] = Handle<Object>(bound_args->get(
7885         JSFunction::kBoundArgumentsStartIndex + i));
7886   }
7887 
7888   if (!bound_function->IsJSFunction()) {
7889     bool exception_thrown;
7890     bound_function = Execution::TryGetConstructorDelegate(bound_function,
7891                                                           &exception_thrown);
7892     if (exception_thrown) return Failure::Exception();
7893   }
7894   ASSERT(bound_function->IsJSFunction());
7895 
7896   bool exception = false;
7897   Handle<Object> result =
7898       Execution::New(Handle<JSFunction>::cast(bound_function),
7899                      total_argc, *param_data, &exception);
7900   if (exception) {
7901     return Failure::Exception();
7902   }
7903   ASSERT(!result.is_null());
7904   return *result;
7905 }
7906 
7907 
TrySettingInlineConstructStub(Isolate * isolate,Handle<JSFunction> function)7908 static void TrySettingInlineConstructStub(Isolate* isolate,
7909                                           Handle<JSFunction> function) {
7910   Handle<Object> prototype = isolate->factory()->null_value();
7911   if (function->has_instance_prototype()) {
7912     prototype = Handle<Object>(function->instance_prototype(), isolate);
7913   }
7914   if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
7915     ConstructStubCompiler compiler(isolate);
7916     Handle<Code> code = compiler.CompileConstructStub(function);
7917     function->shared()->set_construct_stub(*code);
7918   }
7919 }
7920 
7921 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewObject)7922 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
7923   HandleScope scope(isolate);
7924   ASSERT(args.length() == 1);
7925 
7926   Handle<Object> constructor = args.at<Object>(0);
7927 
7928   // If the constructor isn't a proper function we throw a type error.
7929   if (!constructor->IsJSFunction()) {
7930     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7931     Handle<Object> type_error =
7932         isolate->factory()->NewTypeError("not_constructor", arguments);
7933     return isolate->Throw(*type_error);
7934   }
7935 
7936   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
7937 
7938   // If function should not have prototype, construction is not allowed. In this
7939   // case generated code bailouts here, since function has no initial_map.
7940   if (!function->should_have_prototype() && !function->shared()->bound()) {
7941     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7942     Handle<Object> type_error =
7943         isolate->factory()->NewTypeError("not_constructor", arguments);
7944     return isolate->Throw(*type_error);
7945   }
7946 
7947 #ifdef ENABLE_DEBUGGER_SUPPORT
7948   Debug* debug = isolate->debug();
7949   // Handle stepping into constructors if step into is active.
7950   if (debug->StepInActive()) {
7951     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
7952   }
7953 #endif
7954 
7955   if (function->has_initial_map()) {
7956     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
7957       // The 'Function' function ignores the receiver object when
7958       // called using 'new' and creates a new JSFunction object that
7959       // is returned.  The receiver object is only used for error
7960       // reporting if an error occurs when constructing the new
7961       // JSFunction. FACTORY->NewJSObject() should not be used to
7962       // allocate JSFunctions since it does not properly initialize
7963       // the shared part of the function. Since the receiver is
7964       // ignored anyway, we use the global object as the receiver
7965       // instead of a new JSFunction object. This way, errors are
7966       // reported the same way whether or not 'Function' is called
7967       // using 'new'.
7968       return isolate->context()->global();
7969     }
7970   }
7971 
7972   // The function should be compiled for the optimization hints to be
7973   // available. We cannot use EnsureCompiled because that forces a
7974   // compilation through the shared function info which makes it
7975   // impossible for us to optimize.
7976   if (!function->is_compiled()) {
7977     JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
7978   }
7979 
7980   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
7981   if (!function->has_initial_map() &&
7982       shared->IsInobjectSlackTrackingInProgress()) {
7983     // The tracking is already in progress for another function. We can only
7984     // track one initial_map at a time, so we force the completion before the
7985     // function is called as a constructor for the first time.
7986     shared->CompleteInobjectSlackTracking();
7987   }
7988 
7989   bool first_allocation = !shared->live_objects_may_exist();
7990   Handle<JSObject> result = isolate->factory()->NewJSObject(function);
7991   RETURN_IF_EMPTY_HANDLE(isolate, result);
7992   // Delay setting the stub if inobject slack tracking is in progress.
7993   if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
7994     TrySettingInlineConstructStub(isolate, function);
7995   }
7996 
7997   isolate->counters()->constructed_objects()->Increment();
7998   isolate->counters()->constructed_objects_runtime()->Increment();
7999 
8000   return *result;
8001 }
8002 
8003 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FinalizeInstanceSize)8004 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8005   HandleScope scope(isolate);
8006   ASSERT(args.length() == 1);
8007 
8008   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8009   function->shared()->CompleteInobjectSlackTracking();
8010   TrySettingInlineConstructStub(isolate, function);
8011 
8012   return isolate->heap()->undefined_value();
8013 }
8014 
8015 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LazyCompile)8016 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8017   HandleScope scope(isolate);
8018   ASSERT(args.length() == 1);
8019 
8020   Handle<JSFunction> function = args.at<JSFunction>(0);
8021 #ifdef DEBUG
8022   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8023     PrintF("[lazy: ");
8024     function->PrintName();
8025     PrintF("]\n");
8026   }
8027 #endif
8028 
8029   // Compile the target function.
8030   ASSERT(!function->is_compiled());
8031   if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8032     return Failure::Exception();
8033   }
8034 
8035   // All done. Return the compiled code.
8036   ASSERT(function->is_compiled());
8037   return function->code();
8038 }
8039 
8040 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LazyRecompile)8041 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8042   HandleScope scope(isolate);
8043   ASSERT(args.length() == 1);
8044   Handle<JSFunction> function = args.at<JSFunction>(0);
8045 
8046   // If the function is not compiled ignore the lazy
8047   // recompilation. This can happen if the debugger is activated and
8048   // the function is returned to the not compiled state.
8049   if (!function->shared()->is_compiled()) {
8050     function->ReplaceCode(function->shared()->code());
8051     return function->code();
8052   }
8053 
8054   // If the function is not optimizable or debugger is active continue using the
8055   // code from the full compiler.
8056   if (!function->shared()->code()->optimizable() ||
8057       isolate->DebuggerHasBreakPoints()) {
8058     if (FLAG_trace_opt) {
8059       PrintF("[failed to optimize ");
8060       function->PrintName();
8061       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8062           function->shared()->code()->optimizable() ? "T" : "F",
8063           isolate->DebuggerHasBreakPoints() ? "T" : "F");
8064     }
8065     function->ReplaceCode(function->shared()->code());
8066     return function->code();
8067   }
8068   function->shared()->code()->set_profiler_ticks(0);
8069   if (JSFunction::CompileOptimized(function,
8070                                    AstNode::kNoNumber,
8071                                    CLEAR_EXCEPTION)) {
8072     return function->code();
8073   }
8074   if (FLAG_trace_opt) {
8075     PrintF("[failed to optimize ");
8076     function->PrintName();
8077     PrintF(": optimized compilation failed]\n");
8078   }
8079   function->ReplaceCode(function->shared()->code());
8080   return function->code();
8081 }
8082 
8083 
8084 class ActivationsFinder : public ThreadVisitor {
8085  public:
ActivationsFinder(JSFunction * function)8086   explicit ActivationsFinder(JSFunction* function)
8087       : function_(function), has_activations_(false) {}
8088 
VisitThread(Isolate * isolate,ThreadLocalTop * top)8089   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8090     if (has_activations_) return;
8091 
8092     for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
8093       JavaScriptFrame* frame = it.frame();
8094       if (frame->is_optimized() && frame->function() == function_) {
8095         has_activations_ = true;
8096         return;
8097       }
8098     }
8099   }
8100 
has_activations()8101   bool has_activations() { return has_activations_; }
8102 
8103  private:
8104   JSFunction* function_;
8105   bool has_activations_;
8106 };
8107 
8108 
MaterializeArgumentsObjectInFrame(Isolate * isolate,JavaScriptFrame * frame)8109 static void MaterializeArgumentsObjectInFrame(Isolate* isolate,
8110                                               JavaScriptFrame* frame) {
8111   Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8112   Handle<Object> arguments;
8113   for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
8114     if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) {
8115       if (arguments.is_null()) {
8116         // FunctionGetArguments can't throw an exception, so cast away the
8117         // doubt with an assert.
8118         arguments = Handle<Object>(
8119             Accessors::FunctionGetArguments(*function,
8120                                             NULL)->ToObjectUnchecked());
8121         ASSERT(*arguments != isolate->heap()->null_value());
8122         ASSERT(*arguments != isolate->heap()->undefined_value());
8123       }
8124       frame->SetExpression(i, *arguments);
8125     }
8126   }
8127 }
8128 
8129 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NotifyDeoptimized)8130 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8131   HandleScope scope(isolate);
8132   ASSERT(args.length() == 1);
8133   RUNTIME_ASSERT(args[0]->IsSmi());
8134   Deoptimizer::BailoutType type =
8135       static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8136   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8137   ASSERT(isolate->heap()->IsAllocationAllowed());
8138   int jsframes = deoptimizer->jsframe_count();
8139 
8140   deoptimizer->MaterializeHeapNumbers();
8141   delete deoptimizer;
8142 
8143   JavaScriptFrameIterator it(isolate);
8144   for (int i = 0; i < jsframes - 1; i++) {
8145     MaterializeArgumentsObjectInFrame(isolate, it.frame());
8146     it.Advance();
8147   }
8148 
8149   JavaScriptFrame* frame = it.frame();
8150   RUNTIME_ASSERT(frame->function()->IsJSFunction());
8151   Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8152   MaterializeArgumentsObjectInFrame(isolate, frame);
8153 
8154   if (type == Deoptimizer::EAGER) {
8155     RUNTIME_ASSERT(function->IsOptimized());
8156   }
8157 
8158   // Avoid doing too much work when running with --always-opt and keep
8159   // the optimized code around.
8160   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8161     return isolate->heap()->undefined_value();
8162   }
8163 
8164   // Find other optimized activations of the function.
8165   bool has_other_activations = false;
8166   while (!it.done()) {
8167     JavaScriptFrame* frame = it.frame();
8168     if (frame->is_optimized() && frame->function() == *function) {
8169       has_other_activations = true;
8170       break;
8171     }
8172     it.Advance();
8173   }
8174 
8175   if (!has_other_activations) {
8176     ActivationsFinder activations_finder(*function);
8177     isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8178     has_other_activations = activations_finder.has_activations();
8179   }
8180 
8181   if (!has_other_activations) {
8182     if (FLAG_trace_deopt) {
8183       PrintF("[removing optimized code for: ");
8184       function->PrintName();
8185       PrintF("]\n");
8186     }
8187     function->ReplaceCode(function->shared()->code());
8188   } else {
8189     Deoptimizer::DeoptimizeFunction(*function);
8190   }
8191   return isolate->heap()->undefined_value();
8192 }
8193 
8194 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NotifyOSR)8195 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
8196   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8197   delete deoptimizer;
8198   return isolate->heap()->undefined_value();
8199 }
8200 
8201 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeoptimizeFunction)8202 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8203   HandleScope scope(isolate);
8204   ASSERT(args.length() == 1);
8205   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8206   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8207 
8208   Deoptimizer::DeoptimizeFunction(*function);
8209 
8210   return isolate->heap()->undefined_value();
8211 }
8212 
8213 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RunningInSimulator)8214 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8215 #if defined(USE_SIMULATOR)
8216   return isolate->heap()->true_value();
8217 #else
8218   return isolate->heap()->false_value();
8219 #endif
8220 }
8221 
8222 
RUNTIME_FUNCTION(MaybeObject *,Runtime_OptimizeFunctionOnNextCall)8223 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8224   HandleScope scope(isolate);
8225   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8226   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8227 
8228   if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8229   function->MarkForLazyRecompilation();
8230 
8231   Code* unoptimized = function->shared()->code();
8232   if (args.length() == 2 &&
8233       unoptimized->kind() == Code::FUNCTION) {
8234     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8235     CHECK(type->IsEqualTo(CStrVector("osr")));
8236     isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8237     unoptimized->set_allow_osr_at_loop_nesting_level(
8238         Code::kMaxLoopNestingMarker);
8239   }
8240 
8241   return isolate->heap()->undefined_value();
8242 }
8243 
8244 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetOptimizationStatus)8245 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8246   HandleScope scope(isolate);
8247   ASSERT(args.length() == 1);
8248   // The least significant bit (after untagging) indicates whether the
8249   // function is currently optimized, regardless of reason.
8250   if (!V8::UseCrankshaft()) {
8251     return Smi::FromInt(4);  // 4 == "never".
8252   }
8253   if (FLAG_always_opt) {
8254     return Smi::FromInt(3);  // 3 == "always".
8255   }
8256   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8257   return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8258                                  : Smi::FromInt(2);  // 2 == "no".
8259 }
8260 
8261 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetOptimizationCount)8262 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8263   HandleScope scope(isolate);
8264   ASSERT(args.length() == 1);
8265   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8266   return Smi::FromInt(function->shared()->opt_count());
8267 }
8268 
8269 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CompileForOnStackReplacement)8270 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8271   HandleScope scope(isolate);
8272   ASSERT(args.length() == 1);
8273   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8274 
8275   // We're not prepared to handle a function with arguments object.
8276   ASSERT(!function->shared()->uses_arguments());
8277 
8278   // We have hit a back edge in an unoptimized frame for a function that was
8279   // selected for on-stack replacement.  Find the unoptimized code object.
8280   Handle<Code> unoptimized(function->shared()->code(), isolate);
8281   // Keep track of whether we've succeeded in optimizing.
8282   bool succeeded = unoptimized->optimizable();
8283   if (succeeded) {
8284     // If we are trying to do OSR when there are already optimized
8285     // activations of the function, it means (a) the function is directly or
8286     // indirectly recursive and (b) an optimized invocation has been
8287     // deoptimized so that we are currently in an unoptimized activation.
8288     // Check for optimized activations of this function.
8289     JavaScriptFrameIterator it(isolate);
8290     while (succeeded && !it.done()) {
8291       JavaScriptFrame* frame = it.frame();
8292       succeeded = !frame->is_optimized() || frame->function() != *function;
8293       it.Advance();
8294     }
8295   }
8296 
8297   int ast_id = AstNode::kNoNumber;
8298   if (succeeded) {
8299     // The top JS function is this one, the PC is somewhere in the
8300     // unoptimized code.
8301     JavaScriptFrameIterator it(isolate);
8302     JavaScriptFrame* frame = it.frame();
8303     ASSERT(frame->function() == *function);
8304     ASSERT(frame->LookupCode() == *unoptimized);
8305     ASSERT(unoptimized->contains(frame->pc()));
8306 
8307     // Use linear search of the unoptimized code's stack check table to find
8308     // the AST id matching the PC.
8309     Address start = unoptimized->instruction_start();
8310     unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start);
8311     Address table_cursor = start + unoptimized->stack_check_table_offset();
8312     uint32_t table_length = Memory::uint32_at(table_cursor);
8313     table_cursor += kIntSize;
8314     for (unsigned i = 0; i < table_length; ++i) {
8315       // Table entries are (AST id, pc offset) pairs.
8316       uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize);
8317       if (pc_offset == target_pc_offset) {
8318         ast_id = static_cast<int>(Memory::uint32_at(table_cursor));
8319         break;
8320       }
8321       table_cursor += 2 * kIntSize;
8322     }
8323     ASSERT(ast_id != AstNode::kNoNumber);
8324     if (FLAG_trace_osr) {
8325       PrintF("[replacing on-stack at AST id %d in ", ast_id);
8326       function->PrintName();
8327       PrintF("]\n");
8328     }
8329 
8330     // Try to compile the optimized code.  A true return value from
8331     // CompileOptimized means that compilation succeeded, not necessarily
8332     // that optimization succeeded.
8333     if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
8334         function->IsOptimized()) {
8335       DeoptimizationInputData* data = DeoptimizationInputData::cast(
8336           function->code()->deoptimization_data());
8337       if (data->OsrPcOffset()->value() >= 0) {
8338         if (FLAG_trace_osr) {
8339           PrintF("[on-stack replacement offset %d in optimized code]\n",
8340                data->OsrPcOffset()->value());
8341         }
8342         ASSERT(data->OsrAstId()->value() == ast_id);
8343       } else {
8344         // We may never generate the desired OSR entry if we emit an
8345         // early deoptimize.
8346         succeeded = false;
8347       }
8348     } else {
8349       succeeded = false;
8350     }
8351   }
8352 
8353   // Revert to the original stack checks in the original unoptimized code.
8354   if (FLAG_trace_osr) {
8355     PrintF("[restoring original stack checks in ");
8356     function->PrintName();
8357     PrintF("]\n");
8358   }
8359   Handle<Code> check_code;
8360 #if defined(V8_TARGET_ARCH_IA32) || \
8361     defined(V8_TARGET_ARCH_ARM) || \
8362     defined(V8_TARGET_ARCH_MIPS)
8363   if (FLAG_count_based_interrupts) {
8364     InterruptStub interrupt_stub;
8365     check_code = interrupt_stub.GetCode();
8366   } else  // NOLINT
8367 #endif
8368   {  // NOLINT
8369     StackCheckStub check_stub;
8370     check_code = check_stub.GetCode();
8371   }
8372   Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
8373   Deoptimizer::RevertStackCheckCode(*unoptimized,
8374                                     *check_code,
8375                                     *replacement_code);
8376 
8377   // Allow OSR only at nesting level zero again.
8378   unoptimized->set_allow_osr_at_loop_nesting_level(0);
8379 
8380   // If the optimization attempt succeeded, return the AST id tagged as a
8381   // smi. This tells the builtin that we need to translate the unoptimized
8382   // frame to an optimized one.
8383   if (succeeded) {
8384     ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
8385     return Smi::FromInt(ast_id);
8386   } else {
8387     if (function->IsMarkedForLazyRecompilation()) {
8388       function->ReplaceCode(function->shared()->code());
8389     }
8390     return Smi::FromInt(-1);
8391   }
8392 }
8393 
8394 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CheckIsBootstrapping)8395 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8396   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8397   return isolate->heap()->undefined_value();
8398 }
8399 
8400 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetRootNaN)8401 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8402   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8403   return isolate->heap()->nan_value();
8404 }
8405 
8406 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Call)8407 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8408   HandleScope scope(isolate);
8409   ASSERT(args.length() >= 2);
8410   int argc = args.length() - 2;
8411   CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8412   Object* receiver = args[0];
8413 
8414   // If there are too many arguments, allocate argv via malloc.
8415   const int argv_small_size = 10;
8416   Handle<Object> argv_small_buffer[argv_small_size];
8417   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8418   Handle<Object>* argv = argv_small_buffer;
8419   if (argc > argv_small_size) {
8420     argv = new Handle<Object>[argc];
8421     if (argv == NULL) return isolate->StackOverflow();
8422     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8423   }
8424 
8425   for (int i = 0; i < argc; ++i) {
8426      MaybeObject* maybe = args[1 + i];
8427      Object* object;
8428      if (!maybe->To<Object>(&object)) return maybe;
8429      argv[i] = Handle<Object>(object);
8430   }
8431 
8432   bool threw;
8433   Handle<JSReceiver> hfun(fun);
8434   Handle<Object> hreceiver(receiver);
8435   Handle<Object> result =
8436       Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
8437 
8438   if (threw) return Failure::Exception();
8439   return *result;
8440 }
8441 
8442 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Apply)8443 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8444   HandleScope scope(isolate);
8445   ASSERT(args.length() == 5);
8446   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8447   Handle<Object> receiver = args.at<Object>(1);
8448   CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8449   CONVERT_SMI_ARG_CHECKED(offset, 3);
8450   CONVERT_SMI_ARG_CHECKED(argc, 4);
8451   ASSERT(offset >= 0);
8452   ASSERT(argc >= 0);
8453 
8454   // If there are too many arguments, allocate argv via malloc.
8455   const int argv_small_size = 10;
8456   Handle<Object> argv_small_buffer[argv_small_size];
8457   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8458   Handle<Object>* argv = argv_small_buffer;
8459   if (argc > argv_small_size) {
8460     argv = new Handle<Object>[argc];
8461     if (argv == NULL) return isolate->StackOverflow();
8462     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8463   }
8464 
8465   for (int i = 0; i < argc; ++i) {
8466     argv[i] = Object::GetElement(arguments, offset + i);
8467   }
8468 
8469   bool threw;
8470   Handle<Object> result =
8471       Execution::Call(fun, receiver, argc, argv, &threw, true);
8472 
8473   if (threw) return Failure::Exception();
8474   return *result;
8475 }
8476 
8477 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionDelegate)8478 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8479   HandleScope scope(isolate);
8480   ASSERT(args.length() == 1);
8481   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8482   return *Execution::GetFunctionDelegate(args.at<Object>(0));
8483 }
8484 
8485 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetConstructorDelegate)8486 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8487   HandleScope scope(isolate);
8488   ASSERT(args.length() == 1);
8489   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8490   return *Execution::GetConstructorDelegate(args.at<Object>(0));
8491 }
8492 
8493 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewFunctionContext)8494 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8495   NoHandleAllocation ha;
8496   ASSERT(args.length() == 1);
8497 
8498   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8499   int length = function->shared()->scope_info()->ContextLength();
8500   Object* result;
8501   { MaybeObject* maybe_result =
8502         isolate->heap()->AllocateFunctionContext(length, function);
8503     if (!maybe_result->ToObject(&result)) return maybe_result;
8504   }
8505 
8506   isolate->set_context(Context::cast(result));
8507 
8508   return result;  // non-failure
8509 }
8510 
8511 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushWithContext)8512 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8513   NoHandleAllocation ha;
8514   ASSERT(args.length() == 2);
8515   JSObject* extension_object;
8516   if (args[0]->IsJSObject()) {
8517     extension_object = JSObject::cast(args[0]);
8518   } else {
8519     // Convert the object to a proper JavaScript object.
8520     MaybeObject* maybe_js_object = args[0]->ToObject();
8521     if (!maybe_js_object->To(&extension_object)) {
8522       if (Failure::cast(maybe_js_object)->IsInternalError()) {
8523         HandleScope scope(isolate);
8524         Handle<Object> handle = args.at<Object>(0);
8525         Handle<Object> result =
8526             isolate->factory()->NewTypeError("with_expression",
8527                                              HandleVector(&handle, 1));
8528         return isolate->Throw(*result);
8529       } else {
8530         return maybe_js_object;
8531       }
8532     }
8533   }
8534 
8535   JSFunction* function;
8536   if (args[1]->IsSmi()) {
8537     // A smi sentinel indicates a context nested inside global code rather
8538     // than some function.  There is a canonical empty function that can be
8539     // gotten from the global context.
8540     function = isolate->context()->global_context()->closure();
8541   } else {
8542     function = JSFunction::cast(args[1]);
8543   }
8544 
8545   Context* context;
8546   MaybeObject* maybe_context =
8547       isolate->heap()->AllocateWithContext(function,
8548                                            isolate->context(),
8549                                            extension_object);
8550   if (!maybe_context->To(&context)) return maybe_context;
8551   isolate->set_context(context);
8552   return context;
8553 }
8554 
8555 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushCatchContext)8556 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8557   NoHandleAllocation ha;
8558   ASSERT(args.length() == 3);
8559   String* name = String::cast(args[0]);
8560   Object* thrown_object = args[1];
8561   JSFunction* function;
8562   if (args[2]->IsSmi()) {
8563     // A smi sentinel indicates a context nested inside global code rather
8564     // than some function.  There is a canonical empty function that can be
8565     // gotten from the global context.
8566     function = isolate->context()->global_context()->closure();
8567   } else {
8568     function = JSFunction::cast(args[2]);
8569   }
8570   Context* context;
8571   MaybeObject* maybe_context =
8572       isolate->heap()->AllocateCatchContext(function,
8573                                             isolate->context(),
8574                                             name,
8575                                             thrown_object);
8576   if (!maybe_context->To(&context)) return maybe_context;
8577   isolate->set_context(context);
8578   return context;
8579 }
8580 
8581 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushBlockContext)8582 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8583   NoHandleAllocation ha;
8584   ASSERT(args.length() == 2);
8585   ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8586   JSFunction* function;
8587   if (args[1]->IsSmi()) {
8588     // A smi sentinel indicates a context nested inside global code rather
8589     // than some function.  There is a canonical empty function that can be
8590     // gotten from the global context.
8591     function = isolate->context()->global_context()->closure();
8592   } else {
8593     function = JSFunction::cast(args[1]);
8594   }
8595   Context* context;
8596   MaybeObject* maybe_context =
8597       isolate->heap()->AllocateBlockContext(function,
8598                                             isolate->context(),
8599                                             scope_info);
8600   if (!maybe_context->To(&context)) return maybe_context;
8601   isolate->set_context(context);
8602   return context;
8603 }
8604 
8605 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteContextSlot)8606 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8607   HandleScope scope(isolate);
8608   ASSERT(args.length() == 2);
8609 
8610   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8611   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
8612 
8613   int index;
8614   PropertyAttributes attributes;
8615   ContextLookupFlags flags = FOLLOW_CHAINS;
8616   BindingFlags binding_flags;
8617   Handle<Object> holder = context->Lookup(name,
8618                                           flags,
8619                                           &index,
8620                                           &attributes,
8621                                           &binding_flags);
8622 
8623   // If the slot was not found the result is true.
8624   if (holder.is_null()) {
8625     return isolate->heap()->true_value();
8626   }
8627 
8628   // If the slot was found in a context, it should be DONT_DELETE.
8629   if (holder->IsContext()) {
8630     return isolate->heap()->false_value();
8631   }
8632 
8633   // The slot was found in a JSObject, either a context extension object,
8634   // the global object, or the subject of a with.  Try to delete it
8635   // (respecting DONT_DELETE).
8636   Handle<JSObject> object = Handle<JSObject>::cast(holder);
8637   return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
8638 }
8639 
8640 
8641 // A mechanism to return a pair of Object pointers in registers (if possible).
8642 // How this is achieved is calling convention-dependent.
8643 // All currently supported x86 compiles uses calling conventions that are cdecl
8644 // variants where a 64-bit value is returned in two 32-bit registers
8645 // (edx:eax on ia32, r1:r0 on ARM).
8646 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
8647 // In Win64 calling convention, a struct of two pointers is returned in memory,
8648 // allocated by the caller, and passed as a pointer in a hidden first parameter.
8649 #ifdef V8_HOST_ARCH_64_BIT
8650 struct ObjectPair {
8651   MaybeObject* x;
8652   MaybeObject* y;
8653 };
8654 
MakePair(MaybeObject * x,MaybeObject * y)8655 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8656   ObjectPair result = {x, y};
8657   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
8658   // In Win64 they are assigned to a hidden first argument.
8659   return result;
8660 }
8661 #else
8662 typedef uint64_t ObjectPair;
MakePair(MaybeObject * x,MaybeObject * y)8663 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8664   return reinterpret_cast<uint32_t>(x) |
8665       (reinterpret_cast<ObjectPair>(y) << 32);
8666 }
8667 #endif
8668 
8669 
Unhole(Heap * heap,MaybeObject * x,PropertyAttributes attributes)8670 static inline MaybeObject* Unhole(Heap* heap,
8671                                   MaybeObject* x,
8672                                   PropertyAttributes attributes) {
8673   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
8674   USE(attributes);
8675   return x->IsTheHole() ? heap->undefined_value() : x;
8676 }
8677 
8678 
ComputeReceiverForNonGlobal(Isolate * isolate,JSObject * holder)8679 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
8680                                            JSObject* holder) {
8681   ASSERT(!holder->IsGlobalObject());
8682   Context* top = isolate->context();
8683   // Get the context extension function.
8684   JSFunction* context_extension_function =
8685       top->global_context()->context_extension_function();
8686   // If the holder isn't a context extension object, we just return it
8687   // as the receiver. This allows arguments objects to be used as
8688   // receivers, but only if they are put in the context scope chain
8689   // explicitly via a with-statement.
8690   Object* constructor = holder->map()->constructor();
8691   if (constructor != context_extension_function) return holder;
8692   // Fall back to using the global object as the implicit receiver if
8693   // the property turns out to be a local variable allocated in a
8694   // context extension object - introduced via eval. Implicit global
8695   // receivers are indicated with the hole value.
8696   return isolate->heap()->the_hole_value();
8697 }
8698 
8699 
LoadContextSlotHelper(Arguments args,Isolate * isolate,bool throw_error)8700 static ObjectPair LoadContextSlotHelper(Arguments args,
8701                                         Isolate* isolate,
8702                                         bool throw_error) {
8703   HandleScope scope(isolate);
8704   ASSERT_EQ(2, args.length());
8705 
8706   if (!args[0]->IsContext() || !args[1]->IsString()) {
8707     return MakePair(isolate->ThrowIllegalOperation(), NULL);
8708   }
8709   Handle<Context> context = args.at<Context>(0);
8710   Handle<String> name = args.at<String>(1);
8711 
8712   int index;
8713   PropertyAttributes attributes;
8714   ContextLookupFlags flags = FOLLOW_CHAINS;
8715   BindingFlags binding_flags;
8716   Handle<Object> holder = context->Lookup(name,
8717                                           flags,
8718                                           &index,
8719                                           &attributes,
8720                                           &binding_flags);
8721 
8722   // If the index is non-negative, the slot has been found in a context.
8723   if (index >= 0) {
8724     ASSERT(holder->IsContext());
8725     // If the "property" we were looking for is a local variable, the
8726     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
8727     //
8728     // Use the hole as the receiver to signal that the receiver is implicit
8729     // and that the global receiver should be used (as distinguished from an
8730     // explicit receiver that happens to be a global object).
8731     Handle<Object> receiver = isolate->factory()->the_hole_value();
8732     Object* value = Context::cast(*holder)->get(index);
8733     // Check for uninitialized bindings.
8734     switch (binding_flags) {
8735       case MUTABLE_CHECK_INITIALIZED:
8736       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
8737         if (value->IsTheHole()) {
8738           Handle<Object> reference_error =
8739               isolate->factory()->NewReferenceError("not_defined",
8740                                                     HandleVector(&name, 1));
8741           return MakePair(isolate->Throw(*reference_error), NULL);
8742         }
8743         // FALLTHROUGH
8744       case MUTABLE_IS_INITIALIZED:
8745       case IMMUTABLE_IS_INITIALIZED:
8746       case IMMUTABLE_IS_INITIALIZED_HARMONY:
8747         ASSERT(!value->IsTheHole());
8748         return MakePair(value, *receiver);
8749       case IMMUTABLE_CHECK_INITIALIZED:
8750         return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
8751       case MISSING_BINDING:
8752         UNREACHABLE();
8753         return MakePair(NULL, NULL);
8754     }
8755   }
8756 
8757   // Otherwise, if the slot was found the holder is a context extension
8758   // object, subject of a with, or a global object.  We read the named
8759   // property from it.
8760   if (!holder.is_null()) {
8761     Handle<JSObject> object = Handle<JSObject>::cast(holder);
8762     ASSERT(object->HasProperty(*name));
8763     // GetProperty below can cause GC.
8764     Handle<Object> receiver_handle(object->IsGlobalObject()
8765         ? GlobalObject::cast(*object)->global_receiver()
8766         : ComputeReceiverForNonGlobal(isolate, *object));
8767 
8768     // No need to unhole the value here.  This is taken care of by the
8769     // GetProperty function.
8770     MaybeObject* value = object->GetProperty(*name);
8771     return MakePair(value, *receiver_handle);
8772   }
8773 
8774   if (throw_error) {
8775     // The property doesn't exist - throw exception.
8776     Handle<Object> reference_error =
8777         isolate->factory()->NewReferenceError("not_defined",
8778                                               HandleVector(&name, 1));
8779     return MakePair(isolate->Throw(*reference_error), NULL);
8780   } else {
8781     // The property doesn't exist - return undefined.
8782     return MakePair(isolate->heap()->undefined_value(),
8783                     isolate->heap()->undefined_value());
8784   }
8785 }
8786 
8787 
RUNTIME_FUNCTION(ObjectPair,Runtime_LoadContextSlot)8788 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
8789   return LoadContextSlotHelper(args, isolate, true);
8790 }
8791 
8792 
RUNTIME_FUNCTION(ObjectPair,Runtime_LoadContextSlotNoReferenceError)8793 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
8794   return LoadContextSlotHelper(args, isolate, false);
8795 }
8796 
8797 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StoreContextSlot)8798 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
8799   HandleScope scope(isolate);
8800   ASSERT(args.length() == 4);
8801 
8802   Handle<Object> value(args[0], isolate);
8803   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
8804   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
8805   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
8806   StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
8807       ? kNonStrictMode : kStrictMode;
8808 
8809   int index;
8810   PropertyAttributes attributes;
8811   ContextLookupFlags flags = FOLLOW_CHAINS;
8812   BindingFlags binding_flags;
8813   Handle<Object> holder = context->Lookup(name,
8814                                           flags,
8815                                           &index,
8816                                           &attributes,
8817                                           &binding_flags);
8818 
8819   if (index >= 0) {
8820     // The property was found in a context slot.
8821     Handle<Context> context = Handle<Context>::cast(holder);
8822     if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
8823         context->get(index)->IsTheHole()) {
8824       Handle<Object> error =
8825           isolate->factory()->NewReferenceError("not_defined",
8826                                                 HandleVector(&name, 1));
8827       return isolate->Throw(*error);
8828     }
8829     // Ignore if read_only variable.
8830     if ((attributes & READ_ONLY) == 0) {
8831       // Context is a fixed array and set cannot fail.
8832       context->set(index, *value);
8833     } else if (strict_mode == kStrictMode) {
8834       // Setting read only property in strict mode.
8835       Handle<Object> error =
8836           isolate->factory()->NewTypeError("strict_cannot_assign",
8837                                            HandleVector(&name, 1));
8838       return isolate->Throw(*error);
8839     }
8840     return *value;
8841   }
8842 
8843   // Slow case: The property is not in a context slot.  It is either in a
8844   // context extension object, a property of the subject of a with, or a
8845   // property of the global object.
8846   Handle<JSObject> object;
8847 
8848   if (!holder.is_null()) {
8849     // The property exists on the holder.
8850     object = Handle<JSObject>::cast(holder);
8851   } else {
8852     // The property was not found.
8853     ASSERT(attributes == ABSENT);
8854 
8855     if (strict_mode == kStrictMode) {
8856       // Throw in strict mode (assignment to undefined variable).
8857       Handle<Object> error =
8858           isolate->factory()->NewReferenceError(
8859               "not_defined", HandleVector(&name, 1));
8860       return isolate->Throw(*error);
8861     }
8862     // In non-strict mode, the property is added to the global object.
8863     attributes = NONE;
8864     object = Handle<JSObject>(isolate->context()->global());
8865   }
8866 
8867   // Set the property if it's not read only or doesn't yet exist.
8868   if ((attributes & READ_ONLY) == 0 ||
8869       (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
8870     RETURN_IF_EMPTY_HANDLE(
8871         isolate,
8872         JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
8873   } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
8874     // Setting read only property in strict mode.
8875     Handle<Object> error =
8876       isolate->factory()->NewTypeError(
8877           "strict_cannot_assign", HandleVector(&name, 1));
8878     return isolate->Throw(*error);
8879   }
8880   return *value;
8881 }
8882 
8883 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Throw)8884 RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
8885   HandleScope scope(isolate);
8886   ASSERT(args.length() == 1);
8887 
8888   return isolate->Throw(args[0]);
8889 }
8890 
8891 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ReThrow)8892 RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
8893   HandleScope scope(isolate);
8894   ASSERT(args.length() == 1);
8895 
8896   return isolate->ReThrow(args[0]);
8897 }
8898 
8899 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PromoteScheduledException)8900 RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
8901   ASSERT_EQ(0, args.length());
8902   return isolate->PromoteScheduledException();
8903 }
8904 
8905 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ThrowReferenceError)8906 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
8907   HandleScope scope(isolate);
8908   ASSERT(args.length() == 1);
8909 
8910   Handle<Object> name(args[0], isolate);
8911   Handle<Object> reference_error =
8912     isolate->factory()->NewReferenceError("not_defined",
8913                                           HandleVector(&name, 1));
8914   return isolate->Throw(*reference_error);
8915 }
8916 
8917 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StackGuard)8918 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
8919   ASSERT(args.length() == 0);
8920 
8921   // First check if this is a real stack overflow.
8922   if (isolate->stack_guard()->IsStackOverflow()) {
8923     NoHandleAllocation na;
8924     return isolate->StackOverflow();
8925   }
8926 
8927   return Execution::HandleStackGuardInterrupt(isolate);
8928 }
8929 
8930 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Interrupt)8931 RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
8932   ASSERT(args.length() == 0);
8933   return Execution::HandleStackGuardInterrupt(isolate);
8934 }
8935 
8936 
StackSize()8937 static int StackSize() {
8938   int n = 0;
8939   for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
8940   return n;
8941 }
8942 
8943 
PrintTransition(Object * result)8944 static void PrintTransition(Object* result) {
8945   // indentation
8946   { const int nmax = 80;
8947     int n = StackSize();
8948     if (n <= nmax)
8949       PrintF("%4d:%*s", n, n, "");
8950     else
8951       PrintF("%4d:%*s", n, nmax, "...");
8952   }
8953 
8954   if (result == NULL) {
8955     JavaScriptFrame::PrintTop(stdout, true, false);
8956     PrintF(" {\n");
8957   } else {
8958     // function result
8959     PrintF("} -> ");
8960     result->ShortPrint();
8961     PrintF("\n");
8962   }
8963 }
8964 
8965 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TraceEnter)8966 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
8967   ASSERT(args.length() == 0);
8968   NoHandleAllocation ha;
8969   PrintTransition(NULL);
8970   return isolate->heap()->undefined_value();
8971 }
8972 
8973 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TraceExit)8974 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
8975   NoHandleAllocation ha;
8976   PrintTransition(args[0]);
8977   return args[0];  // return TOS
8978 }
8979 
8980 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPrint)8981 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
8982   NoHandleAllocation ha;
8983   ASSERT(args.length() == 1);
8984 
8985 #ifdef DEBUG
8986   if (args[0]->IsString()) {
8987     // If we have a string, assume it's a code "marker"
8988     // and print some interesting cpu debugging info.
8989     JavaScriptFrameIterator it(isolate);
8990     JavaScriptFrame* frame = it.frame();
8991     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
8992            frame->fp(), frame->sp(), frame->caller_sp());
8993   } else {
8994     PrintF("DebugPrint: ");
8995   }
8996   args[0]->Print();
8997   if (args[0]->IsHeapObject()) {
8998     PrintF("\n");
8999     HeapObject::cast(args[0])->map()->Print();
9000   }
9001 #else
9002   // ShortPrint is available in release mode. Print is not.
9003   args[0]->ShortPrint();
9004 #endif
9005   PrintF("\n");
9006   Flush();
9007 
9008   return args[0];  // return TOS
9009 }
9010 
9011 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugTrace)9012 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9013   ASSERT(args.length() == 0);
9014   NoHandleAllocation ha;
9015   isolate->PrintStack();
9016   return isolate->heap()->undefined_value();
9017 }
9018 
9019 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateCurrentTime)9020 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9021   NoHandleAllocation ha;
9022   ASSERT(args.length() == 0);
9023 
9024   // According to ECMA-262, section 15.9.1, page 117, the precision of
9025   // the number in a Date object representing a particular instant in
9026   // time is milliseconds. Therefore, we floor the result of getting
9027   // the OS time.
9028   double millis = floor(OS::TimeCurrentMillis());
9029   return isolate->heap()->NumberFromDouble(millis);
9030 }
9031 
9032 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateParseString)9033 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9034   HandleScope scope(isolate);
9035   ASSERT(args.length() == 2);
9036 
9037   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9038   FlattenString(str);
9039 
9040   CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9041 
9042   MaybeObject* maybe_result_array =
9043       output->EnsureCanContainHeapObjectElements();
9044   if (maybe_result_array->IsFailure()) return maybe_result_array;
9045   RUNTIME_ASSERT(output->HasFastElements());
9046 
9047   AssertNoAllocation no_allocation;
9048 
9049   FixedArray* output_array = FixedArray::cast(output->elements());
9050   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9051   bool result;
9052   String::FlatContent str_content = str->GetFlatContent();
9053   if (str_content.IsAscii()) {
9054     result = DateParser::Parse(str_content.ToAsciiVector(),
9055                                output_array,
9056                                isolate->unicode_cache());
9057   } else {
9058     ASSERT(str_content.IsTwoByte());
9059     result = DateParser::Parse(str_content.ToUC16Vector(),
9060                                output_array,
9061                                isolate->unicode_cache());
9062   }
9063 
9064   if (result) {
9065     return *output;
9066   } else {
9067     return isolate->heap()->null_value();
9068   }
9069 }
9070 
9071 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateLocalTimezone)9072 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9073   NoHandleAllocation ha;
9074   ASSERT(args.length() == 1);
9075 
9076   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9077   int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9078   const char* zone = OS::LocalTimezone(static_cast<double>(time));
9079   return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9080 }
9081 
9082 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateToUTC)9083 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9084   NoHandleAllocation ha;
9085   ASSERT(args.length() == 1);
9086 
9087   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9088   int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9089 
9090   return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9091 }
9092 
9093 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GlobalReceiver)9094 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9095   ASSERT(args.length() == 1);
9096   Object* global = args[0];
9097   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9098   return JSGlobalObject::cast(global)->global_receiver();
9099 }
9100 
9101 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ParseJson)9102 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9103   HandleScope scope(isolate);
9104   ASSERT_EQ(1, args.length());
9105   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9106 
9107   source = Handle<String>(source->TryFlattenGetString());
9108   // Optimized fast case where we only have ASCII characters.
9109   Handle<Object> result;
9110   if (source->IsSeqAsciiString()) {
9111     result = JsonParser<true>::Parse(source);
9112   } else {
9113     result = JsonParser<false>::Parse(source);
9114   }
9115   if (result.is_null()) {
9116     // Syntax error or stack overflow in scanner.
9117     ASSERT(isolate->has_pending_exception());
9118     return Failure::Exception();
9119   }
9120   return *result;
9121 }
9122 
9123 
CodeGenerationFromStringsAllowed(Isolate * isolate,Handle<Context> context)9124 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9125                                       Handle<Context> context) {
9126   ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9127   // Check with callback if set.
9128   AllowCodeGenerationFromStringsCallback callback =
9129       isolate->allow_code_gen_callback();
9130   if (callback == NULL) {
9131     // No callback set and code generation disallowed.
9132     return false;
9133   } else {
9134     // Callback set. Let it decide if code generation is allowed.
9135     VMState state(isolate, EXTERNAL);
9136     return callback(v8::Utils::ToLocal(context));
9137   }
9138 }
9139 
9140 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CompileString)9141 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9142   HandleScope scope(isolate);
9143   ASSERT_EQ(1, args.length());
9144   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9145 
9146   // Extract global context.
9147   Handle<Context> context(isolate->context()->global_context());
9148 
9149   // Check if global context allows code generation from
9150   // strings. Throw an exception if it doesn't.
9151   if (context->allow_code_gen_from_strings()->IsFalse() &&
9152       !CodeGenerationFromStringsAllowed(isolate, context)) {
9153     return isolate->Throw(*isolate->factory()->NewError(
9154         "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9155   }
9156 
9157   // Compile source string in the global context.
9158   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9159       source, context, true, CLASSIC_MODE, RelocInfo::kNoPosition);
9160   if (shared.is_null()) return Failure::Exception();
9161   Handle<JSFunction> fun =
9162       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9163                                                             context,
9164                                                             NOT_TENURED);
9165   return *fun;
9166 }
9167 
9168 
CompileGlobalEval(Isolate * isolate,Handle<String> source,Handle<Object> receiver,LanguageMode language_mode,int scope_position)9169 static ObjectPair CompileGlobalEval(Isolate* isolate,
9170                                     Handle<String> source,
9171                                     Handle<Object> receiver,
9172                                     LanguageMode language_mode,
9173                                     int scope_position) {
9174   Handle<Context> context = Handle<Context>(isolate->context());
9175   Handle<Context> global_context = Handle<Context>(context->global_context());
9176 
9177   // Check if global context allows code generation from
9178   // strings. Throw an exception if it doesn't.
9179   if (global_context->allow_code_gen_from_strings()->IsFalse() &&
9180       !CodeGenerationFromStringsAllowed(isolate, global_context)) {
9181     isolate->Throw(*isolate->factory()->NewError(
9182         "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9183     return MakePair(Failure::Exception(), NULL);
9184   }
9185 
9186   // Deal with a normal eval call with a string argument. Compile it
9187   // and return the compiled function bound in the local context.
9188   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9189       source,
9190       Handle<Context>(isolate->context()),
9191       context->IsGlobalContext(),
9192       language_mode,
9193       scope_position);
9194   if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
9195   Handle<JSFunction> compiled =
9196       isolate->factory()->NewFunctionFromSharedFunctionInfo(
9197           shared, context, NOT_TENURED);
9198   return MakePair(*compiled, *receiver);
9199 }
9200 
9201 
RUNTIME_FUNCTION(ObjectPair,Runtime_ResolvePossiblyDirectEval)9202 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9203   ASSERT(args.length() == 5);
9204 
9205   HandleScope scope(isolate);
9206   Handle<Object> callee = args.at<Object>(0);
9207 
9208   // If "eval" didn't refer to the original GlobalEval, it's not a
9209   // direct call to eval.
9210   // (And even if it is, but the first argument isn't a string, just let
9211   // execution default to an indirect call to eval, which will also return
9212   // the first argument without doing anything).
9213   if (*callee != isolate->global_context()->global_eval_fun() ||
9214       !args[1]->IsString()) {
9215     return MakePair(*callee, isolate->heap()->the_hole_value());
9216   }
9217 
9218   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9219   ASSERT(args[4]->IsSmi());
9220   return CompileGlobalEval(isolate,
9221                            args.at<String>(1),
9222                            args.at<Object>(2),
9223                            language_mode,
9224                            args.smi_at(4));
9225 }
9226 
9227 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetNewFunctionAttributes)9228 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) {
9229   // This utility adjusts the property attributes for newly created Function
9230   // object ("new Function(...)") by changing the map.
9231   // All it does is changing the prototype property to enumerable
9232   // as specified in ECMA262, 15.3.5.2.
9233   HandleScope scope(isolate);
9234   ASSERT(args.length() == 1);
9235   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
9236 
9237   Handle<Map> map = func->shared()->is_classic_mode()
9238       ? isolate->function_instance_map()
9239       : isolate->strict_mode_function_instance_map();
9240 
9241   ASSERT(func->map()->instance_type() == map->instance_type());
9242   ASSERT(func->map()->instance_size() == map->instance_size());
9243   func->set_map(*map);
9244   return *func;
9245 }
9246 
9247 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AllocateInNewSpace)9248 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9249   // Allocate a block of memory in NewSpace (filled with a filler).
9250   // Use as fallback for allocation in generated code when NewSpace
9251   // is full.
9252   ASSERT(args.length() == 1);
9253   CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9254   int size = size_smi->value();
9255   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9256   RUNTIME_ASSERT(size > 0);
9257   Heap* heap = isolate->heap();
9258   const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
9259   RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
9260   Object* allocation;
9261   { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
9262     if (maybe_allocation->ToObject(&allocation)) {
9263       heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9264     }
9265     return maybe_allocation;
9266   }
9267 }
9268 
9269 
9270 // Push an object unto an array of objects if it is not already in the
9271 // array.  Returns true if the element was pushed on the stack and
9272 // false otherwise.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushIfAbsent)9273 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9274   ASSERT(args.length() == 2);
9275   CONVERT_ARG_CHECKED(JSArray, array, 0);
9276   CONVERT_ARG_CHECKED(JSObject, element, 1);
9277   RUNTIME_ASSERT(array->HasFastElements() || array->HasFastSmiOnlyElements());
9278   int length = Smi::cast(array->length())->value();
9279   FixedArray* elements = FixedArray::cast(array->elements());
9280   for (int i = 0; i < length; i++) {
9281     if (elements->get(i) == element) return isolate->heap()->false_value();
9282   }
9283   Object* obj;
9284   // Strict not needed. Used for cycle detection in Array join implementation.
9285   { MaybeObject* maybe_obj =
9286         array->SetFastElement(length, element, kNonStrictMode, true);
9287     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9288   }
9289   return isolate->heap()->true_value();
9290 }
9291 
9292 
9293 /**
9294  * A simple visitor visits every element of Array's.
9295  * The backend storage can be a fixed array for fast elements case,
9296  * or a dictionary for sparse array. Since Dictionary is a subtype
9297  * of FixedArray, the class can be used by both fast and slow cases.
9298  * The second parameter of the constructor, fast_elements, specifies
9299  * whether the storage is a FixedArray or Dictionary.
9300  *
9301  * An index limit is used to deal with the situation that a result array
9302  * length overflows 32-bit non-negative integer.
9303  */
9304 class ArrayConcatVisitor {
9305  public:
ArrayConcatVisitor(Isolate * isolate,Handle<FixedArray> storage,bool fast_elements)9306   ArrayConcatVisitor(Isolate* isolate,
9307                      Handle<FixedArray> storage,
9308                      bool fast_elements) :
9309       isolate_(isolate),
9310       storage_(Handle<FixedArray>::cast(
9311           isolate->global_handles()->Create(*storage))),
9312       index_offset_(0u),
9313       fast_elements_(fast_elements) { }
9314 
~ArrayConcatVisitor()9315   ~ArrayConcatVisitor() {
9316     clear_storage();
9317   }
9318 
visit(uint32_t i,Handle<Object> elm)9319   void visit(uint32_t i, Handle<Object> elm) {
9320     if (i >= JSObject::kMaxElementCount - index_offset_) return;
9321     uint32_t index = index_offset_ + i;
9322 
9323     if (fast_elements_) {
9324       if (index < static_cast<uint32_t>(storage_->length())) {
9325         storage_->set(index, *elm);
9326         return;
9327       }
9328       // Our initial estimate of length was foiled, possibly by
9329       // getters on the arrays increasing the length of later arrays
9330       // during iteration.
9331       // This shouldn't happen in anything but pathological cases.
9332       SetDictionaryMode(index);
9333       // Fall-through to dictionary mode.
9334     }
9335     ASSERT(!fast_elements_);
9336     Handle<SeededNumberDictionary> dict(
9337         SeededNumberDictionary::cast(*storage_));
9338     Handle<SeededNumberDictionary> result =
9339         isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9340     if (!result.is_identical_to(dict)) {
9341       // Dictionary needed to grow.
9342       clear_storage();
9343       set_storage(*result);
9344     }
9345 }
9346 
increase_index_offset(uint32_t delta)9347   void increase_index_offset(uint32_t delta) {
9348     if (JSObject::kMaxElementCount - index_offset_ < delta) {
9349       index_offset_ = JSObject::kMaxElementCount;
9350     } else {
9351       index_offset_ += delta;
9352     }
9353   }
9354 
ToArray()9355   Handle<JSArray> ToArray() {
9356     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9357     Handle<Object> length =
9358         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9359     Handle<Map> map;
9360     if (fast_elements_) {
9361       map = isolate_->factory()->GetElementsTransitionMap(array,
9362                                                           FAST_ELEMENTS);
9363     } else {
9364       map = isolate_->factory()->GetElementsTransitionMap(array,
9365                                                           DICTIONARY_ELEMENTS);
9366     }
9367     array->set_map(*map);
9368     array->set_length(*length);
9369     array->set_elements(*storage_);
9370     return array;
9371   }
9372 
9373  private:
9374   // Convert storage to dictionary mode.
SetDictionaryMode(uint32_t index)9375   void SetDictionaryMode(uint32_t index) {
9376     ASSERT(fast_elements_);
9377     Handle<FixedArray> current_storage(*storage_);
9378     Handle<SeededNumberDictionary> slow_storage(
9379         isolate_->factory()->NewSeededNumberDictionary(
9380             current_storage->length()));
9381     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9382     for (uint32_t i = 0; i < current_length; i++) {
9383       HandleScope loop_scope;
9384       Handle<Object> element(current_storage->get(i));
9385       if (!element->IsTheHole()) {
9386         Handle<SeededNumberDictionary> new_storage =
9387           isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9388         if (!new_storage.is_identical_to(slow_storage)) {
9389           slow_storage = loop_scope.CloseAndEscape(new_storage);
9390         }
9391       }
9392     }
9393     clear_storage();
9394     set_storage(*slow_storage);
9395     fast_elements_ = false;
9396   }
9397 
clear_storage()9398   inline void clear_storage() {
9399     isolate_->global_handles()->Destroy(
9400         Handle<Object>::cast(storage_).location());
9401   }
9402 
set_storage(FixedArray * storage)9403   inline void set_storage(FixedArray* storage) {
9404     storage_ = Handle<FixedArray>::cast(
9405         isolate_->global_handles()->Create(storage));
9406   }
9407 
9408   Isolate* isolate_;
9409   Handle<FixedArray> storage_;  // Always a global handle.
9410   // Index after last seen index. Always less than or equal to
9411   // JSObject::kMaxElementCount.
9412   uint32_t index_offset_;
9413   bool fast_elements_;
9414 };
9415 
9416 
EstimateElementCount(Handle<JSArray> array)9417 static uint32_t EstimateElementCount(Handle<JSArray> array) {
9418   uint32_t length = static_cast<uint32_t>(array->length()->Number());
9419   int element_count = 0;
9420   switch (array->GetElementsKind()) {
9421     case FAST_SMI_ONLY_ELEMENTS:
9422     case FAST_ELEMENTS: {
9423       // Fast elements can't have lengths that are not representable by
9424       // a 32-bit signed integer.
9425       ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9426       int fast_length = static_cast<int>(length);
9427       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9428       for (int i = 0; i < fast_length; i++) {
9429         if (!elements->get(i)->IsTheHole()) element_count++;
9430       }
9431       break;
9432     }
9433     case FAST_DOUBLE_ELEMENTS:
9434       // TODO(1810): Decide if it's worthwhile to implement this.
9435       UNREACHABLE();
9436       break;
9437     case DICTIONARY_ELEMENTS: {
9438       Handle<SeededNumberDictionary> dictionary(
9439           SeededNumberDictionary::cast(array->elements()));
9440       int capacity = dictionary->Capacity();
9441       for (int i = 0; i < capacity; i++) {
9442         Handle<Object> key(dictionary->KeyAt(i));
9443         if (dictionary->IsKey(*key)) {
9444           element_count++;
9445         }
9446       }
9447       break;
9448     }
9449     case NON_STRICT_ARGUMENTS_ELEMENTS:
9450     case EXTERNAL_BYTE_ELEMENTS:
9451     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9452     case EXTERNAL_SHORT_ELEMENTS:
9453     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9454     case EXTERNAL_INT_ELEMENTS:
9455     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9456     case EXTERNAL_FLOAT_ELEMENTS:
9457     case EXTERNAL_DOUBLE_ELEMENTS:
9458     case EXTERNAL_PIXEL_ELEMENTS:
9459       // External arrays are always dense.
9460       return length;
9461   }
9462   // As an estimate, we assume that the prototype doesn't contain any
9463   // inherited elements.
9464   return element_count;
9465 }
9466 
9467 
9468 
9469 template<class ExternalArrayClass, class ElementType>
IterateExternalArrayElements(Isolate * isolate,Handle<JSObject> receiver,bool elements_are_ints,bool elements_are_guaranteed_smis,ArrayConcatVisitor * visitor)9470 static void IterateExternalArrayElements(Isolate* isolate,
9471                                          Handle<JSObject> receiver,
9472                                          bool elements_are_ints,
9473                                          bool elements_are_guaranteed_smis,
9474                                          ArrayConcatVisitor* visitor) {
9475   Handle<ExternalArrayClass> array(
9476       ExternalArrayClass::cast(receiver->elements()));
9477   uint32_t len = static_cast<uint32_t>(array->length());
9478 
9479   ASSERT(visitor != NULL);
9480   if (elements_are_ints) {
9481     if (elements_are_guaranteed_smis) {
9482       for (uint32_t j = 0; j < len; j++) {
9483         HandleScope loop_scope;
9484         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))));
9485         visitor->visit(j, e);
9486       }
9487     } else {
9488       for (uint32_t j = 0; j < len; j++) {
9489         HandleScope loop_scope;
9490         int64_t val = static_cast<int64_t>(array->get_scalar(j));
9491         if (Smi::IsValid(static_cast<intptr_t>(val))) {
9492           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
9493           visitor->visit(j, e);
9494         } else {
9495           Handle<Object> e =
9496               isolate->factory()->NewNumber(static_cast<ElementType>(val));
9497           visitor->visit(j, e);
9498         }
9499       }
9500     }
9501   } else {
9502     for (uint32_t j = 0; j < len; j++) {
9503       HandleScope loop_scope(isolate);
9504       Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
9505       visitor->visit(j, e);
9506     }
9507   }
9508 }
9509 
9510 
9511 // Used for sorting indices in a List<uint32_t>.
compareUInt32(const uint32_t * ap,const uint32_t * bp)9512 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
9513   uint32_t a = *ap;
9514   uint32_t b = *bp;
9515   return (a == b) ? 0 : (a < b) ? -1 : 1;
9516 }
9517 
9518 
CollectElementIndices(Handle<JSObject> object,uint32_t range,List<uint32_t> * indices)9519 static void CollectElementIndices(Handle<JSObject> object,
9520                                   uint32_t range,
9521                                   List<uint32_t>* indices) {
9522   ElementsKind kind = object->GetElementsKind();
9523   switch (kind) {
9524     case FAST_SMI_ONLY_ELEMENTS:
9525     case FAST_ELEMENTS: {
9526       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
9527       uint32_t length = static_cast<uint32_t>(elements->length());
9528       if (range < length) length = range;
9529       for (uint32_t i = 0; i < length; i++) {
9530         if (!elements->get(i)->IsTheHole()) {
9531           indices->Add(i);
9532         }
9533       }
9534       break;
9535     }
9536     case FAST_DOUBLE_ELEMENTS: {
9537       // TODO(1810): Decide if it's worthwhile to implement this.
9538       UNREACHABLE();
9539       break;
9540     }
9541     case DICTIONARY_ELEMENTS: {
9542       Handle<SeededNumberDictionary> dict(
9543           SeededNumberDictionary::cast(object->elements()));
9544       uint32_t capacity = dict->Capacity();
9545       for (uint32_t j = 0; j < capacity; j++) {
9546         HandleScope loop_scope;
9547         Handle<Object> k(dict->KeyAt(j));
9548         if (dict->IsKey(*k)) {
9549           ASSERT(k->IsNumber());
9550           uint32_t index = static_cast<uint32_t>(k->Number());
9551           if (index < range) {
9552             indices->Add(index);
9553           }
9554         }
9555       }
9556       break;
9557     }
9558     default: {
9559       int dense_elements_length;
9560       switch (kind) {
9561         case EXTERNAL_PIXEL_ELEMENTS: {
9562           dense_elements_length =
9563               ExternalPixelArray::cast(object->elements())->length();
9564           break;
9565         }
9566         case EXTERNAL_BYTE_ELEMENTS: {
9567           dense_elements_length =
9568               ExternalByteArray::cast(object->elements())->length();
9569           break;
9570         }
9571         case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9572           dense_elements_length =
9573               ExternalUnsignedByteArray::cast(object->elements())->length();
9574           break;
9575         }
9576         case EXTERNAL_SHORT_ELEMENTS: {
9577           dense_elements_length =
9578               ExternalShortArray::cast(object->elements())->length();
9579           break;
9580         }
9581         case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9582           dense_elements_length =
9583               ExternalUnsignedShortArray::cast(object->elements())->length();
9584           break;
9585         }
9586         case EXTERNAL_INT_ELEMENTS: {
9587           dense_elements_length =
9588               ExternalIntArray::cast(object->elements())->length();
9589           break;
9590         }
9591         case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9592           dense_elements_length =
9593               ExternalUnsignedIntArray::cast(object->elements())->length();
9594           break;
9595         }
9596         case EXTERNAL_FLOAT_ELEMENTS: {
9597           dense_elements_length =
9598               ExternalFloatArray::cast(object->elements())->length();
9599           break;
9600         }
9601         case EXTERNAL_DOUBLE_ELEMENTS: {
9602           dense_elements_length =
9603               ExternalDoubleArray::cast(object->elements())->length();
9604           break;
9605         }
9606         default:
9607           UNREACHABLE();
9608           dense_elements_length = 0;
9609           break;
9610       }
9611       uint32_t length = static_cast<uint32_t>(dense_elements_length);
9612       if (range <= length) {
9613         length = range;
9614         // We will add all indices, so we might as well clear it first
9615         // and avoid duplicates.
9616         indices->Clear();
9617       }
9618       for (uint32_t i = 0; i < length; i++) {
9619         indices->Add(i);
9620       }
9621       if (length == range) return;  // All indices accounted for already.
9622       break;
9623     }
9624   }
9625 
9626   Handle<Object> prototype(object->GetPrototype());
9627   if (prototype->IsJSObject()) {
9628     // The prototype will usually have no inherited element indices,
9629     // but we have to check.
9630     CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
9631   }
9632 }
9633 
9634 
9635 /**
9636  * A helper function that visits elements of a JSArray in numerical
9637  * order.
9638  *
9639  * The visitor argument called for each existing element in the array
9640  * with the element index and the element's value.
9641  * Afterwards it increments the base-index of the visitor by the array
9642  * length.
9643  * Returns false if any access threw an exception, otherwise true.
9644  */
IterateElements(Isolate * isolate,Handle<JSArray> receiver,ArrayConcatVisitor * visitor)9645 static bool IterateElements(Isolate* isolate,
9646                             Handle<JSArray> receiver,
9647                             ArrayConcatVisitor* visitor) {
9648   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
9649   switch (receiver->GetElementsKind()) {
9650     case FAST_SMI_ONLY_ELEMENTS:
9651     case FAST_ELEMENTS: {
9652       // Run through the elements FixedArray and use HasElement and GetElement
9653       // to check the prototype for missing elements.
9654       Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
9655       int fast_length = static_cast<int>(length);
9656       ASSERT(fast_length <= elements->length());
9657       for (int j = 0; j < fast_length; j++) {
9658         HandleScope loop_scope(isolate);
9659         Handle<Object> element_value(elements->get(j), isolate);
9660         if (!element_value->IsTheHole()) {
9661           visitor->visit(j, element_value);
9662         } else if (receiver->HasElement(j)) {
9663           // Call GetElement on receiver, not its prototype, or getters won't
9664           // have the correct receiver.
9665           element_value = Object::GetElement(receiver, j);
9666           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
9667           visitor->visit(j, element_value);
9668         }
9669       }
9670       break;
9671     }
9672     case FAST_DOUBLE_ELEMENTS: {
9673       // TODO(1810): Decide if it's worthwhile to implement this.
9674       UNREACHABLE();
9675       break;
9676     }
9677     case DICTIONARY_ELEMENTS: {
9678       Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
9679       List<uint32_t> indices(dict->Capacity() / 2);
9680       // Collect all indices in the object and the prototypes less
9681       // than length. This might introduce duplicates in the indices list.
9682       CollectElementIndices(receiver, length, &indices);
9683       indices.Sort(&compareUInt32);
9684       int j = 0;
9685       int n = indices.length();
9686       while (j < n) {
9687         HandleScope loop_scope;
9688         uint32_t index = indices[j];
9689         Handle<Object> element = Object::GetElement(receiver, index);
9690         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
9691         visitor->visit(index, element);
9692         // Skip to next different index (i.e., omit duplicates).
9693         do {
9694           j++;
9695         } while (j < n && indices[j] == index);
9696       }
9697       break;
9698     }
9699     case EXTERNAL_PIXEL_ELEMENTS: {
9700       Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
9701           receiver->elements()));
9702       for (uint32_t j = 0; j < length; j++) {
9703         Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)));
9704         visitor->visit(j, e);
9705       }
9706       break;
9707     }
9708     case EXTERNAL_BYTE_ELEMENTS: {
9709       IterateExternalArrayElements<ExternalByteArray, int8_t>(
9710           isolate, receiver, true, true, visitor);
9711       break;
9712     }
9713     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9714       IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
9715           isolate, receiver, true, true, visitor);
9716       break;
9717     }
9718     case EXTERNAL_SHORT_ELEMENTS: {
9719       IterateExternalArrayElements<ExternalShortArray, int16_t>(
9720           isolate, receiver, true, true, visitor);
9721       break;
9722     }
9723     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9724       IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
9725           isolate, receiver, true, true, visitor);
9726       break;
9727     }
9728     case EXTERNAL_INT_ELEMENTS: {
9729       IterateExternalArrayElements<ExternalIntArray, int32_t>(
9730           isolate, receiver, true, false, visitor);
9731       break;
9732     }
9733     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9734       IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
9735           isolate, receiver, true, false, visitor);
9736       break;
9737     }
9738     case EXTERNAL_FLOAT_ELEMENTS: {
9739       IterateExternalArrayElements<ExternalFloatArray, float>(
9740           isolate, receiver, false, false, visitor);
9741       break;
9742     }
9743     case EXTERNAL_DOUBLE_ELEMENTS: {
9744       IterateExternalArrayElements<ExternalDoubleArray, double>(
9745           isolate, receiver, false, false, visitor);
9746       break;
9747     }
9748     default:
9749       UNREACHABLE();
9750       break;
9751   }
9752   visitor->increase_index_offset(length);
9753   return true;
9754 }
9755 
9756 
9757 /**
9758  * Array::concat implementation.
9759  * See ECMAScript 262, 15.4.4.4.
9760  * TODO(581): Fix non-compliance for very large concatenations and update to
9761  * following the ECMAScript 5 specification.
9762  */
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayConcat)9763 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
9764   ASSERT(args.length() == 1);
9765   HandleScope handle_scope(isolate);
9766 
9767   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
9768   int argument_count = static_cast<int>(arguments->length()->Number());
9769   RUNTIME_ASSERT(arguments->HasFastElements());
9770   Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
9771 
9772   // Pass 1: estimate the length and number of elements of the result.
9773   // The actual length can be larger if any of the arguments have getters
9774   // that mutate other arguments (but will otherwise be precise).
9775   // The number of elements is precise if there are no inherited elements.
9776 
9777   uint32_t estimate_result_length = 0;
9778   uint32_t estimate_nof_elements = 0;
9779   {
9780     for (int i = 0; i < argument_count; i++) {
9781       HandleScope loop_scope;
9782       Handle<Object> obj(elements->get(i));
9783       uint32_t length_estimate;
9784       uint32_t element_estimate;
9785       if (obj->IsJSArray()) {
9786         Handle<JSArray> array(Handle<JSArray>::cast(obj));
9787         // TODO(1810): Find out if it's worthwhile to properly support
9788         // arbitrary ElementsKinds. For now, pessimistically transition to
9789         // FAST_ELEMENTS.
9790         if (array->HasFastDoubleElements()) {
9791           array = Handle<JSArray>::cast(
9792               JSObject::TransitionElementsKind(array, FAST_ELEMENTS));
9793         }
9794         length_estimate =
9795             static_cast<uint32_t>(array->length()->Number());
9796         element_estimate =
9797             EstimateElementCount(array);
9798       } else {
9799         length_estimate = 1;
9800         element_estimate = 1;
9801       }
9802       // Avoid overflows by capping at kMaxElementCount.
9803       if (JSObject::kMaxElementCount - estimate_result_length <
9804           length_estimate) {
9805         estimate_result_length = JSObject::kMaxElementCount;
9806       } else {
9807         estimate_result_length += length_estimate;
9808       }
9809       if (JSObject::kMaxElementCount - estimate_nof_elements <
9810           element_estimate) {
9811         estimate_nof_elements = JSObject::kMaxElementCount;
9812       } else {
9813         estimate_nof_elements += element_estimate;
9814       }
9815     }
9816   }
9817 
9818   // If estimated number of elements is more than half of length, a
9819   // fixed array (fast case) is more time and space-efficient than a
9820   // dictionary.
9821   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
9822 
9823   Handle<FixedArray> storage;
9824   if (fast_case) {
9825     // The backing storage array must have non-existing elements to
9826     // preserve holes across concat operations.
9827     storage = isolate->factory()->NewFixedArrayWithHoles(
9828         estimate_result_length);
9829   } else {
9830     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
9831     uint32_t at_least_space_for = estimate_nof_elements +
9832                                   (estimate_nof_elements >> 2);
9833     storage = Handle<FixedArray>::cast(
9834         isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
9835   }
9836 
9837   ArrayConcatVisitor visitor(isolate, storage, fast_case);
9838 
9839   for (int i = 0; i < argument_count; i++) {
9840     Handle<Object> obj(elements->get(i));
9841     if (obj->IsJSArray()) {
9842       Handle<JSArray> array = Handle<JSArray>::cast(obj);
9843       if (!IterateElements(isolate, array, &visitor)) {
9844         return Failure::Exception();
9845       }
9846     } else {
9847       visitor.visit(0, obj);
9848       visitor.increase_index_offset(1);
9849     }
9850   }
9851 
9852   return *visitor.ToArray();
9853 }
9854 
9855 
9856 // This will not allocate (flatten the string), but it may run
9857 // very slowly for very deeply nested ConsStrings.  For debugging use only.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GlobalPrint)9858 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
9859   NoHandleAllocation ha;
9860   ASSERT(args.length() == 1);
9861 
9862   CONVERT_ARG_CHECKED(String, string, 0);
9863   StringInputBuffer buffer(string);
9864   while (buffer.has_more()) {
9865     uint16_t character = buffer.GetNext();
9866     PrintF("%c", character);
9867   }
9868   return string;
9869 }
9870 
9871 // Moves all own elements of an object, that are below a limit, to positions
9872 // starting at zero. All undefined values are placed after non-undefined values,
9873 // and are followed by non-existing element. Does not change the length
9874 // property.
9875 // Returns the number of non-undefined elements collected.
RUNTIME_FUNCTION(MaybeObject *,Runtime_RemoveArrayHoles)9876 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
9877   ASSERT(args.length() == 2);
9878   CONVERT_ARG_CHECKED(JSObject, object, 0);
9879   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
9880   return object->PrepareElementsForSort(limit);
9881 }
9882 
9883 
9884 // Move contents of argument 0 (an array) to argument 1 (an array)
RUNTIME_FUNCTION(MaybeObject *,Runtime_MoveArrayContents)9885 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
9886   ASSERT(args.length() == 2);
9887   CONVERT_ARG_CHECKED(JSArray, from, 0);
9888   CONVERT_ARG_CHECKED(JSArray, to, 1);
9889   FixedArrayBase* new_elements = from->elements();
9890   MaybeObject* maybe_new_map;
9891   ElementsKind elements_kind;
9892   if (new_elements->map() == isolate->heap()->fixed_array_map() ||
9893       new_elements->map() == isolate->heap()->fixed_cow_array_map()) {
9894     elements_kind = FAST_ELEMENTS;
9895   } else if (new_elements->map() ==
9896              isolate->heap()->fixed_double_array_map()) {
9897     elements_kind = FAST_DOUBLE_ELEMENTS;
9898   } else {
9899     elements_kind = DICTIONARY_ELEMENTS;
9900   }
9901   maybe_new_map = to->GetElementsTransitionMap(isolate, elements_kind);
9902   Object* new_map;
9903   if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
9904   to->set_map(Map::cast(new_map));
9905   to->set_elements(new_elements);
9906   to->set_length(from->length());
9907   Object* obj;
9908   { MaybeObject* maybe_obj = from->ResetElements();
9909     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9910   }
9911   from->set_length(Smi::FromInt(0));
9912   return to;
9913 }
9914 
9915 
9916 // How many elements does this object/array have?
RUNTIME_FUNCTION(MaybeObject *,Runtime_EstimateNumberOfElements)9917 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
9918   ASSERT(args.length() == 1);
9919   CONVERT_ARG_CHECKED(JSObject, object, 0);
9920   HeapObject* elements = object->elements();
9921   if (elements->IsDictionary()) {
9922     int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
9923     return Smi::FromInt(result);
9924   } else if (object->IsJSArray()) {
9925     return JSArray::cast(object)->length();
9926   } else {
9927     return Smi::FromInt(FixedArray::cast(elements)->length());
9928   }
9929 }
9930 
9931 
9932 // Returns an array that tells you where in the [0, length) interval an array
9933 // might have elements.  Can either return keys (positive integers) or
9934 // intervals (pair of a negative integer (-start-1) followed by a
9935 // positive (length)) or undefined values.
9936 // Intervals can span over some keys that are not in the object.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetArrayKeys)9937 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
9938   ASSERT(args.length() == 2);
9939   HandleScope scope(isolate);
9940   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
9941   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
9942   if (array->elements()->IsDictionary()) {
9943     // Create an array and get all the keys into it, then remove all the
9944     // keys that are not integers in the range 0 to length-1.
9945     bool threw = false;
9946     Handle<FixedArray> keys =
9947         GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw);
9948     if (threw) return Failure::Exception();
9949 
9950     int keys_length = keys->length();
9951     for (int i = 0; i < keys_length; i++) {
9952       Object* key = keys->get(i);
9953       uint32_t index = 0;
9954       if (!key->ToArrayIndex(&index) || index >= length) {
9955         // Zap invalid keys.
9956         keys->set_undefined(i);
9957       }
9958     }
9959     return *isolate->factory()->NewJSArrayWithElements(keys);
9960   } else {
9961     ASSERT(array->HasFastElements() ||
9962            array->HasFastSmiOnlyElements() ||
9963            array->HasFastDoubleElements());
9964     Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
9965     // -1 means start of array.
9966     single_interval->set(0, Smi::FromInt(-1));
9967     FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
9968     uint32_t actual_length =
9969         static_cast<uint32_t>(elements->length());
9970     uint32_t min_length = actual_length < length ? actual_length : length;
9971     Handle<Object> length_object =
9972         isolate->factory()->NewNumber(static_cast<double>(min_length));
9973     single_interval->set(1, *length_object);
9974     return *isolate->factory()->NewJSArrayWithElements(single_interval);
9975   }
9976 }
9977 
9978 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LookupAccessor)9979 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
9980   ASSERT(args.length() == 3);
9981   CONVERT_ARG_CHECKED(JSObject, obj, 0);
9982   CONVERT_ARG_CHECKED(String, name, 1);
9983   CONVERT_SMI_ARG_CHECKED(flag, 2);
9984   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
9985   return obj->LookupAccessor(name, component);
9986 }
9987 
9988 
9989 #ifdef ENABLE_DEBUGGER_SUPPORT
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugBreak)9990 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
9991   ASSERT(args.length() == 0);
9992   return Execution::DebugBreakHelper();
9993 }
9994 
9995 
9996 // Helper functions for wrapping and unwrapping stack frame ids.
WrapFrameId(StackFrame::Id id)9997 static Smi* WrapFrameId(StackFrame::Id id) {
9998   ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
9999   return Smi::FromInt(id >> 2);
10000 }
10001 
10002 
UnwrapFrameId(int wrapped)10003 static StackFrame::Id UnwrapFrameId(int wrapped) {
10004   return static_cast<StackFrame::Id>(wrapped << 2);
10005 }
10006 
10007 
10008 // Adds a JavaScript function as a debug event listener.
10009 // args[0]: debug event listener function to set or null or undefined for
10010 //          clearing the event listener function
10011 // args[1]: object supplied during callback
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDebugEventListener)10012 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10013   ASSERT(args.length() == 2);
10014   RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10015                  args[0]->IsUndefined() ||
10016                  args[0]->IsNull());
10017   Handle<Object> callback = args.at<Object>(0);
10018   Handle<Object> data = args.at<Object>(1);
10019   isolate->debugger()->SetEventListener(callback, data);
10020 
10021   return isolate->heap()->undefined_value();
10022 }
10023 
10024 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Break)10025 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10026   ASSERT(args.length() == 0);
10027   isolate->stack_guard()->DebugBreak();
10028   return isolate->heap()->undefined_value();
10029 }
10030 
10031 
DebugLookupResultValue(Heap * heap,Object * receiver,String * name,LookupResult * result,bool * caught_exception)10032 static MaybeObject* DebugLookupResultValue(Heap* heap,
10033                                            Object* receiver,
10034                                            String* name,
10035                                            LookupResult* result,
10036                                            bool* caught_exception) {
10037   Object* value;
10038   switch (result->type()) {
10039     case NORMAL:
10040       value = result->holder()->GetNormalizedProperty(result);
10041       if (value->IsTheHole()) {
10042         return heap->undefined_value();
10043       }
10044       return value;
10045     case FIELD:
10046       value =
10047           JSObject::cast(
10048               result->holder())->FastPropertyAt(result->GetFieldIndex());
10049       if (value->IsTheHole()) {
10050         return heap->undefined_value();
10051       }
10052       return value;
10053     case CONSTANT_FUNCTION:
10054       return result->GetConstantFunction();
10055     case CALLBACKS: {
10056       Object* structure = result->GetCallbackObject();
10057       if (structure->IsForeign() || structure->IsAccessorInfo()) {
10058         MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
10059             receiver, structure, name);
10060         if (!maybe_value->ToObject(&value)) {
10061           if (maybe_value->IsRetryAfterGC()) return maybe_value;
10062           ASSERT(maybe_value->IsException());
10063           maybe_value = heap->isolate()->pending_exception();
10064           heap->isolate()->clear_pending_exception();
10065           if (caught_exception != NULL) {
10066             *caught_exception = true;
10067           }
10068           return maybe_value;
10069         }
10070         return value;
10071       } else {
10072         return heap->undefined_value();
10073       }
10074     }
10075     case INTERCEPTOR:
10076     case MAP_TRANSITION:
10077     case ELEMENTS_TRANSITION:
10078     case CONSTANT_TRANSITION:
10079     case NULL_DESCRIPTOR:
10080       return heap->undefined_value();
10081     case HANDLER:
10082       UNREACHABLE();
10083       return heap->undefined_value();
10084   }
10085   UNREACHABLE();  // keep the compiler happy
10086   return heap->undefined_value();
10087 }
10088 
10089 
10090 // Get debugger related details for an object property.
10091 // args[0]: object holding property
10092 // args[1]: name of the property
10093 //
10094 // The array returned contains the following information:
10095 // 0: Property value
10096 // 1: Property details
10097 // 2: Property value is exception
10098 // 3: Getter function if defined
10099 // 4: Setter function if defined
10100 // Items 2-4 are only filled if the property has either a getter or a setter
10101 // defined through __defineGetter__ and/or __defineSetter__.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetPropertyDetails)10102 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10103   HandleScope scope(isolate);
10104 
10105   ASSERT(args.length() == 2);
10106 
10107   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10108   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10109 
10110   // Make sure to set the current context to the context before the debugger was
10111   // entered (if the debugger is entered). The reason for switching context here
10112   // is that for some property lookups (accessors and interceptors) callbacks
10113   // into the embedding application can occour, and the embedding application
10114   // could have the assumption that its own global context is the current
10115   // context and not some internal debugger context.
10116   SaveContext save(isolate);
10117   if (isolate->debug()->InDebugger()) {
10118     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10119   }
10120 
10121   // Skip the global proxy as it has no properties and always delegates to the
10122   // real global object.
10123   if (obj->IsJSGlobalProxy()) {
10124     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10125   }
10126 
10127 
10128   // Check if the name is trivially convertible to an index and get the element
10129   // if so.
10130   uint32_t index;
10131   if (name->AsArrayIndex(&index)) {
10132     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10133     Object* element_or_char;
10134     { MaybeObject* maybe_element_or_char =
10135           Runtime::GetElementOrCharAt(isolate, obj, index);
10136       if (!maybe_element_or_char->ToObject(&element_or_char)) {
10137         return maybe_element_or_char;
10138       }
10139     }
10140     details->set(0, element_or_char);
10141     details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
10142     return *isolate->factory()->NewJSArrayWithElements(details);
10143   }
10144 
10145   // Find the number of objects making up this.
10146   int length = LocalPrototypeChainLength(*obj);
10147 
10148   // Try local lookup on each of the objects.
10149   Handle<JSObject> jsproto = obj;
10150   for (int i = 0; i < length; i++) {
10151     LookupResult result(isolate);
10152     jsproto->LocalLookup(*name, &result);
10153     if (result.IsProperty()) {
10154       // LookupResult is not GC safe as it holds raw object pointers.
10155       // GC can happen later in this code so put the required fields into
10156       // local variables using handles when required for later use.
10157       PropertyType result_type = result.type();
10158       Handle<Object> result_callback_obj;
10159       if (result_type == CALLBACKS) {
10160         result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10161                                              isolate);
10162       }
10163       Smi* property_details = result.GetPropertyDetails().AsSmi();
10164       // DebugLookupResultValue can cause GC so details from LookupResult needs
10165       // to be copied to handles before this.
10166       bool caught_exception = false;
10167       Object* raw_value;
10168       { MaybeObject* maybe_raw_value =
10169             DebugLookupResultValue(isolate->heap(), *obj, *name,
10170                                    &result, &caught_exception);
10171         if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10172       }
10173       Handle<Object> value(raw_value, isolate);
10174 
10175       // If the callback object is a fixed array then it contains JavaScript
10176       // getter and/or setter.
10177       bool hasJavaScriptAccessors = result_type == CALLBACKS &&
10178                                     result_callback_obj->IsAccessorPair();
10179       Handle<FixedArray> details =
10180           isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10181       details->set(0, *value);
10182       details->set(1, property_details);
10183       if (hasJavaScriptAccessors) {
10184         AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10185         details->set(2, isolate->heap()->ToBoolean(caught_exception));
10186         details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10187         details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10188       }
10189 
10190       return *isolate->factory()->NewJSArrayWithElements(details);
10191     }
10192     if (i < length - 1) {
10193       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10194     }
10195   }
10196 
10197   return isolate->heap()->undefined_value();
10198 }
10199 
10200 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetProperty)10201 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10202   HandleScope scope(isolate);
10203 
10204   ASSERT(args.length() == 2);
10205 
10206   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10207   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10208 
10209   LookupResult result(isolate);
10210   obj->Lookup(*name, &result);
10211   if (result.IsProperty()) {
10212     return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10213   }
10214   return isolate->heap()->undefined_value();
10215 }
10216 
10217 
10218 // Return the property type calculated from the property details.
10219 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyTypeFromDetails)10220 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10221   ASSERT(args.length() == 1);
10222   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10223   return Smi::FromInt(static_cast<int>(details.type()));
10224 }
10225 
10226 
10227 // Return the property attribute calculated from the property details.
10228 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyAttributesFromDetails)10229 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10230   ASSERT(args.length() == 1);
10231   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10232   return Smi::FromInt(static_cast<int>(details.attributes()));
10233 }
10234 
10235 
10236 // Return the property insertion index calculated from the property details.
10237 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyIndexFromDetails)10238 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10239   ASSERT(args.length() == 1);
10240   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10241   return Smi::FromInt(details.index());
10242 }
10243 
10244 
10245 // Return property value from named interceptor.
10246 // args[0]: object
10247 // args[1]: property name
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugNamedInterceptorPropertyValue)10248 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10249   HandleScope scope(isolate);
10250   ASSERT(args.length() == 2);
10251   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10252   RUNTIME_ASSERT(obj->HasNamedInterceptor());
10253   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10254 
10255   PropertyAttributes attributes;
10256   return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
10257 }
10258 
10259 
10260 // Return element value from indexed interceptor.
10261 // args[0]: object
10262 // args[1]: index
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugIndexedInterceptorElementValue)10263 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10264   HandleScope scope(isolate);
10265   ASSERT(args.length() == 2);
10266   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10267   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10268   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10269 
10270   return obj->GetElementWithInterceptor(*obj, index);
10271 }
10272 
10273 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CheckExecutionState)10274 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10275   ASSERT(args.length() >= 1);
10276   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10277   // Check that the break id is valid.
10278   if (isolate->debug()->break_id() == 0 ||
10279       break_id != isolate->debug()->break_id()) {
10280     return isolate->Throw(
10281         isolate->heap()->illegal_execution_state_symbol());
10282   }
10283 
10284   return isolate->heap()->true_value();
10285 }
10286 
10287 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFrameCount)10288 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10289   HandleScope scope(isolate);
10290   ASSERT(args.length() == 1);
10291 
10292   // Check arguments.
10293   Object* result;
10294   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10295       RUNTIME_ARGUMENTS(isolate, args));
10296     if (!maybe_result->ToObject(&result)) return maybe_result;
10297   }
10298 
10299   // Count all frames which are relevant to debugging stack trace.
10300   int n = 0;
10301   StackFrame::Id id = isolate->debug()->break_frame_id();
10302   if (id == StackFrame::NO_ID) {
10303     // If there is no JavaScript stack frame count is 0.
10304     return Smi::FromInt(0);
10305   }
10306 
10307   for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10308     n += it.frame()->GetInlineCount();
10309   }
10310   return Smi::FromInt(n);
10311 }
10312 
10313 
10314 class FrameInspector {
10315  public:
FrameInspector(JavaScriptFrame * frame,int inlined_jsframe_index,Isolate * isolate)10316   FrameInspector(JavaScriptFrame* frame,
10317                  int inlined_jsframe_index,
10318                  Isolate* isolate)
10319       : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
10320     // Calculate the deoptimized frame.
10321     if (frame->is_optimized()) {
10322       deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
10323           frame, inlined_jsframe_index, isolate);
10324     }
10325     has_adapted_arguments_ = frame_->has_adapted_arguments();
10326     is_bottommost_ = inlined_jsframe_index == 0;
10327     is_optimized_ = frame_->is_optimized();
10328   }
10329 
~FrameInspector()10330   ~FrameInspector() {
10331     // Get rid of the calculated deoptimized frame if any.
10332     if (deoptimized_frame_ != NULL) {
10333       Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
10334                                                   isolate_);
10335     }
10336   }
10337 
GetParametersCount()10338   int GetParametersCount() {
10339     return is_optimized_
10340         ? deoptimized_frame_->parameters_count()
10341         : frame_->ComputeParametersCount();
10342   }
expression_count()10343   int expression_count() { return deoptimized_frame_->expression_count(); }
GetFunction()10344   Object* GetFunction() {
10345     return is_optimized_
10346         ? deoptimized_frame_->GetFunction()
10347         : frame_->function();
10348   }
GetParameter(int index)10349   Object* GetParameter(int index) {
10350     return is_optimized_
10351         ? deoptimized_frame_->GetParameter(index)
10352         : frame_->GetParameter(index);
10353   }
GetExpression(int index)10354   Object* GetExpression(int index) {
10355     return is_optimized_
10356         ? deoptimized_frame_->GetExpression(index)
10357         : frame_->GetExpression(index);
10358   }
GetSourcePosition()10359   int GetSourcePosition() {
10360     return is_optimized_
10361         ? deoptimized_frame_->GetSourcePosition()
10362         : frame_->LookupCode()->SourcePosition(frame_->pc());
10363   }
IsConstructor()10364   bool IsConstructor() {
10365     return is_optimized_ && !is_bottommost_
10366         ? deoptimized_frame_->HasConstructStub()
10367         : frame_->IsConstructor();
10368   }
10369 
10370   // To inspect all the provided arguments the frame might need to be
10371   // replaced with the arguments frame.
SetArgumentsFrame(JavaScriptFrame * frame)10372   void SetArgumentsFrame(JavaScriptFrame* frame) {
10373     ASSERT(has_adapted_arguments_);
10374     frame_ = frame;
10375     is_optimized_ = frame_->is_optimized();
10376     ASSERT(!is_optimized_);
10377   }
10378 
10379  private:
10380   JavaScriptFrame* frame_;
10381   DeoptimizedFrameInfo* deoptimized_frame_;
10382   Isolate* isolate_;
10383   bool is_optimized_;
10384   bool is_bottommost_;
10385   bool has_adapted_arguments_;
10386 
10387   DISALLOW_COPY_AND_ASSIGN(FrameInspector);
10388 };
10389 
10390 
10391 static const int kFrameDetailsFrameIdIndex = 0;
10392 static const int kFrameDetailsReceiverIndex = 1;
10393 static const int kFrameDetailsFunctionIndex = 2;
10394 static const int kFrameDetailsArgumentCountIndex = 3;
10395 static const int kFrameDetailsLocalCountIndex = 4;
10396 static const int kFrameDetailsSourcePositionIndex = 5;
10397 static const int kFrameDetailsConstructCallIndex = 6;
10398 static const int kFrameDetailsAtReturnIndex = 7;
10399 static const int kFrameDetailsFlagsIndex = 8;
10400 static const int kFrameDetailsFirstDynamicIndex = 9;
10401 
10402 
FindSavedContextForFrame(Isolate * isolate,JavaScriptFrame * frame)10403 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
10404                                              JavaScriptFrame* frame) {
10405   SaveContext* save = isolate->save_context();
10406   while (save != NULL && !save->IsBelowFrame(frame)) {
10407     save = save->prev();
10408   }
10409   ASSERT(save != NULL);
10410   return save;
10411 }
10412 
10413 
10414 // Return an array with frame details
10415 // args[0]: number: break id
10416 // args[1]: number: frame index
10417 //
10418 // The array returned contains the following information:
10419 // 0: Frame id
10420 // 1: Receiver
10421 // 2: Function
10422 // 3: Argument count
10423 // 4: Local count
10424 // 5: Source position
10425 // 6: Constructor call
10426 // 7: Is at return
10427 // 8: Flags
10428 // Arguments name, value
10429 // Locals name, value
10430 // Return value if any
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFrameDetails)10431 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
10432   HandleScope scope(isolate);
10433   ASSERT(args.length() == 2);
10434 
10435   // Check arguments.
10436   Object* check;
10437   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10438       RUNTIME_ARGUMENTS(isolate, args));
10439     if (!maybe_check->ToObject(&check)) return maybe_check;
10440   }
10441   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10442   Heap* heap = isolate->heap();
10443 
10444   // Find the relevant frame with the requested index.
10445   StackFrame::Id id = isolate->debug()->break_frame_id();
10446   if (id == StackFrame::NO_ID) {
10447     // If there are no JavaScript stack frames return undefined.
10448     return heap->undefined_value();
10449   }
10450 
10451   int count = 0;
10452   JavaScriptFrameIterator it(isolate, id);
10453   for (; !it.done(); it.Advance()) {
10454     if (index < count + it.frame()->GetInlineCount()) break;
10455     count += it.frame()->GetInlineCount();
10456   }
10457   if (it.done()) return heap->undefined_value();
10458 
10459   bool is_optimized = it.frame()->is_optimized();
10460 
10461   int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
10462   if (is_optimized) {
10463     inlined_jsframe_index =
10464         it.frame()->GetInlineCount() - (index - count) - 1;
10465   }
10466   FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
10467 
10468   // Traverse the saved contexts chain to find the active context for the
10469   // selected frame.
10470   SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
10471 
10472   // Get the frame id.
10473   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
10474 
10475   // Find source position in unoptimized code.
10476   int position = frame_inspector.GetSourcePosition();
10477 
10478   // Check for constructor frame.
10479   bool constructor = frame_inspector.IsConstructor();
10480 
10481   // Get scope info and read from it for local variable information.
10482   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
10483   Handle<SharedFunctionInfo> shared(function->shared());
10484   Handle<ScopeInfo> scope_info(shared->scope_info());
10485   ASSERT(*scope_info != ScopeInfo::Empty());
10486 
10487   // Get the locals names and values into a temporary array.
10488   //
10489   // TODO(1240907): Hide compiler-introduced stack variables
10490   // (e.g. .result)?  For users of the debugger, they will probably be
10491   // confusing.
10492   Handle<FixedArray> locals =
10493       isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
10494 
10495   // Fill in the values of the locals.
10496   int i = 0;
10497   for (; i < scope_info->StackLocalCount(); ++i) {
10498     // Use the value from the stack.
10499     locals->set(i * 2, scope_info->LocalName(i));
10500     locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
10501   }
10502   if (i < scope_info->LocalCount()) {
10503     // Get the context containing declarations.
10504     Handle<Context> context(
10505         Context::cast(it.frame()->context())->declaration_context());
10506     for (; i < scope_info->LocalCount(); ++i) {
10507       Handle<String> name(scope_info->LocalName(i));
10508       VariableMode mode;
10509       InitializationFlag init_flag;
10510       locals->set(i * 2, *name);
10511       locals->set(i * 2 + 1, context->get(
10512           scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
10513     }
10514   }
10515 
10516   // Check whether this frame is positioned at return. If not top
10517   // frame or if the frame is optimized it cannot be at a return.
10518   bool at_return = false;
10519   if (!is_optimized && index == 0) {
10520     at_return = isolate->debug()->IsBreakAtReturn(it.frame());
10521   }
10522 
10523   // If positioned just before return find the value to be returned and add it
10524   // to the frame information.
10525   Handle<Object> return_value = isolate->factory()->undefined_value();
10526   if (at_return) {
10527     StackFrameIterator it2(isolate);
10528     Address internal_frame_sp = NULL;
10529     while (!it2.done()) {
10530       if (it2.frame()->is_internal()) {
10531         internal_frame_sp = it2.frame()->sp();
10532       } else {
10533         if (it2.frame()->is_java_script()) {
10534           if (it2.frame()->id() == it.frame()->id()) {
10535             // The internal frame just before the JavaScript frame contains the
10536             // value to return on top. A debug break at return will create an
10537             // internal frame to store the return value (eax/rax/r0) before
10538             // entering the debug break exit frame.
10539             if (internal_frame_sp != NULL) {
10540               return_value =
10541                   Handle<Object>(Memory::Object_at(internal_frame_sp),
10542                                  isolate);
10543               break;
10544             }
10545           }
10546         }
10547 
10548         // Indicate that the previous frame was not an internal frame.
10549         internal_frame_sp = NULL;
10550       }
10551       it2.Advance();
10552     }
10553   }
10554 
10555   // Now advance to the arguments adapter frame (if any). It contains all
10556   // the provided parameters whereas the function frame always have the number
10557   // of arguments matching the functions parameters. The rest of the
10558   // information (except for what is collected above) is the same.
10559   if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
10560     it.AdvanceToArgumentsFrame();
10561     frame_inspector.SetArgumentsFrame(it.frame());
10562   }
10563 
10564   // Find the number of arguments to fill. At least fill the number of
10565   // parameters for the function and fill more if more parameters are provided.
10566   int argument_count = scope_info->ParameterCount();
10567   if (argument_count < frame_inspector.GetParametersCount()) {
10568     argument_count = frame_inspector.GetParametersCount();
10569   }
10570 
10571   // Calculate the size of the result.
10572   int details_size = kFrameDetailsFirstDynamicIndex +
10573                      2 * (argument_count + scope_info->LocalCount()) +
10574                      (at_return ? 1 : 0);
10575   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
10576 
10577   // Add the frame id.
10578   details->set(kFrameDetailsFrameIdIndex, *frame_id);
10579 
10580   // Add the function (same as in function frame).
10581   details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
10582 
10583   // Add the arguments count.
10584   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
10585 
10586   // Add the locals count
10587   details->set(kFrameDetailsLocalCountIndex,
10588                Smi::FromInt(scope_info->LocalCount()));
10589 
10590   // Add the source position.
10591   if (position != RelocInfo::kNoPosition) {
10592     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
10593   } else {
10594     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
10595   }
10596 
10597   // Add the constructor information.
10598   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
10599 
10600   // Add the at return information.
10601   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
10602 
10603   // Add flags to indicate information on whether this frame is
10604   //   bit 0: invoked in the debugger context.
10605   //   bit 1: optimized frame.
10606   //   bit 2: inlined in optimized frame
10607   int flags = 0;
10608   if (*save->context() == *isolate->debug()->debug_context()) {
10609     flags |= 1 << 0;
10610   }
10611   if (is_optimized) {
10612     flags |= 1 << 1;
10613     flags |= inlined_jsframe_index << 2;
10614   }
10615   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
10616 
10617   // Fill the dynamic part.
10618   int details_index = kFrameDetailsFirstDynamicIndex;
10619 
10620   // Add arguments name and value.
10621   for (int i = 0; i < argument_count; i++) {
10622     // Name of the argument.
10623     if (i < scope_info->ParameterCount()) {
10624       details->set(details_index++, scope_info->ParameterName(i));
10625     } else {
10626       details->set(details_index++, heap->undefined_value());
10627     }
10628 
10629     // Parameter value.
10630     if (i < frame_inspector.GetParametersCount()) {
10631       // Get the value from the stack.
10632       details->set(details_index++, frame_inspector.GetParameter(i));
10633     } else {
10634       details->set(details_index++, heap->undefined_value());
10635     }
10636   }
10637 
10638   // Add locals name and value from the temporary copy from the function frame.
10639   for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
10640     details->set(details_index++, locals->get(i));
10641   }
10642 
10643   // Add the value being returned.
10644   if (at_return) {
10645     details->set(details_index++, *return_value);
10646   }
10647 
10648   // Add the receiver (same as in function frame).
10649   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
10650   // THE FRAME ITERATOR TO WRAP THE RECEIVER.
10651   Handle<Object> receiver(it.frame()->receiver(), isolate);
10652   if (!receiver->IsJSObject() &&
10653       shared->is_classic_mode() &&
10654       !shared->native()) {
10655     // If the receiver is not a JSObject and the function is not a
10656     // builtin or strict-mode we have hit an optimization where a
10657     // value object is not converted into a wrapped JS objects. To
10658     // hide this optimization from the debugger, we wrap the receiver
10659     // by creating correct wrapper object based on the calling frame's
10660     // global context.
10661     it.Advance();
10662     Handle<Context> calling_frames_global_context(
10663         Context::cast(Context::cast(it.frame()->context())->global_context()));
10664     receiver =
10665         isolate->factory()->ToObject(receiver, calling_frames_global_context);
10666   }
10667   details->set(kFrameDetailsReceiverIndex, *receiver);
10668 
10669   ASSERT_EQ(details_size, details_index);
10670   return *isolate->factory()->NewJSArrayWithElements(details);
10671 }
10672 
10673 
10674 // Copy all the context locals into an object used to materialize a scope.
CopyContextLocalsToScopeObject(Isolate * isolate,Handle<ScopeInfo> scope_info,Handle<Context> context,Handle<JSObject> scope_object)10675 static bool CopyContextLocalsToScopeObject(
10676     Isolate* isolate,
10677     Handle<ScopeInfo> scope_info,
10678     Handle<Context> context,
10679     Handle<JSObject> scope_object) {
10680   // Fill all context locals to the context extension.
10681   for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
10682     VariableMode mode;
10683     InitializationFlag init_flag;
10684     int context_index = scope_info->ContextSlotIndex(
10685         scope_info->ContextLocalName(i), &mode, &init_flag);
10686 
10687     RETURN_IF_EMPTY_HANDLE_VALUE(
10688         isolate,
10689         SetProperty(scope_object,
10690                     Handle<String>(scope_info->ContextLocalName(i)),
10691                     Handle<Object>(context->get(context_index), isolate),
10692                     NONE,
10693                     kNonStrictMode),
10694         false);
10695   }
10696 
10697   return true;
10698 }
10699 
10700 
10701 // Create a plain JSObject which materializes the local scope for the specified
10702 // frame.
MaterializeLocalScopeWithFrameInspector(Isolate * isolate,JavaScriptFrame * frame,FrameInspector * frame_inspector)10703 static Handle<JSObject> MaterializeLocalScopeWithFrameInspector(
10704     Isolate* isolate,
10705     JavaScriptFrame* frame,
10706     FrameInspector* frame_inspector) {
10707   Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
10708   Handle<SharedFunctionInfo> shared(function->shared());
10709   Handle<ScopeInfo> scope_info(shared->scope_info());
10710 
10711   // Allocate and initialize a JSObject with all the arguments, stack locals
10712   // heap locals and extension properties of the debugged function.
10713   Handle<JSObject> local_scope =
10714       isolate->factory()->NewJSObject(isolate->object_function());
10715 
10716   // First fill all parameters.
10717   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
10718     Handle<Object> value(
10719         i < frame_inspector->GetParametersCount() ?
10720         frame_inspector->GetParameter(i) : isolate->heap()->undefined_value());
10721 
10722     RETURN_IF_EMPTY_HANDLE_VALUE(
10723         isolate,
10724         SetProperty(local_scope,
10725                     Handle<String>(scope_info->ParameterName(i)),
10726                     value,
10727                     NONE,
10728                     kNonStrictMode),
10729         Handle<JSObject>());
10730   }
10731 
10732   // Second fill all stack locals.
10733   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
10734     RETURN_IF_EMPTY_HANDLE_VALUE(
10735         isolate,
10736         SetProperty(local_scope,
10737                     Handle<String>(scope_info->StackLocalName(i)),
10738                     Handle<Object>(frame_inspector->GetExpression(i)),
10739                     NONE,
10740                     kNonStrictMode),
10741         Handle<JSObject>());
10742   }
10743 
10744   if (scope_info->HasContext()) {
10745     // Third fill all context locals.
10746     Handle<Context> frame_context(Context::cast(frame->context()));
10747     Handle<Context> function_context(frame_context->declaration_context());
10748     if (!CopyContextLocalsToScopeObject(
10749             isolate, scope_info, function_context, local_scope)) {
10750       return Handle<JSObject>();
10751     }
10752 
10753     // Finally copy any properties from the function context extension.
10754     // These will be variables introduced by eval.
10755     if (function_context->closure() == *function) {
10756       if (function_context->has_extension() &&
10757           !function_context->IsGlobalContext()) {
10758         Handle<JSObject> ext(JSObject::cast(function_context->extension()));
10759         bool threw = false;
10760         Handle<FixedArray> keys =
10761             GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10762         if (threw) return Handle<JSObject>();
10763 
10764         for (int i = 0; i < keys->length(); i++) {
10765           // Names of variables introduced by eval are strings.
10766           ASSERT(keys->get(i)->IsString());
10767           Handle<String> key(String::cast(keys->get(i)));
10768           RETURN_IF_EMPTY_HANDLE_VALUE(
10769               isolate,
10770               SetProperty(local_scope,
10771                           key,
10772                           GetProperty(ext, key),
10773                           NONE,
10774                           kNonStrictMode),
10775               Handle<JSObject>());
10776         }
10777       }
10778     }
10779   }
10780 
10781   return local_scope;
10782 }
10783 
10784 
MaterializeLocalScope(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index)10785 static Handle<JSObject> MaterializeLocalScope(
10786     Isolate* isolate,
10787     JavaScriptFrame* frame,
10788     int inlined_jsframe_index) {
10789   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
10790   return MaterializeLocalScopeWithFrameInspector(isolate,
10791                                                  frame,
10792                                                  &frame_inspector);
10793 }
10794 
10795 
10796 // Create a plain JSObject which materializes the closure content for the
10797 // context.
MaterializeClosure(Isolate * isolate,Handle<Context> context)10798 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
10799                                            Handle<Context> context) {
10800   ASSERT(context->IsFunctionContext());
10801 
10802   Handle<SharedFunctionInfo> shared(context->closure()->shared());
10803   Handle<ScopeInfo> scope_info(shared->scope_info());
10804 
10805   // Allocate and initialize a JSObject with all the content of this function
10806   // closure.
10807   Handle<JSObject> closure_scope =
10808       isolate->factory()->NewJSObject(isolate->object_function());
10809 
10810   // Fill all context locals to the context extension.
10811   if (!CopyContextLocalsToScopeObject(
10812           isolate, scope_info, context, closure_scope)) {
10813     return Handle<JSObject>();
10814   }
10815 
10816   // Finally copy any properties from the function context extension. This will
10817   // be variables introduced by eval.
10818   if (context->has_extension()) {
10819     Handle<JSObject> ext(JSObject::cast(context->extension()));
10820     bool threw = false;
10821     Handle<FixedArray> keys =
10822         GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10823     if (threw) return Handle<JSObject>();
10824 
10825     for (int i = 0; i < keys->length(); i++) {
10826       // Names of variables introduced by eval are strings.
10827       ASSERT(keys->get(i)->IsString());
10828       Handle<String> key(String::cast(keys->get(i)));
10829        RETURN_IF_EMPTY_HANDLE_VALUE(
10830           isolate,
10831           SetProperty(closure_scope,
10832                       key,
10833                       GetProperty(ext, key),
10834                       NONE,
10835                       kNonStrictMode),
10836           Handle<JSObject>());
10837     }
10838   }
10839 
10840   return closure_scope;
10841 }
10842 
10843 
10844 // Create a plain JSObject which materializes the scope for the specified
10845 // catch context.
MaterializeCatchScope(Isolate * isolate,Handle<Context> context)10846 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
10847                                               Handle<Context> context) {
10848   ASSERT(context->IsCatchContext());
10849   Handle<String> name(String::cast(context->extension()));
10850   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX));
10851   Handle<JSObject> catch_scope =
10852       isolate->factory()->NewJSObject(isolate->object_function());
10853   RETURN_IF_EMPTY_HANDLE_VALUE(
10854       isolate,
10855       SetProperty(catch_scope, name, thrown_object, NONE, kNonStrictMode),
10856       Handle<JSObject>());
10857   return catch_scope;
10858 }
10859 
10860 
10861 // Create a plain JSObject which materializes the block scope for the specified
10862 // block context.
MaterializeBlockScope(Isolate * isolate,Handle<Context> context)10863 static Handle<JSObject> MaterializeBlockScope(
10864     Isolate* isolate,
10865     Handle<Context> context) {
10866   ASSERT(context->IsBlockContext());
10867   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
10868 
10869   // Allocate and initialize a JSObject with all the arguments, stack locals
10870   // heap locals and extension properties of the debugged function.
10871   Handle<JSObject> block_scope =
10872       isolate->factory()->NewJSObject(isolate->object_function());
10873 
10874   // Fill all context locals.
10875   if (!CopyContextLocalsToScopeObject(
10876           isolate, scope_info, context, block_scope)) {
10877     return Handle<JSObject>();
10878   }
10879 
10880   return block_scope;
10881 }
10882 
10883 
10884 // Create a plain JSObject which materializes the module scope for the specified
10885 // module context.
MaterializeModuleScope(Isolate * isolate,Handle<Context> context)10886 static Handle<JSObject> MaterializeModuleScope(
10887     Isolate* isolate,
10888     Handle<Context> context) {
10889   ASSERT(context->IsModuleContext());
10890   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
10891 
10892   // Allocate and initialize a JSObject with all the members of the debugged
10893   // module.
10894   Handle<JSObject> module_scope =
10895       isolate->factory()->NewJSObject(isolate->object_function());
10896 
10897   // Fill all context locals.
10898   if (!CopyContextLocalsToScopeObject(
10899           isolate, scope_info, context, module_scope)) {
10900     return Handle<JSObject>();
10901   }
10902 
10903   return module_scope;
10904 }
10905 
10906 
10907 // Iterate over the actual scopes visible from a stack frame. The iteration
10908 // proceeds from the innermost visible nested scope outwards. All scopes are
10909 // backed by an actual context except the local scope, which is inserted
10910 // "artificially" in the context chain.
10911 class ScopeIterator {
10912  public:
10913   enum ScopeType {
10914     ScopeTypeGlobal = 0,
10915     ScopeTypeLocal,
10916     ScopeTypeWith,
10917     ScopeTypeClosure,
10918     ScopeTypeCatch,
10919     ScopeTypeBlock,
10920     ScopeTypeModule
10921   };
10922 
ScopeIterator(Isolate * isolate,JavaScriptFrame * frame,int inlined_jsframe_index)10923   ScopeIterator(Isolate* isolate,
10924                 JavaScriptFrame* frame,
10925                 int inlined_jsframe_index)
10926     : isolate_(isolate),
10927       frame_(frame),
10928       inlined_jsframe_index_(inlined_jsframe_index),
10929       function_(JSFunction::cast(frame->function())),
10930       context_(Context::cast(frame->context())),
10931       nested_scope_chain_(4) {
10932 
10933     // Catch the case when the debugger stops in an internal function.
10934     Handle<SharedFunctionInfo> shared_info(function_->shared());
10935     Handle<ScopeInfo> scope_info(shared_info->scope_info());
10936     if (shared_info->script() == isolate->heap()->undefined_value()) {
10937       while (context_->closure() == *function_) {
10938         context_ = Handle<Context>(context_->previous(), isolate_);
10939       }
10940       return;
10941     }
10942 
10943     // Get the debug info (create it if it does not exist).
10944     if (!isolate->debug()->EnsureDebugInfo(shared_info)) {
10945       // Return if ensuring debug info failed.
10946       return;
10947     }
10948     Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
10949 
10950     // Find the break point where execution has stopped.
10951     BreakLocationIterator break_location_iterator(debug_info,
10952                                                   ALL_BREAK_LOCATIONS);
10953     break_location_iterator.FindBreakLocationFromAddress(frame->pc());
10954     if (break_location_iterator.IsExit()) {
10955       // We are within the return sequence. At the momemt it is not possible to
10956       // get a source position which is consistent with the current scope chain.
10957       // Thus all nested with, catch and block contexts are skipped and we only
10958       // provide the function scope.
10959       if (scope_info->HasContext()) {
10960         context_ = Handle<Context>(context_->declaration_context(), isolate_);
10961       } else {
10962         while (context_->closure() == *function_) {
10963           context_ = Handle<Context>(context_->previous(), isolate_);
10964         }
10965       }
10966       if (scope_info->Type() != EVAL_SCOPE) nested_scope_chain_.Add(scope_info);
10967     } else {
10968       // Reparse the code and analyze the scopes.
10969       ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
10970       Handle<Script> script(Script::cast(shared_info->script()));
10971       Scope* scope = NULL;
10972 
10973       // Check whether we are in global, eval or function code.
10974       Handle<ScopeInfo> scope_info(shared_info->scope_info());
10975       if (scope_info->Type() != FUNCTION_SCOPE) {
10976         // Global or eval code.
10977         CompilationInfo info(script);
10978         if (scope_info->Type() == GLOBAL_SCOPE) {
10979           info.MarkAsGlobal();
10980         } else {
10981           ASSERT(scope_info->Type() == EVAL_SCOPE);
10982           info.MarkAsEval();
10983           info.SetCallingContext(Handle<Context>(function_->context()));
10984         }
10985         if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
10986           scope = info.function()->scope();
10987         }
10988       } else {
10989         // Function code
10990         CompilationInfo info(shared_info);
10991         if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
10992           scope = info.function()->scope();
10993         }
10994       }
10995 
10996       // Retrieve the scope chain for the current position.
10997       if (scope != NULL) {
10998         int source_position = shared_info->code()->SourcePosition(frame_->pc());
10999         scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
11000       } else {
11001         // A failed reparse indicates that the preparser has diverged from the
11002         // parser or that the preparse data given to the initial parse has been
11003         // faulty. We fail in debug mode but in release mode we only provide the
11004         // information we get from the context chain but nothing about
11005         // completely stack allocated scopes or stack allocated locals.
11006         UNREACHABLE();
11007       }
11008     }
11009   }
11010 
11011   // More scopes?
Done()11012   bool Done() { return context_.is_null(); }
11013 
11014   // Move to the next scope.
Next()11015   void Next() {
11016     ScopeType scope_type = Type();
11017     if (scope_type == ScopeTypeGlobal) {
11018       // The global scope is always the last in the chain.
11019       ASSERT(context_->IsGlobalContext());
11020       context_ = Handle<Context>();
11021       return;
11022     }
11023     if (nested_scope_chain_.is_empty()) {
11024       context_ = Handle<Context>(context_->previous(), isolate_);
11025     } else {
11026       if (nested_scope_chain_.last()->HasContext()) {
11027         ASSERT(context_->previous() != NULL);
11028         context_ = Handle<Context>(context_->previous(), isolate_);
11029       }
11030       nested_scope_chain_.RemoveLast();
11031     }
11032   }
11033 
11034   // Return the type of the current scope.
Type()11035   ScopeType Type() {
11036     if (!nested_scope_chain_.is_empty()) {
11037       Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11038       switch (scope_info->Type()) {
11039         case FUNCTION_SCOPE:
11040           ASSERT(context_->IsFunctionContext() ||
11041                  !scope_info->HasContext());
11042           return ScopeTypeLocal;
11043         case MODULE_SCOPE:
11044           ASSERT(context_->IsModuleContext());
11045           return ScopeTypeModule;
11046         case GLOBAL_SCOPE:
11047           ASSERT(context_->IsGlobalContext());
11048           return ScopeTypeGlobal;
11049         case WITH_SCOPE:
11050           ASSERT(context_->IsWithContext());
11051           return ScopeTypeWith;
11052         case CATCH_SCOPE:
11053           ASSERT(context_->IsCatchContext());
11054           return ScopeTypeCatch;
11055         case BLOCK_SCOPE:
11056           ASSERT(!scope_info->HasContext() ||
11057                  context_->IsBlockContext());
11058           return ScopeTypeBlock;
11059         case EVAL_SCOPE:
11060           UNREACHABLE();
11061       }
11062     }
11063     if (context_->IsGlobalContext()) {
11064       ASSERT(context_->global()->IsGlobalObject());
11065       return ScopeTypeGlobal;
11066     }
11067     if (context_->IsFunctionContext()) {
11068       return ScopeTypeClosure;
11069     }
11070     if (context_->IsCatchContext()) {
11071       return ScopeTypeCatch;
11072     }
11073     if (context_->IsBlockContext()) {
11074       return ScopeTypeBlock;
11075     }
11076     if (context_->IsModuleContext()) {
11077       return ScopeTypeModule;
11078     }
11079     ASSERT(context_->IsWithContext());
11080     return ScopeTypeWith;
11081   }
11082 
11083   // Return the JavaScript object with the content of the current scope.
ScopeObject()11084   Handle<JSObject> ScopeObject() {
11085     switch (Type()) {
11086       case ScopeIterator::ScopeTypeGlobal:
11087         return Handle<JSObject>(CurrentContext()->global());
11088       case ScopeIterator::ScopeTypeLocal:
11089         // Materialize the content of the local scope into a JSObject.
11090         ASSERT(nested_scope_chain_.length() == 1);
11091         return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11092       case ScopeIterator::ScopeTypeWith:
11093         // Return the with object.
11094         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11095       case ScopeIterator::ScopeTypeCatch:
11096         return MaterializeCatchScope(isolate_, CurrentContext());
11097       case ScopeIterator::ScopeTypeClosure:
11098         // Materialize the content of the closure scope into a JSObject.
11099         return MaterializeClosure(isolate_, CurrentContext());
11100       case ScopeIterator::ScopeTypeBlock:
11101         return MaterializeBlockScope(isolate_, CurrentContext());
11102       case ScopeIterator::ScopeTypeModule:
11103         return MaterializeModuleScope(isolate_, CurrentContext());
11104     }
11105     UNREACHABLE();
11106     return Handle<JSObject>();
11107   }
11108 
CurrentScopeInfo()11109   Handle<ScopeInfo> CurrentScopeInfo() {
11110     if (!nested_scope_chain_.is_empty()) {
11111       return nested_scope_chain_.last();
11112     } else if (context_->IsBlockContext()) {
11113       return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
11114     } else if (context_->IsFunctionContext()) {
11115       return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
11116     }
11117     return Handle<ScopeInfo>::null();
11118   }
11119 
11120   // Return the context for this scope. For the local context there might not
11121   // be an actual context.
CurrentContext()11122   Handle<Context> CurrentContext() {
11123     if (Type() == ScopeTypeGlobal ||
11124         nested_scope_chain_.is_empty()) {
11125       return context_;
11126     } else if (nested_scope_chain_.last()->HasContext()) {
11127       return context_;
11128     } else {
11129       return Handle<Context>();
11130     }
11131   }
11132 
11133 #ifdef DEBUG
11134   // Debug print of the content of the current scope.
DebugPrint()11135   void DebugPrint() {
11136     switch (Type()) {
11137       case ScopeIterator::ScopeTypeGlobal:
11138         PrintF("Global:\n");
11139         CurrentContext()->Print();
11140         break;
11141 
11142       case ScopeIterator::ScopeTypeLocal: {
11143         PrintF("Local:\n");
11144         function_->shared()->scope_info()->Print();
11145         if (!CurrentContext().is_null()) {
11146           CurrentContext()->Print();
11147           if (CurrentContext()->has_extension()) {
11148             Handle<Object> extension(CurrentContext()->extension());
11149             if (extension->IsJSContextExtensionObject()) {
11150               extension->Print();
11151             }
11152           }
11153         }
11154         break;
11155       }
11156 
11157       case ScopeIterator::ScopeTypeWith:
11158         PrintF("With:\n");
11159         CurrentContext()->extension()->Print();
11160         break;
11161 
11162       case ScopeIterator::ScopeTypeCatch:
11163         PrintF("Catch:\n");
11164         CurrentContext()->extension()->Print();
11165         CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
11166         break;
11167 
11168       case ScopeIterator::ScopeTypeClosure:
11169         PrintF("Closure:\n");
11170         CurrentContext()->Print();
11171         if (CurrentContext()->has_extension()) {
11172           Handle<Object> extension(CurrentContext()->extension());
11173           if (extension->IsJSContextExtensionObject()) {
11174             extension->Print();
11175           }
11176         }
11177         break;
11178 
11179       default:
11180         UNREACHABLE();
11181     }
11182     PrintF("\n");
11183   }
11184 #endif
11185 
11186  private:
11187   Isolate* isolate_;
11188   JavaScriptFrame* frame_;
11189   int inlined_jsframe_index_;
11190   Handle<JSFunction> function_;
11191   Handle<Context> context_;
11192   List<Handle<ScopeInfo> > nested_scope_chain_;
11193 
11194   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11195 };
11196 
11197 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScopeCount)11198 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11199   HandleScope scope(isolate);
11200   ASSERT(args.length() == 2);
11201 
11202   // Check arguments.
11203   Object* check;
11204   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11205       RUNTIME_ARGUMENTS(isolate, args));
11206     if (!maybe_check->ToObject(&check)) return maybe_check;
11207   }
11208   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11209 
11210   // Get the frame where the debugging is performed.
11211   StackFrame::Id id = UnwrapFrameId(wrapped_id);
11212   JavaScriptFrameIterator it(isolate, id);
11213   JavaScriptFrame* frame = it.frame();
11214 
11215   // Count the visible scopes.
11216   int n = 0;
11217   for (ScopeIterator it(isolate, frame, 0);
11218        !it.Done();
11219        it.Next()) {
11220     n++;
11221   }
11222 
11223   return Smi::FromInt(n);
11224 }
11225 
11226 
11227 static const int kScopeDetailsTypeIndex = 0;
11228 static const int kScopeDetailsObjectIndex = 1;
11229 static const int kScopeDetailsSize = 2;
11230 
11231 // Return an array with scope details
11232 // args[0]: number: break id
11233 // args[1]: number: frame index
11234 // args[2]: number: inlined frame index
11235 // args[3]: number: scope index
11236 //
11237 // The array returned contains the following information:
11238 // 0: Scope type
11239 // 1: Scope object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScopeDetails)11240 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
11241   HandleScope scope(isolate);
11242   ASSERT(args.length() == 4);
11243 
11244   // Check arguments.
11245   Object* check;
11246   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11247       RUNTIME_ARGUMENTS(isolate, args));
11248     if (!maybe_check->ToObject(&check)) return maybe_check;
11249   }
11250   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11251   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11252   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
11253 
11254   // Get the frame where the debugging is performed.
11255   StackFrame::Id id = UnwrapFrameId(wrapped_id);
11256   JavaScriptFrameIterator frame_it(isolate, id);
11257   JavaScriptFrame* frame = frame_it.frame();
11258 
11259   // Find the requested scope.
11260   int n = 0;
11261   ScopeIterator it(isolate, frame, inlined_jsframe_index);
11262   for (; !it.Done() && n < index; it.Next()) {
11263     n++;
11264   }
11265   if (it.Done()) {
11266     return isolate->heap()->undefined_value();
11267   }
11268 
11269   // Calculate the size of the result.
11270   int details_size = kScopeDetailsSize;
11271   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11272 
11273   // Fill in scope details.
11274   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type()));
11275   Handle<JSObject> scope_object = it.ScopeObject();
11276   RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
11277   details->set(kScopeDetailsObjectIndex, *scope_object);
11278 
11279   return *isolate->factory()->NewJSArrayWithElements(details);
11280 }
11281 
11282 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPrintScopes)11283 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
11284   HandleScope scope(isolate);
11285   ASSERT(args.length() == 0);
11286 
11287 #ifdef DEBUG
11288   // Print the scopes for the top frame.
11289   StackFrameLocator locator;
11290   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
11291   for (ScopeIterator it(isolate, frame, 0);
11292        !it.Done();
11293        it.Next()) {
11294     it.DebugPrint();
11295   }
11296 #endif
11297   return isolate->heap()->undefined_value();
11298 }
11299 
11300 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetThreadCount)11301 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
11302   HandleScope scope(isolate);
11303   ASSERT(args.length() == 1);
11304 
11305   // Check arguments.
11306   Object* result;
11307   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11308       RUNTIME_ARGUMENTS(isolate, args));
11309     if (!maybe_result->ToObject(&result)) return maybe_result;
11310   }
11311 
11312   // Count all archived V8 threads.
11313   int n = 0;
11314   for (ThreadState* thread =
11315           isolate->thread_manager()->FirstThreadStateInUse();
11316        thread != NULL;
11317        thread = thread->Next()) {
11318     n++;
11319   }
11320 
11321   // Total number of threads is current thread and archived threads.
11322   return Smi::FromInt(n + 1);
11323 }
11324 
11325 
11326 static const int kThreadDetailsCurrentThreadIndex = 0;
11327 static const int kThreadDetailsThreadIdIndex = 1;
11328 static const int kThreadDetailsSize = 2;
11329 
11330 // Return an array with thread details
11331 // args[0]: number: break id
11332 // args[1]: number: thread index
11333 //
11334 // The array returned contains the following information:
11335 // 0: Is current thread?
11336 // 1: Thread id
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetThreadDetails)11337 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
11338   HandleScope scope(isolate);
11339   ASSERT(args.length() == 2);
11340 
11341   // Check arguments.
11342   Object* check;
11343   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11344       RUNTIME_ARGUMENTS(isolate, args));
11345     if (!maybe_check->ToObject(&check)) return maybe_check;
11346   }
11347   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11348 
11349   // Allocate array for result.
11350   Handle<FixedArray> details =
11351       isolate->factory()->NewFixedArray(kThreadDetailsSize);
11352 
11353   // Thread index 0 is current thread.
11354   if (index == 0) {
11355     // Fill the details.
11356     details->set(kThreadDetailsCurrentThreadIndex,
11357                  isolate->heap()->true_value());
11358     details->set(kThreadDetailsThreadIdIndex,
11359                  Smi::FromInt(ThreadId::Current().ToInteger()));
11360   } else {
11361     // Find the thread with the requested index.
11362     int n = 1;
11363     ThreadState* thread =
11364         isolate->thread_manager()->FirstThreadStateInUse();
11365     while (index != n && thread != NULL) {
11366       thread = thread->Next();
11367       n++;
11368     }
11369     if (thread == NULL) {
11370       return isolate->heap()->undefined_value();
11371     }
11372 
11373     // Fill the details.
11374     details->set(kThreadDetailsCurrentThreadIndex,
11375                  isolate->heap()->false_value());
11376     details->set(kThreadDetailsThreadIdIndex,
11377                  Smi::FromInt(thread->id().ToInteger()));
11378   }
11379 
11380   // Convert to JS array and return.
11381   return *isolate->factory()->NewJSArrayWithElements(details);
11382 }
11383 
11384 
11385 // Sets the disable break state
11386 // args[0]: disable break state
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDisableBreak)11387 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
11388   HandleScope scope(isolate);
11389   ASSERT(args.length() == 1);
11390   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
11391   isolate->debug()->set_disable_break(disable_break);
11392   return  isolate->heap()->undefined_value();
11393 }
11394 
11395 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetBreakLocations)11396 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
11397   HandleScope scope(isolate);
11398   ASSERT(args.length() == 1);
11399 
11400   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11401   Handle<SharedFunctionInfo> shared(fun->shared());
11402   // Find the number of break points
11403   Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
11404   if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
11405   // Return array as JS array
11406   return *isolate->factory()->NewJSArrayWithElements(
11407       Handle<FixedArray>::cast(break_locations));
11408 }
11409 
11410 
11411 // Set a break point in a function
11412 // args[0]: function
11413 // args[1]: number: break source position (within the function source)
11414 // args[2]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetFunctionBreakPoint)11415 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
11416   HandleScope scope(isolate);
11417   ASSERT(args.length() == 3);
11418   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11419   Handle<SharedFunctionInfo> shared(fun->shared());
11420   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11421   RUNTIME_ASSERT(source_position >= 0);
11422   Handle<Object> break_point_object_arg = args.at<Object>(2);
11423 
11424   // Set break point.
11425   isolate->debug()->SetBreakPoint(shared, break_point_object_arg,
11426                                   &source_position);
11427 
11428   return Smi::FromInt(source_position);
11429 }
11430 
11431 
FindSharedFunctionInfoInScript(Isolate * isolate,Handle<Script> script,int position)11432 Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
11433                                                 Handle<Script> script,
11434                                                 int position) {
11435   // Iterate the heap looking for SharedFunctionInfo generated from the
11436   // script. The inner most SharedFunctionInfo containing the source position
11437   // for the requested break point is found.
11438   // NOTE: This might require several heap iterations. If the SharedFunctionInfo
11439   // which is found is not compiled it is compiled and the heap is iterated
11440   // again as the compilation might create inner functions from the newly
11441   // compiled function and the actual requested break point might be in one of
11442   // these functions.
11443   bool done = false;
11444   // The current candidate for the source position:
11445   int target_start_position = RelocInfo::kNoPosition;
11446   Handle<SharedFunctionInfo> target;
11447   while (!done) {
11448     { // Extra scope for iterator and no-allocation.
11449       isolate->heap()->EnsureHeapIsIterable();
11450       AssertNoAllocation no_alloc_during_heap_iteration;
11451       HeapIterator iterator;
11452       for (HeapObject* obj = iterator.next();
11453            obj != NULL; obj = iterator.next()) {
11454         if (obj->IsSharedFunctionInfo()) {
11455           Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
11456           if (shared->script() == *script) {
11457             // If the SharedFunctionInfo found has the requested script data and
11458             // contains the source position it is a candidate.
11459             int start_position = shared->function_token_position();
11460             if (start_position == RelocInfo::kNoPosition) {
11461               start_position = shared->start_position();
11462             }
11463             if (start_position <= position &&
11464                 position <= shared->end_position()) {
11465               // If there is no candidate or this function is within the current
11466               // candidate this is the new candidate.
11467               if (target.is_null()) {
11468                 target_start_position = start_position;
11469                 target = shared;
11470               } else {
11471                 if (target_start_position == start_position &&
11472                     shared->end_position() == target->end_position()) {
11473                     // If a top-level function contain only one function
11474                     // declartion the source for the top-level and the
11475                     // function is the same. In that case prefer the non
11476                     // top-level function.
11477                   if (!shared->is_toplevel()) {
11478                     target_start_position = start_position;
11479                     target = shared;
11480                   }
11481                 } else if (target_start_position <= start_position &&
11482                            shared->end_position() <= target->end_position()) {
11483                   // This containment check includes equality as a function
11484                   // inside a top-level function can share either start or end
11485                   // position with the top-level function.
11486                   target_start_position = start_position;
11487                   target = shared;
11488                 }
11489               }
11490             }
11491           }
11492         }
11493       }  // End for loop.
11494     }  // End No allocation scope.
11495 
11496     if (target.is_null()) {
11497       return isolate->heap()->undefined_value();
11498     }
11499 
11500     // If the candidate found is compiled we are done. NOTE: when lazy
11501     // compilation of inner functions is introduced some additional checking
11502     // needs to be done here to compile inner functions.
11503     done = target->is_compiled();
11504     if (!done) {
11505       // If the candidate is not compiled compile it to reveal any inner
11506       // functions which might contain the requested source position.
11507       SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION);
11508     }
11509   }  // End while loop.
11510 
11511   return *target;
11512 }
11513 
11514 
11515 // Changes the state of a break point in a script and returns source position
11516 // where break point was set. NOTE: Regarding performance see the NOTE for
11517 // GetScriptFromScriptData.
11518 // args[0]: script to set break point in
11519 // args[1]: number: break source position (within the script source)
11520 // args[2]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetScriptBreakPoint)11521 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
11522   HandleScope scope(isolate);
11523   ASSERT(args.length() == 3);
11524   CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
11525   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11526   RUNTIME_ASSERT(source_position >= 0);
11527   Handle<Object> break_point_object_arg = args.at<Object>(2);
11528 
11529   // Get the script from the script wrapper.
11530   RUNTIME_ASSERT(wrapper->value()->IsScript());
11531   Handle<Script> script(Script::cast(wrapper->value()));
11532 
11533   Object* result = Runtime::FindSharedFunctionInfoInScript(
11534       isolate, script, source_position);
11535   if (!result->IsUndefined()) {
11536     Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
11537     // Find position within function. The script position might be before the
11538     // source position of the first function.
11539     int position;
11540     if (shared->start_position() > source_position) {
11541       position = 0;
11542     } else {
11543       position = source_position - shared->start_position();
11544     }
11545     isolate->debug()->SetBreakPoint(shared, break_point_object_arg, &position);
11546     position += shared->start_position();
11547     return Smi::FromInt(position);
11548   }
11549   return  isolate->heap()->undefined_value();
11550 }
11551 
11552 
11553 // Clear a break point
11554 // args[0]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClearBreakPoint)11555 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
11556   HandleScope scope(isolate);
11557   ASSERT(args.length() == 1);
11558   Handle<Object> break_point_object_arg = args.at<Object>(0);
11559 
11560   // Clear break point.
11561   isolate->debug()->ClearBreakPoint(break_point_object_arg);
11562 
11563   return isolate->heap()->undefined_value();
11564 }
11565 
11566 
11567 // Change the state of break on exceptions.
11568 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
11569 // args[1]: Boolean indicating on/off.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ChangeBreakOnException)11570 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
11571   HandleScope scope(isolate);
11572   ASSERT(args.length() == 2);
11573   RUNTIME_ASSERT(args[0]->IsNumber());
11574   CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
11575 
11576   // If the number doesn't match an enum value, the ChangeBreakOnException
11577   // function will default to affecting caught exceptions.
11578   ExceptionBreakType type =
11579       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11580   // Update break point state.
11581   isolate->debug()->ChangeBreakOnException(type, enable);
11582   return isolate->heap()->undefined_value();
11583 }
11584 
11585 
11586 // Returns the state of break on exceptions
11587 // args[0]: boolean indicating uncaught exceptions
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsBreakOnException)11588 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
11589   HandleScope scope(isolate);
11590   ASSERT(args.length() == 1);
11591   RUNTIME_ASSERT(args[0]->IsNumber());
11592 
11593   ExceptionBreakType type =
11594       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11595   bool result = isolate->debug()->IsBreakOnException(type);
11596   return Smi::FromInt(result);
11597 }
11598 
11599 
11600 // Prepare for stepping
11601 // args[0]: break id for checking execution state
11602 // args[1]: step action from the enumeration StepAction
11603 // args[2]: number of times to perform the step, for step out it is the number
11604 //          of frames to step down.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PrepareStep)11605 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
11606   HandleScope scope(isolate);
11607   ASSERT(args.length() == 3);
11608   // Check arguments.
11609   Object* check;
11610   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11611       RUNTIME_ARGUMENTS(isolate, args));
11612     if (!maybe_check->ToObject(&check)) return maybe_check;
11613   }
11614   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
11615     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11616   }
11617 
11618   // Get the step action and check validity.
11619   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
11620   if (step_action != StepIn &&
11621       step_action != StepNext &&
11622       step_action != StepOut &&
11623       step_action != StepInMin &&
11624       step_action != StepMin) {
11625     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11626   }
11627 
11628   // Get the number of steps.
11629   int step_count = NumberToInt32(args[2]);
11630   if (step_count < 1) {
11631     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11632   }
11633 
11634   // Clear all current stepping setup.
11635   isolate->debug()->ClearStepping();
11636 
11637   // Prepare step.
11638   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
11639                                 step_count);
11640   return isolate->heap()->undefined_value();
11641 }
11642 
11643 
11644 // Clear all stepping set by PrepareStep.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClearStepping)11645 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
11646   HandleScope scope(isolate);
11647   ASSERT(args.length() == 0);
11648   isolate->debug()->ClearStepping();
11649   return isolate->heap()->undefined_value();
11650 }
11651 
11652 
11653 // Creates a copy of the with context chain. The copy of the context chain is
11654 // is linked to the function context supplied.
CopyNestedScopeContextChain(Isolate * isolate,Handle<JSFunction> function,Handle<Context> base,JavaScriptFrame * frame,int inlined_jsframe_index)11655 static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
11656                                                    Handle<JSFunction> function,
11657                                                    Handle<Context> base,
11658                                                    JavaScriptFrame* frame,
11659                                                    int inlined_jsframe_index) {
11660   HandleScope scope(isolate);
11661   List<Handle<ScopeInfo> > scope_chain;
11662   List<Handle<Context> > context_chain;
11663 
11664   ScopeIterator it(isolate, frame, inlined_jsframe_index);
11665   for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
11666          it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
11667     ASSERT(!it.Done());
11668     scope_chain.Add(it.CurrentScopeInfo());
11669     context_chain.Add(it.CurrentContext());
11670   }
11671 
11672   // At the end of the chain. Return the base context to link to.
11673   Handle<Context> context = base;
11674 
11675   // Iteratively copy and or materialize the nested contexts.
11676   while (!scope_chain.is_empty()) {
11677     Handle<ScopeInfo> scope_info = scope_chain.RemoveLast();
11678     Handle<Context> current = context_chain.RemoveLast();
11679     ASSERT(!(scope_info->HasContext() & current.is_null()));
11680 
11681     if (scope_info->Type() == CATCH_SCOPE) {
11682       Handle<String> name(String::cast(current->extension()));
11683       Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX));
11684       context =
11685           isolate->factory()->NewCatchContext(function,
11686                                               context,
11687                                               name,
11688                                               thrown_object);
11689     } else if (scope_info->Type() == BLOCK_SCOPE) {
11690       // Materialize the contents of the block scope into a JSObject.
11691       Handle<JSObject> block_scope_object =
11692           MaterializeBlockScope(isolate, current);
11693       if (block_scope_object.is_null()) {
11694         return Handle<Context>::null();
11695       }
11696       // Allocate a new function context for the debug evaluation and set the
11697       // extension object.
11698       Handle<Context> new_context =
11699           isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11700                                                  function);
11701       new_context->set_extension(*block_scope_object);
11702       new_context->set_previous(*context);
11703       context = new_context;
11704     } else {
11705       ASSERT(scope_info->Type() == WITH_SCOPE);
11706       ASSERT(current->IsWithContext());
11707       Handle<JSObject> extension(JSObject::cast(current->extension()));
11708       context =
11709           isolate->factory()->NewWithContext(function, context, extension);
11710     }
11711   }
11712 
11713   return scope.CloseAndEscape(context);
11714 }
11715 
11716 
11717 // Helper function to find or create the arguments object for
11718 // Runtime_DebugEvaluate.
GetArgumentsObject(Isolate * isolate,JavaScriptFrame * frame,FrameInspector * frame_inspector,Handle<ScopeInfo> scope_info,Handle<Context> function_context)11719 static Handle<Object> GetArgumentsObject(Isolate* isolate,
11720                                          JavaScriptFrame* frame,
11721                                          FrameInspector* frame_inspector,
11722                                          Handle<ScopeInfo> scope_info,
11723                                          Handle<Context> function_context) {
11724   // Try to find the value of 'arguments' to pass as parameter. If it is not
11725   // found (that is the debugged function does not reference 'arguments' and
11726   // does not support eval) then create an 'arguments' object.
11727   int index;
11728   if (scope_info->StackLocalCount() > 0) {
11729     index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
11730     if (index != -1) {
11731       return Handle<Object>(frame->GetExpression(index), isolate);
11732     }
11733   }
11734 
11735   if (scope_info->HasHeapAllocatedLocals()) {
11736     VariableMode mode;
11737     InitializationFlag init_flag;
11738     index = scope_info->ContextSlotIndex(
11739         isolate->heap()->arguments_symbol(), &mode, &init_flag);
11740     if (index != -1) {
11741       return Handle<Object>(function_context->get(index), isolate);
11742     }
11743   }
11744 
11745   Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
11746   int length = frame_inspector->GetParametersCount();
11747   Handle<JSObject> arguments =
11748       isolate->factory()->NewArgumentsObject(function, length);
11749   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
11750 
11751   AssertNoAllocation no_gc;
11752   WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
11753   for (int i = 0; i < length; i++) {
11754     array->set(i, frame_inspector->GetParameter(i), mode);
11755   }
11756   arguments->set_elements(*array);
11757   return arguments;
11758 }
11759 
11760 
11761 static const char kSourceStr[] =
11762     "(function(arguments,__source__){return eval(__source__);})";
11763 
11764 
11765 // Evaluate a piece of JavaScript in the context of a stack frame for
11766 // debugging. This is accomplished by creating a new context which in its
11767 // extension part has all the parameters and locals of the function on the
11768 // stack frame. A function which calls eval with the code to evaluate is then
11769 // compiled in this context and called in this context. As this context
11770 // replaces the context of the function on the stack frame a new (empty)
11771 // function is created as well to be used as the closure for the context.
11772 // This function and the context acts as replacements for the function on the
11773 // stack frame presenting the same view of the values of parameters and
11774 // local variables as if the piece of JavaScript was evaluated at the point
11775 // where the function on the stack frame is currently stopped.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugEvaluate)11776 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
11777   HandleScope scope(isolate);
11778 
11779   // Check the execution state and decode arguments frame and source to be
11780   // evaluated.
11781   ASSERT(args.length() == 6);
11782   Object* check_result;
11783   { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
11784       RUNTIME_ARGUMENTS(isolate, args));
11785     if (!maybe_check_result->ToObject(&check_result)) {
11786       return maybe_check_result;
11787     }
11788   }
11789   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11790   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11791   CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
11792   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
11793   Handle<Object> additional_context(args[5]);
11794 
11795   // Handle the processing of break.
11796   DisableBreak disable_break_save(disable_break);
11797 
11798   // Get the frame where the debugging is performed.
11799   StackFrame::Id id = UnwrapFrameId(wrapped_id);
11800   JavaScriptFrameIterator it(isolate, id);
11801   JavaScriptFrame* frame = it.frame();
11802   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11803   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11804   Handle<ScopeInfo> scope_info(function->shared()->scope_info());
11805 
11806   // Traverse the saved contexts chain to find the active context for the
11807   // selected frame.
11808   SaveContext* save = FindSavedContextForFrame(isolate, frame);
11809 
11810   SaveContext savex(isolate);
11811   isolate->set_context(*(save->context()));
11812 
11813   // Create the (empty) function replacing the function on the stack frame for
11814   // the purpose of evaluating in the context created below. It is important
11815   // that this function does not describe any parameters and local variables
11816   // in the context. If it does then this will cause problems with the lookup
11817   // in Context::Lookup, where context slots for parameters and local variables
11818   // are looked at before the extension object.
11819   Handle<JSFunction> go_between =
11820       isolate->factory()->NewFunction(isolate->factory()->empty_string(),
11821                                       isolate->factory()->undefined_value());
11822   go_between->set_context(function->context());
11823 #ifdef DEBUG
11824   Handle<ScopeInfo> go_between_scope_info(go_between->shared()->scope_info());
11825   ASSERT(go_between_scope_info->ParameterCount() == 0);
11826   ASSERT(go_between_scope_info->ContextLocalCount() == 0);
11827 #endif
11828 
11829   // Materialize the content of the local scope into a JSObject.
11830   Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector(
11831       isolate, frame, &frame_inspector);
11832   RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
11833 
11834   // Allocate a new context for the debug evaluation and set the extension
11835   // object build.
11836   Handle<Context> context =
11837       isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11838                                              go_between);
11839   context->set_extension(*local_scope);
11840   // Copy any with contexts present and chain them in front of this context.
11841   Handle<Context> frame_context(Context::cast(frame->context()));
11842   Handle<Context> function_context;
11843   // Get the function's context if it has one.
11844   if (scope_info->HasContext()) {
11845     function_context = Handle<Context>(frame_context->declaration_context());
11846   }
11847   context = CopyNestedScopeContextChain(isolate,
11848                                         go_between,
11849                                         context,
11850                                         frame,
11851                                         inlined_jsframe_index);
11852 
11853   if (additional_context->IsJSObject()) {
11854     Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
11855     context =
11856         isolate->factory()->NewWithContext(go_between, context, extension);
11857   }
11858 
11859   // Wrap the evaluation statement in a new function compiled in the newly
11860   // created context. The function has one parameter which has to be called
11861   // 'arguments'. This it to have access to what would have been 'arguments' in
11862   // the function being debugged.
11863   // function(arguments,__source__) {return eval(__source__);}
11864 
11865   Handle<String> function_source =
11866       isolate->factory()->NewStringFromAscii(
11867           Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
11868 
11869   // Currently, the eval code will be executed in non-strict mode,
11870   // even in the strict code context.
11871   Handle<SharedFunctionInfo> shared =
11872       Compiler::CompileEval(function_source,
11873                             context,
11874                             context->IsGlobalContext(),
11875                             CLASSIC_MODE,
11876                             RelocInfo::kNoPosition);
11877   if (shared.is_null()) return Failure::Exception();
11878   Handle<JSFunction> compiled_function =
11879       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
11880 
11881   // Invoke the result of the compilation to get the evaluation function.
11882   bool has_pending_exception;
11883   Handle<Object> receiver(frame->receiver(), isolate);
11884   Handle<Object> evaluation_function =
11885       Execution::Call(compiled_function, receiver, 0, NULL,
11886                       &has_pending_exception);
11887   if (has_pending_exception) return Failure::Exception();
11888 
11889   Handle<Object> arguments = GetArgumentsObject(isolate,
11890                                                 frame,
11891                                                 &frame_inspector,
11892                                                 scope_info,
11893                                                 function_context);
11894 
11895   // Invoke the evaluation function and return the result.
11896   Handle<Object> argv[] = { arguments, source };
11897   Handle<Object> result =
11898       Execution::Call(Handle<JSFunction>::cast(evaluation_function),
11899                       receiver,
11900                       ARRAY_SIZE(argv),
11901                       argv,
11902                       &has_pending_exception);
11903   if (has_pending_exception) return Failure::Exception();
11904 
11905   // Skip the global proxy as it has no properties and always delegates to the
11906   // real global object.
11907   if (result->IsJSGlobalProxy()) {
11908     result = Handle<JSObject>(JSObject::cast(result->GetPrototype()));
11909   }
11910 
11911   return *result;
11912 }
11913 
11914 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugEvaluateGlobal)11915 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
11916   HandleScope scope(isolate);
11917 
11918   // Check the execution state and decode arguments frame and source to be
11919   // evaluated.
11920   ASSERT(args.length() == 4);
11921   Object* check_result;
11922   { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
11923       RUNTIME_ARGUMENTS(isolate, args));
11924     if (!maybe_check_result->ToObject(&check_result)) {
11925       return maybe_check_result;
11926     }
11927   }
11928   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
11929   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
11930   Handle<Object> additional_context(args[3]);
11931 
11932   // Handle the processing of break.
11933   DisableBreak disable_break_save(disable_break);
11934 
11935   // Enter the top context from before the debugger was invoked.
11936   SaveContext save(isolate);
11937   SaveContext* top = &save;
11938   while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
11939     top = top->prev();
11940   }
11941   if (top != NULL) {
11942     isolate->set_context(*top->context());
11943   }
11944 
11945   // Get the global context now set to the top context from before the
11946   // debugger was invoked.
11947   Handle<Context> context = isolate->global_context();
11948 
11949   bool is_global = true;
11950 
11951   if (additional_context->IsJSObject()) {
11952     // Create a new with context with the additional context information between
11953     // the context of the debugged function and the eval code to be executed.
11954     context = isolate->factory()->NewWithContext(
11955         Handle<JSFunction>(context->closure()),
11956         context,
11957         Handle<JSObject>::cast(additional_context));
11958     is_global = false;
11959   }
11960 
11961   // Compile the source to be evaluated.
11962   // Currently, the eval code will be executed in non-strict mode,
11963   // even in the strict code context.
11964   Handle<SharedFunctionInfo> shared =
11965       Compiler::CompileEval(source,
11966                             context,
11967                             is_global,
11968                             CLASSIC_MODE,
11969                             RelocInfo::kNoPosition);
11970   if (shared.is_null()) return Failure::Exception();
11971   Handle<JSFunction> compiled_function =
11972       Handle<JSFunction>(
11973           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
11974                                                                 context));
11975 
11976   // Invoke the result of the compilation to get the evaluation function.
11977   bool has_pending_exception;
11978   Handle<Object> receiver = isolate->global();
11979   Handle<Object> result =
11980     Execution::Call(compiled_function, receiver, 0, NULL,
11981                     &has_pending_exception);
11982   // Clear the oneshot breakpoints so that the debugger does not step further.
11983   isolate->debug()->ClearStepping();
11984   if (has_pending_exception) return Failure::Exception();
11985   return *result;
11986 }
11987 
11988 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetLoadedScripts)11989 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
11990   HandleScope scope(isolate);
11991   ASSERT(args.length() == 0);
11992 
11993   // Fill the script objects.
11994   Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
11995 
11996   // Convert the script objects to proper JS objects.
11997   for (int i = 0; i < instances->length(); i++) {
11998     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
11999     // Get the script wrapper in a local handle before calling GetScriptWrapper,
12000     // because using
12001     //   instances->set(i, *GetScriptWrapper(script))
12002     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12003     // already have dereferenced the instances handle.
12004     Handle<JSValue> wrapper = GetScriptWrapper(script);
12005     instances->set(i, *wrapper);
12006   }
12007 
12008   // Return result as a JS array.
12009   Handle<JSObject> result =
12010       isolate->factory()->NewJSObject(isolate->array_function());
12011   isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12012   return *result;
12013 }
12014 
12015 
12016 // 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)12017 static int DebugReferencedBy(HeapIterator* iterator,
12018                              JSObject* target,
12019                              Object* instance_filter, int max_references,
12020                              FixedArray* instances, int instances_size,
12021                              JSFunction* arguments_function) {
12022   NoHandleAllocation ha;
12023   AssertNoAllocation no_alloc;
12024 
12025   // Iterate the heap.
12026   int count = 0;
12027   JSObject* last = NULL;
12028   HeapObject* heap_obj = NULL;
12029   while (((heap_obj = iterator->next()) != NULL) &&
12030          (max_references == 0 || count < max_references)) {
12031     // Only look at all JSObjects.
12032     if (heap_obj->IsJSObject()) {
12033       // Skip context extension objects and argument arrays as these are
12034       // checked in the context of functions using them.
12035       JSObject* obj = JSObject::cast(heap_obj);
12036       if (obj->IsJSContextExtensionObject() ||
12037           obj->map()->constructor() == arguments_function) {
12038         continue;
12039       }
12040 
12041       // Check if the JS object has a reference to the object looked for.
12042       if (obj->ReferencesObject(target)) {
12043         // Check instance filter if supplied. This is normally used to avoid
12044         // references from mirror objects (see Runtime_IsInPrototypeChain).
12045         if (!instance_filter->IsUndefined()) {
12046           Object* V = obj;
12047           while (true) {
12048             Object* prototype = V->GetPrototype();
12049             if (prototype->IsNull()) {
12050               break;
12051             }
12052             if (instance_filter == prototype) {
12053               obj = NULL;  // Don't add this object.
12054               break;
12055             }
12056             V = prototype;
12057           }
12058         }
12059 
12060         if (obj != NULL) {
12061           // Valid reference found add to instance array if supplied an update
12062           // count.
12063           if (instances != NULL && count < instances_size) {
12064             instances->set(count, obj);
12065           }
12066           last = obj;
12067           count++;
12068         }
12069       }
12070     }
12071   }
12072 
12073   // Check for circular reference only. This can happen when the object is only
12074   // referenced from mirrors and has a circular reference in which case the
12075   // object is not really alive and would have been garbage collected if not
12076   // referenced from the mirror.
12077   if (count == 1 && last == target) {
12078     count = 0;
12079   }
12080 
12081   // Return the number of referencing objects found.
12082   return count;
12083 }
12084 
12085 
12086 // Scan the heap for objects with direct references to an object
12087 // args[0]: the object to find references to
12088 // args[1]: constructor function for instances to exclude (Mirror)
12089 // args[2]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugReferencedBy)12090 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12091   ASSERT(args.length() == 3);
12092 
12093   // First perform a full GC in order to avoid references from dead objects.
12094   isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12095                                      "%DebugReferencedBy");
12096   // The heap iterator reserves the right to do a GC to make the heap iterable.
12097   // Due to the GC above we know it won't need to do that, but it seems cleaner
12098   // to get the heap iterator constructed before we start having unprotected
12099   // Object* locals that are not protected by handles.
12100 
12101   // Check parameters.
12102   CONVERT_ARG_CHECKED(JSObject, target, 0);
12103   Object* instance_filter = args[1];
12104   RUNTIME_ASSERT(instance_filter->IsUndefined() ||
12105                  instance_filter->IsJSObject());
12106   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
12107   RUNTIME_ASSERT(max_references >= 0);
12108 
12109 
12110   // Get the constructor function for context extension and arguments array.
12111   JSObject* arguments_boilerplate =
12112       isolate->context()->global_context()->arguments_boilerplate();
12113   JSFunction* arguments_function =
12114       JSFunction::cast(arguments_boilerplate->map()->constructor());
12115 
12116   // Get the number of referencing objects.
12117   int count;
12118   HeapIterator heap_iterator;
12119   count = DebugReferencedBy(&heap_iterator,
12120                             target, instance_filter, max_references,
12121                             NULL, 0, arguments_function);
12122 
12123   // Allocate an array to hold the result.
12124   Object* object;
12125   { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12126     if (!maybe_object->ToObject(&object)) return maybe_object;
12127   }
12128   FixedArray* instances = FixedArray::cast(object);
12129 
12130   // Fill the referencing objects.
12131   // AllocateFixedArray above does not make the heap non-iterable.
12132   ASSERT(HEAP->IsHeapIterable());
12133   HeapIterator heap_iterator2;
12134   count = DebugReferencedBy(&heap_iterator2,
12135                             target, instance_filter, max_references,
12136                             instances, count, arguments_function);
12137 
12138   // Return result as JS array.
12139   Object* result;
12140   MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12141       isolate->context()->global_context()->array_function());
12142   if (!maybe_result->ToObject(&result)) return maybe_result;
12143   return JSArray::cast(result)->SetContent(instances);
12144 }
12145 
12146 
12147 // Helper function used by Runtime_DebugConstructedBy below.
DebugConstructedBy(HeapIterator * iterator,JSFunction * constructor,int max_references,FixedArray * instances,int instances_size)12148 static int DebugConstructedBy(HeapIterator* iterator,
12149                               JSFunction* constructor,
12150                               int max_references,
12151                               FixedArray* instances,
12152                               int instances_size) {
12153   AssertNoAllocation no_alloc;
12154 
12155   // Iterate the heap.
12156   int count = 0;
12157   HeapObject* heap_obj = NULL;
12158   while (((heap_obj = iterator->next()) != NULL) &&
12159          (max_references == 0 || count < max_references)) {
12160     // Only look at all JSObjects.
12161     if (heap_obj->IsJSObject()) {
12162       JSObject* obj = JSObject::cast(heap_obj);
12163       if (obj->map()->constructor() == constructor) {
12164         // Valid reference found add to instance array if supplied an update
12165         // count.
12166         if (instances != NULL && count < instances_size) {
12167           instances->set(count, obj);
12168         }
12169         count++;
12170       }
12171     }
12172   }
12173 
12174   // Return the number of referencing objects found.
12175   return count;
12176 }
12177 
12178 
12179 // Scan the heap for objects constructed by a specific function.
12180 // args[0]: the constructor to find instances of
12181 // args[1]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugConstructedBy)12182 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
12183   ASSERT(args.length() == 2);
12184 
12185   // First perform a full GC in order to avoid dead objects.
12186   isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12187                                      "%DebugConstructedBy");
12188 
12189   // Check parameters.
12190   CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
12191   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
12192   RUNTIME_ASSERT(max_references >= 0);
12193 
12194   // Get the number of referencing objects.
12195   int count;
12196   HeapIterator heap_iterator;
12197   count = DebugConstructedBy(&heap_iterator,
12198                              constructor,
12199                              max_references,
12200                              NULL,
12201                              0);
12202 
12203   // Allocate an array to hold the result.
12204   Object* object;
12205   { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12206     if (!maybe_object->ToObject(&object)) return maybe_object;
12207   }
12208   FixedArray* instances = FixedArray::cast(object);
12209 
12210   ASSERT(HEAP->IsHeapIterable());
12211   // Fill the referencing objects.
12212   HeapIterator heap_iterator2;
12213   count = DebugConstructedBy(&heap_iterator2,
12214                              constructor,
12215                              max_references,
12216                              instances,
12217                              count);
12218 
12219   // Return result as JS array.
12220   Object* result;
12221   { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12222           isolate->context()->global_context()->array_function());
12223     if (!maybe_result->ToObject(&result)) return maybe_result;
12224   }
12225   return JSArray::cast(result)->SetContent(instances);
12226 }
12227 
12228 
12229 // Find the effective prototype object as returned by __proto__.
12230 // args[0]: the object to find the prototype for.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetPrototype)12231 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
12232   ASSERT(args.length() == 1);
12233 
12234   CONVERT_ARG_CHECKED(JSObject, obj, 0);
12235 
12236   // Use the __proto__ accessor.
12237   return Accessors::ObjectPrototype.getter(obj, NULL);
12238 }
12239 
12240 
12241 // Patches script source (should be called upon BeforeCompile event).
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugSetScriptSource)12242 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
12243   HandleScope scope(isolate);
12244   ASSERT(args.length() == 2);
12245 
12246   CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
12247   Handle<String> source(String::cast(args[1]));
12248 
12249   RUNTIME_ASSERT(script_wrapper->value()->IsScript());
12250   Handle<Script> script(Script::cast(script_wrapper->value()));
12251 
12252   int compilation_state = Smi::cast(script->compilation_state())->value();
12253   RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
12254   script->set_source(*source);
12255 
12256   return isolate->heap()->undefined_value();
12257 }
12258 
12259 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SystemBreak)12260 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
12261   ASSERT(args.length() == 0);
12262   CPU::DebugBreak();
12263   return isolate->heap()->undefined_value();
12264 }
12265 
12266 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugDisassembleFunction)12267 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
12268 #ifdef DEBUG
12269   HandleScope scope(isolate);
12270   ASSERT(args.length() == 1);
12271   // Get the function and make sure it is compiled.
12272   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12273   Handle<SharedFunctionInfo> shared(func->shared());
12274   if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
12275     return Failure::Exception();
12276   }
12277   func->code()->PrintLn();
12278 #endif  // DEBUG
12279   return isolate->heap()->undefined_value();
12280 }
12281 
12282 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugDisassembleConstructor)12283 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
12284 #ifdef DEBUG
12285   HandleScope scope(isolate);
12286   ASSERT(args.length() == 1);
12287   // Get the function and make sure it is compiled.
12288   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12289   Handle<SharedFunctionInfo> shared(func->shared());
12290   if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
12291     return Failure::Exception();
12292   }
12293   shared->construct_stub()->PrintLn();
12294 #endif  // DEBUG
12295   return isolate->heap()->undefined_value();
12296 }
12297 
12298 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetInferredName)12299 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
12300   NoHandleAllocation ha;
12301   ASSERT(args.length() == 1);
12302 
12303   CONVERT_ARG_CHECKED(JSFunction, f, 0);
12304   return f->shared()->inferred_name();
12305 }
12306 
12307 
FindSharedFunctionInfosForScript(HeapIterator * iterator,Script * script,FixedArray * buffer)12308 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
12309                                             Script* script,
12310                                             FixedArray* buffer) {
12311   AssertNoAllocation no_allocations;
12312   int counter = 0;
12313   int buffer_size = buffer->length();
12314   for (HeapObject* obj = iterator->next();
12315        obj != NULL;
12316        obj = iterator->next()) {
12317     ASSERT(obj != NULL);
12318     if (!obj->IsSharedFunctionInfo()) {
12319       continue;
12320     }
12321     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
12322     if (shared->script() != script) {
12323       continue;
12324     }
12325     if (counter < buffer_size) {
12326       buffer->set(counter, shared);
12327     }
12328     counter++;
12329   }
12330   return counter;
12331 }
12332 
12333 // For a script finds all SharedFunctionInfo's in the heap that points
12334 // to this script. Returns JSArray of SharedFunctionInfo wrapped
12335 // in OpaqueReferences.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFindSharedFunctionInfosForScript)12336 RUNTIME_FUNCTION(MaybeObject*,
12337                  Runtime_LiveEditFindSharedFunctionInfosForScript) {
12338   ASSERT(args.length() == 1);
12339   HandleScope scope(isolate);
12340   CONVERT_ARG_CHECKED(JSValue, script_value, 0);
12341 
12342 
12343   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
12344 
12345   const int kBufferSize = 32;
12346 
12347   Handle<FixedArray> array;
12348   array = isolate->factory()->NewFixedArray(kBufferSize);
12349   int number;
12350   {
12351     isolate->heap()->EnsureHeapIsIterable();
12352     AssertNoAllocation no_allocations;
12353     HeapIterator heap_iterator;
12354     Script* scr = *script;
12355     FixedArray* arr = *array;
12356     number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12357   }
12358   if (number > kBufferSize) {
12359     array = isolate->factory()->NewFixedArray(number);
12360     isolate->heap()->EnsureHeapIsIterable();
12361     AssertNoAllocation no_allocations;
12362     HeapIterator heap_iterator;
12363     Script* scr = *script;
12364     FixedArray* arr = *array;
12365     FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12366   }
12367 
12368   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
12369   result->set_length(Smi::FromInt(number));
12370 
12371   LiveEdit::WrapSharedFunctionInfos(result);
12372 
12373   return *result;
12374 }
12375 
12376 // For a script calculates compilation information about all its functions.
12377 // The script source is explicitly specified by the second argument.
12378 // The source of the actual script is not used, however it is important that
12379 // all generated code keeps references to this particular instance of script.
12380 // Returns a JSArray of compilation infos. The array is ordered so that
12381 // each function with all its descendant is always stored in a continues range
12382 // with the function itself going first. The root function is a script function.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditGatherCompileInfo)12383 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
12384   ASSERT(args.length() == 2);
12385   HandleScope scope(isolate);
12386   CONVERT_ARG_CHECKED(JSValue, script, 0);
12387   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12388   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
12389 
12390   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
12391 
12392   if (isolate->has_pending_exception()) {
12393     return Failure::Exception();
12394   }
12395 
12396   return result;
12397 }
12398 
12399 // Changes the source of the script to a new_source.
12400 // If old_script_name is provided (i.e. is a String), also creates a copy of
12401 // the script with its original source and sends notification to debugger.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceScript)12402 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
12403   ASSERT(args.length() == 3);
12404   HandleScope scope(isolate);
12405   CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
12406   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
12407   Handle<Object> old_script_name(args[2], isolate);
12408 
12409   RUNTIME_ASSERT(original_script_value->value()->IsScript());
12410   Handle<Script> original_script(Script::cast(original_script_value->value()));
12411 
12412   Object* old_script = LiveEdit::ChangeScriptSource(original_script,
12413                                                     new_source,
12414                                                     old_script_name);
12415 
12416   if (old_script->IsScript()) {
12417     Handle<Script> script_handle(Script::cast(old_script));
12418     return *(GetScriptWrapper(script_handle));
12419   } else {
12420     return isolate->heap()->null_value();
12421   }
12422 }
12423 
12424 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFunctionSourceUpdated)12425 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
12426   ASSERT(args.length() == 1);
12427   HandleScope scope(isolate);
12428   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
12429   return LiveEdit::FunctionSourceUpdated(shared_info);
12430 }
12431 
12432 
12433 // Replaces code of SharedFunctionInfo with a new one.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceFunctionCode)12434 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
12435   ASSERT(args.length() == 2);
12436   HandleScope scope(isolate);
12437   CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
12438   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
12439 
12440   return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
12441 }
12442 
12443 // Connects SharedFunctionInfo to another script.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFunctionSetScript)12444 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
12445   ASSERT(args.length() == 2);
12446   HandleScope scope(isolate);
12447   Handle<Object> function_object(args[0], isolate);
12448   Handle<Object> script_object(args[1], isolate);
12449 
12450   if (function_object->IsJSValue()) {
12451     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
12452     if (script_object->IsJSValue()) {
12453       RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
12454       Script* script = Script::cast(JSValue::cast(*script_object)->value());
12455       script_object = Handle<Object>(script, isolate);
12456     }
12457 
12458     LiveEdit::SetFunctionScript(function_wrapper, script_object);
12459   } else {
12460     // Just ignore this. We may not have a SharedFunctionInfo for some functions
12461     // and we check it in this function.
12462   }
12463 
12464   return isolate->heap()->undefined_value();
12465 }
12466 
12467 
12468 // In a code of a parent function replaces original function as embedded object
12469 // with a substitution one.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceRefToNestedFunction)12470 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
12471   ASSERT(args.length() == 3);
12472   HandleScope scope(isolate);
12473 
12474   CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
12475   CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
12476   CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
12477 
12478   LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
12479                                        subst_wrapper);
12480 
12481   return isolate->heap()->undefined_value();
12482 }
12483 
12484 
12485 // Updates positions of a shared function info (first parameter) according
12486 // to script source change. Text change is described in second parameter as
12487 // array of groups of 3 numbers:
12488 // (change_begin, change_end, change_end_new_position).
12489 // Each group describes a change in text; groups are sorted by change_begin.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditPatchFunctionPositions)12490 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
12491   ASSERT(args.length() == 2);
12492   HandleScope scope(isolate);
12493   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12494   CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
12495 
12496   return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
12497 }
12498 
12499 
12500 // For array of SharedFunctionInfo's (each wrapped in JSValue)
12501 // checks that none of them have activations on stacks (of any thread).
12502 // Returns array of the same length with corresponding results of
12503 // LiveEdit::FunctionPatchabilityStatus type.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditCheckAndDropActivations)12504 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
12505   ASSERT(args.length() == 2);
12506   HandleScope scope(isolate);
12507   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12508   CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
12509 
12510   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
12511 }
12512 
12513 // Compares 2 strings line-by-line, then token-wise and returns diff in form
12514 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
12515 // of diff chunks.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditCompareStrings)12516 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
12517   ASSERT(args.length() == 2);
12518   HandleScope scope(isolate);
12519   CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
12520   CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
12521 
12522   return *LiveEdit::CompareStrings(s1, s2);
12523 }
12524 
12525 
12526 // A testing entry. Returns statement position which is the closest to
12527 // source_position.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionCodePositionFromSource)12528 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
12529   ASSERT(args.length() == 2);
12530   HandleScope scope(isolate);
12531   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12532   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12533 
12534   Handle<Code> code(function->code(), isolate);
12535 
12536   if (code->kind() != Code::FUNCTION &&
12537       code->kind() != Code::OPTIMIZED_FUNCTION) {
12538     return isolate->heap()->undefined_value();
12539   }
12540 
12541   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
12542   int closest_pc = 0;
12543   int distance = kMaxInt;
12544   while (!it.done()) {
12545     int statement_position = static_cast<int>(it.rinfo()->data());
12546     // Check if this break point is closer that what was previously found.
12547     if (source_position <= statement_position &&
12548         statement_position - source_position < distance) {
12549       closest_pc =
12550           static_cast<int>(it.rinfo()->pc() - code->instruction_start());
12551       distance = statement_position - source_position;
12552       // Check whether we can't get any closer.
12553       if (distance == 0) break;
12554     }
12555     it.next();
12556   }
12557 
12558   return Smi::FromInt(closest_pc);
12559 }
12560 
12561 
12562 // Calls specified function with or without entering the debugger.
12563 // This is used in unit tests to run code as if debugger is entered or simply
12564 // to have a stack with C++ frame in the middle.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ExecuteInDebugContext)12565 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
12566   ASSERT(args.length() == 2);
12567   HandleScope scope(isolate);
12568   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12569   CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
12570 
12571   Handle<Object> result;
12572   bool pending_exception;
12573   {
12574     if (without_debugger) {
12575       result = Execution::Call(function, isolate->global(), 0, NULL,
12576                                &pending_exception);
12577     } else {
12578       EnterDebugger enter_debugger;
12579       result = Execution::Call(function, isolate->global(), 0, NULL,
12580                                &pending_exception);
12581     }
12582   }
12583   if (!pending_exception) {
12584     return *result;
12585   } else {
12586     return Failure::Exception();
12587   }
12588 }
12589 
12590 
12591 // Sets a v8 flag.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetFlags)12592 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
12593   CONVERT_ARG_CHECKED(String, arg, 0);
12594   SmartArrayPointer<char> flags =
12595       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
12596   FlagList::SetFlagsFromString(*flags, StrLength(*flags));
12597   return isolate->heap()->undefined_value();
12598 }
12599 
12600 
12601 // Performs a GC.
12602 // Presently, it only does a full GC.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CollectGarbage)12603 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
12604   isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
12605   return isolate->heap()->undefined_value();
12606 }
12607 
12608 
12609 // Gets the current heap usage.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetHeapUsage)12610 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
12611   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
12612   if (!Smi::IsValid(usage)) {
12613     return *isolate->factory()->NewNumberFromInt(usage);
12614   }
12615   return Smi::FromInt(usage);
12616 }
12617 
12618 
12619 // Captures a live object list from the present heap.
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasLOLEnabled)12620 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLOLEnabled) {
12621 #ifdef LIVE_OBJECT_LIST
12622   return isolate->heap()->true_value();
12623 #else
12624   return isolate->heap()->false_value();
12625 #endif
12626 }
12627 
12628 
12629 // Captures a live object list from the present heap.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CaptureLOL)12630 RUNTIME_FUNCTION(MaybeObject*, Runtime_CaptureLOL) {
12631 #ifdef LIVE_OBJECT_LIST
12632   return LiveObjectList::Capture();
12633 #else
12634   return isolate->heap()->undefined_value();
12635 #endif
12636 }
12637 
12638 
12639 // Deletes the specified live object list.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteLOL)12640 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) {
12641 #ifdef LIVE_OBJECT_LIST
12642   CONVERT_SMI_ARG_CHECKED(id, 0);
12643   bool success = LiveObjectList::Delete(id);
12644   return isolate->heap()->ToBoolean(success);
12645 #else
12646   return isolate->heap()->undefined_value();
12647 #endif
12648 }
12649 
12650 
12651 // Generates the response to a debugger request for a dump of the objects
12652 // contained in the difference between the captured live object lists
12653 // specified by id1 and id2.
12654 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12655 // dumped.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DumpLOL)12656 RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) {
12657 #ifdef LIVE_OBJECT_LIST
12658   HandleScope scope;
12659   CONVERT_SMI_ARG_CHECKED(id1, 0);
12660   CONVERT_SMI_ARG_CHECKED(id2, 1);
12661   CONVERT_SMI_ARG_CHECKED(start, 2);
12662   CONVERT_SMI_ARG_CHECKED(count, 3);
12663   CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 4);
12664   EnterDebugger enter_debugger;
12665   return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
12666 #else
12667   return isolate->heap()->undefined_value();
12668 #endif
12669 }
12670 
12671 
12672 // Gets the specified object as requested by the debugger.
12673 // This is only used for obj ids shown in live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLObj)12674 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) {
12675 #ifdef LIVE_OBJECT_LIST
12676   CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12677   Object* result = LiveObjectList::GetObj(obj_id);
12678   return result;
12679 #else
12680   return isolate->heap()->undefined_value();
12681 #endif
12682 }
12683 
12684 
12685 // Gets the obj id for the specified address if valid.
12686 // This is only used for obj ids shown in live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLObjId)12687 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) {
12688 #ifdef LIVE_OBJECT_LIST
12689   HandleScope scope;
12690   CONVERT_ARG_HANDLE_CHECKED(String, address, 0);
12691   Object* result = LiveObjectList::GetObjId(address);
12692   return result;
12693 #else
12694   return isolate->heap()->undefined_value();
12695 #endif
12696 }
12697 
12698 
12699 // Gets the retainers that references the specified object alive.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLObjRetainers)12700 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) {
12701 #ifdef LIVE_OBJECT_LIST
12702   HandleScope scope;
12703   CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12704   RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject());
12705   RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean());
12706   RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi());
12707   RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi());
12708   CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 5);
12709 
12710   Handle<JSObject> instance_filter;
12711   if (args[1]->IsJSObject()) {
12712     instance_filter = args.at<JSObject>(1);
12713   }
12714   bool verbose = false;
12715   if (args[2]->IsBoolean()) {
12716     verbose = args[2]->IsTrue();
12717   }
12718   int start = 0;
12719   if (args[3]->IsSmi()) {
12720     start = args.smi_at(3);
12721   }
12722   int limit = Smi::kMaxValue;
12723   if (args[4]->IsSmi()) {
12724     limit = args.smi_at(4);
12725   }
12726 
12727   return LiveObjectList::GetObjRetainers(obj_id,
12728                                          instance_filter,
12729                                          verbose,
12730                                          start,
12731                                          limit,
12732                                          filter_obj);
12733 #else
12734   return isolate->heap()->undefined_value();
12735 #endif
12736 }
12737 
12738 
12739 // Gets the reference path between 2 objects.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLPath)12740 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) {
12741 #ifdef LIVE_OBJECT_LIST
12742   HandleScope scope;
12743   CONVERT_SMI_ARG_CHECKED(obj_id1, 0);
12744   CONVERT_SMI_ARG_CHECKED(obj_id2, 1);
12745   RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject());
12746 
12747   Handle<JSObject> instance_filter;
12748   if (args[2]->IsJSObject()) {
12749     instance_filter = args.at<JSObject>(2);
12750   }
12751 
12752   Object* result =
12753       LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
12754   return result;
12755 #else
12756   return isolate->heap()->undefined_value();
12757 #endif
12758 }
12759 
12760 
12761 // Generates the response to a debugger request for a list of all
12762 // previously captured live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_InfoLOL)12763 RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) {
12764 #ifdef LIVE_OBJECT_LIST
12765   CONVERT_SMI_ARG_CHECKED(start, 0);
12766   CONVERT_SMI_ARG_CHECKED(count, 1);
12767   return LiveObjectList::Info(start, count);
12768 #else
12769   return isolate->heap()->undefined_value();
12770 #endif
12771 }
12772 
12773 
12774 // Gets a dump of the specified object as requested by the debugger.
12775 // This is only used for obj ids shown in live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PrintLOLObj)12776 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) {
12777 #ifdef LIVE_OBJECT_LIST
12778   HandleScope scope;
12779   CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12780   Object* result = LiveObjectList::PrintObj(obj_id);
12781   return result;
12782 #else
12783   return isolate->heap()->undefined_value();
12784 #endif
12785 }
12786 
12787 
12788 // Resets and releases all previously captured live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ResetLOL)12789 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) {
12790 #ifdef LIVE_OBJECT_LIST
12791   LiveObjectList::Reset();
12792   return isolate->heap()->undefined_value();
12793 #else
12794   return isolate->heap()->undefined_value();
12795 #endif
12796 }
12797 
12798 
12799 // Generates the response to a debugger request for a summary of the types
12800 // of objects in the difference between the captured live object lists
12801 // specified by id1 and id2.
12802 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12803 // summarized.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SummarizeLOL)12804 RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) {
12805 #ifdef LIVE_OBJECT_LIST
12806   HandleScope scope;
12807   CONVERT_SMI_ARG_CHECKED(id1, 0);
12808   CONVERT_SMI_ARG_CHECKED(id2, 1);
12809   CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 2);
12810 
12811   EnterDebugger enter_debugger;
12812   return LiveObjectList::Summarize(id1, id2, filter_obj);
12813 #else
12814   return isolate->heap()->undefined_value();
12815 #endif
12816 }
12817 
12818 #endif  // ENABLE_DEBUGGER_SUPPORT
12819 
12820 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ProfilerResume)12821 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) {
12822   NoHandleAllocation ha;
12823   v8::V8::ResumeProfiler();
12824   return isolate->heap()->undefined_value();
12825 }
12826 
12827 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ProfilerPause)12828 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) {
12829   NoHandleAllocation ha;
12830   v8::V8::PauseProfiler();
12831   return isolate->heap()->undefined_value();
12832 }
12833 
12834 
12835 // Finds the script object from the script data. NOTE: This operation uses
12836 // heap traversal to find the function generated for the source position
12837 // for the requested break point. For lazily compiled functions several heap
12838 // traversals might be required rendering this operation as a rather slow
12839 // operation. However for setting break points which is normally done through
12840 // some kind of user interaction the performance is not crucial.
Runtime_GetScriptFromScriptName(Handle<String> script_name)12841 static Handle<Object> Runtime_GetScriptFromScriptName(
12842     Handle<String> script_name) {
12843   // Scan the heap for Script objects to find the script with the requested
12844   // script data.
12845   Handle<Script> script;
12846   script_name->GetHeap()->EnsureHeapIsIterable();
12847   AssertNoAllocation no_allocation_during_heap_iteration;
12848   HeapIterator iterator;
12849   HeapObject* obj = NULL;
12850   while (script.is_null() && ((obj = iterator.next()) != NULL)) {
12851     // If a script is found check if it has the script data requested.
12852     if (obj->IsScript()) {
12853       if (Script::cast(obj)->name()->IsString()) {
12854         if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
12855           script = Handle<Script>(Script::cast(obj));
12856         }
12857       }
12858     }
12859   }
12860 
12861   // If no script with the requested script data is found return undefined.
12862   if (script.is_null()) return FACTORY->undefined_value();
12863 
12864   // Return the script found.
12865   return GetScriptWrapper(script);
12866 }
12867 
12868 
12869 // Get the script object from script data. NOTE: Regarding performance
12870 // see the NOTE for GetScriptFromScriptData.
12871 // args[0]: script data for the script to find the source for
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScript)12872 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
12873   HandleScope scope(isolate);
12874 
12875   ASSERT(args.length() == 1);
12876 
12877   CONVERT_ARG_CHECKED(String, script_name, 0);
12878 
12879   // Find the requested script.
12880   Handle<Object> result =
12881       Runtime_GetScriptFromScriptName(Handle<String>(script_name));
12882   return *result;
12883 }
12884 
12885 
12886 // Determines whether the given stack frame should be displayed in
12887 // a stack trace.  The caller is the error constructor that asked
12888 // for the stack trace to be collected.  The first time a construct
12889 // call to this function is encountered it is skipped.  The seen_caller
12890 // in/out parameter is used to remember if the caller has been seen
12891 // yet.
ShowFrameInStackTrace(StackFrame * raw_frame,Object * caller,bool * seen_caller)12892 static bool ShowFrameInStackTrace(StackFrame* raw_frame,
12893                                   Object* caller,
12894                                   bool* seen_caller) {
12895   // Only display JS frames.
12896   if (!raw_frame->is_java_script()) {
12897     return false;
12898   }
12899   JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12900   Object* raw_fun = frame->function();
12901   // Not sure when this can happen but skip it just in case.
12902   if (!raw_fun->IsJSFunction()) {
12903     return false;
12904   }
12905   if ((raw_fun == caller) && !(*seen_caller)) {
12906     *seen_caller = true;
12907     return false;
12908   }
12909   // Skip all frames until we've seen the caller.
12910   if (!(*seen_caller)) return false;
12911   // Also, skip non-visible built-in functions and any call with the builtins
12912   // object as receiver, so as to not reveal either the builtins object or
12913   // an internal function.
12914   // The --builtins-in-stack-traces command line flag allows including
12915   // internal call sites in the stack trace for debugging purposes.
12916   if (!FLAG_builtins_in_stack_traces) {
12917     JSFunction* fun = JSFunction::cast(raw_fun);
12918     if (frame->receiver()->IsJSBuiltinsObject() ||
12919         (fun->IsBuiltin() && !fun->shared()->native())) {
12920       return false;
12921     }
12922   }
12923   return true;
12924 }
12925 
12926 
12927 // Collect the raw data for a stack trace.  Returns an array of 4
12928 // element segments each containing a receiver, function, code and
12929 // native code offset.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CollectStackTrace)12930 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
12931   ASSERT_EQ(args.length(), 3);
12932   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
12933   Handle<Object> caller = args.at<Object>(1);
12934   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
12935 
12936   HandleScope scope(isolate);
12937   Factory* factory = isolate->factory();
12938 
12939   limit = Max(limit, 0);  // Ensure that limit is not negative.
12940   int initial_size = Min(limit, 10);
12941   Handle<FixedArray> elements =
12942       factory->NewFixedArrayWithHoles(initial_size * 4);
12943 
12944   StackFrameIterator iter(isolate);
12945   // If the caller parameter is a function we skip frames until we're
12946   // under it before starting to collect.
12947   bool seen_caller = !caller->IsJSFunction();
12948   int cursor = 0;
12949   int frames_seen = 0;
12950   while (!iter.done() && frames_seen < limit) {
12951     StackFrame* raw_frame = iter.frame();
12952     if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
12953       frames_seen++;
12954       JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12955       // Set initial size to the maximum inlining level + 1 for the outermost
12956       // function.
12957       List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1);
12958       frame->Summarize(&frames);
12959       for (int i = frames.length() - 1; i >= 0; i--) {
12960         if (cursor + 4 > elements->length()) {
12961           int new_capacity = JSObject::NewElementsCapacity(elements->length());
12962           Handle<FixedArray> new_elements =
12963               factory->NewFixedArrayWithHoles(new_capacity);
12964           for (int i = 0; i < cursor; i++) {
12965             new_elements->set(i, elements->get(i));
12966           }
12967           elements = new_elements;
12968         }
12969         ASSERT(cursor + 4 <= elements->length());
12970 
12971         Handle<Object> recv = frames[i].receiver();
12972         Handle<JSFunction> fun = frames[i].function();
12973         Handle<Code> code = frames[i].code();
12974         Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
12975         elements->set(cursor++, *recv);
12976         elements->set(cursor++, *fun);
12977         elements->set(cursor++, *code);
12978         elements->set(cursor++, *offset);
12979       }
12980     }
12981     iter.Advance();
12982   }
12983   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
12984   // Capture and attach a more detailed stack trace if necessary.
12985   isolate->CaptureAndSetCurrentStackTraceFor(error_object);
12986   result->set_length(Smi::FromInt(cursor));
12987   return *result;
12988 }
12989 
12990 
12991 // Returns V8 version as a string.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetV8Version)12992 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
12993   ASSERT_EQ(args.length(), 0);
12994 
12995   NoHandleAllocation ha;
12996 
12997   const char* version_string = v8::V8::GetVersion();
12998 
12999   return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
13000                                                   NOT_TENURED);
13001 }
13002 
13003 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Abort)13004 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
13005   ASSERT(args.length() == 2);
13006   OS::PrintError("abort: %s\n",
13007                  reinterpret_cast<char*>(args[0]) + args.smi_at(1));
13008   isolate->PrintStack();
13009   OS::Abort();
13010   UNREACHABLE();
13011   return NULL;
13012 }
13013 
13014 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFromCache)13015 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
13016   // This is only called from codegen, so checks might be more lax.
13017   CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
13018   Object* key = args[1];
13019 
13020   int finger_index = cache->finger_index();
13021   Object* o = cache->get(finger_index);
13022   if (o == key) {
13023     // The fastest case: hit the same place again.
13024     return cache->get(finger_index + 1);
13025   }
13026 
13027   for (int i = finger_index - 2;
13028        i >= JSFunctionResultCache::kEntriesIndex;
13029        i -= 2) {
13030     o = cache->get(i);
13031     if (o == key) {
13032       cache->set_finger_index(i);
13033       return cache->get(i + 1);
13034     }
13035   }
13036 
13037   int size = cache->size();
13038   ASSERT(size <= cache->length());
13039 
13040   for (int i = size - 2; i > finger_index; i -= 2) {
13041     o = cache->get(i);
13042     if (o == key) {
13043       cache->set_finger_index(i);
13044       return cache->get(i + 1);
13045     }
13046   }
13047 
13048   // There is no value in the cache.  Invoke the function and cache result.
13049   HandleScope scope(isolate);
13050 
13051   Handle<JSFunctionResultCache> cache_handle(cache);
13052   Handle<Object> key_handle(key);
13053   Handle<Object> value;
13054   {
13055     Handle<JSFunction> factory(JSFunction::cast(
13056           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
13057     // TODO(antonm): consider passing a receiver when constructing a cache.
13058     Handle<Object> receiver(isolate->global_context()->global());
13059     // This handle is nor shared, nor used later, so it's safe.
13060     Handle<Object> argv[] = { key_handle };
13061     bool pending_exception;
13062     value = Execution::Call(factory,
13063                             receiver,
13064                             ARRAY_SIZE(argv),
13065                             argv,
13066                             &pending_exception);
13067     if (pending_exception) return Failure::Exception();
13068   }
13069 
13070 #ifdef DEBUG
13071   if (FLAG_verify_heap) {
13072     cache_handle->JSFunctionResultCacheVerify();
13073   }
13074 #endif
13075 
13076   // Function invocation may have cleared the cache.  Reread all the data.
13077   finger_index = cache_handle->finger_index();
13078   size = cache_handle->size();
13079 
13080   // If we have spare room, put new data into it, otherwise evict post finger
13081   // entry which is likely to be the least recently used.
13082   int index = -1;
13083   if (size < cache_handle->length()) {
13084     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
13085     index = size;
13086   } else {
13087     index = finger_index + JSFunctionResultCache::kEntrySize;
13088     if (index == cache_handle->length()) {
13089       index = JSFunctionResultCache::kEntriesIndex;
13090     }
13091   }
13092 
13093   ASSERT(index % 2 == 0);
13094   ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
13095   ASSERT(index < cache_handle->length());
13096 
13097   cache_handle->set(index, *key_handle);
13098   cache_handle->set(index + 1, *value);
13099   cache_handle->set_finger_index(index);
13100 
13101 #ifdef DEBUG
13102   if (FLAG_verify_heap) {
13103     cache_handle->JSFunctionResultCacheVerify();
13104   }
13105 #endif
13106 
13107   return *value;
13108 }
13109 
13110 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewMessageObject)13111 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewMessageObject) {
13112   HandleScope scope(isolate);
13113   CONVERT_ARG_HANDLE_CHECKED(String, type, 0);
13114   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 1);
13115   return *isolate->factory()->NewJSMessageObject(
13116       type,
13117       arguments,
13118       0,
13119       0,
13120       isolate->factory()->undefined_value(),
13121       isolate->factory()->undefined_value(),
13122       isolate->factory()->undefined_value());
13123 }
13124 
13125 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetType)13126 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetType) {
13127   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13128   return message->type();
13129 }
13130 
13131 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetArguments)13132 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetArguments) {
13133   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13134   return message->arguments();
13135 }
13136 
13137 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetStartPosition)13138 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
13139   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13140   return Smi::FromInt(message->start_position());
13141 }
13142 
13143 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetScript)13144 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
13145   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13146   return message->script();
13147 }
13148 
13149 
13150 #ifdef DEBUG
13151 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
13152 // Exclude the code in release mode.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ListNatives)13153 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
13154   ASSERT(args.length() == 0);
13155   HandleScope scope;
13156 #define COUNT_ENTRY(Name, argc, ressize) + 1
13157   int entry_count = 0
13158       RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
13159       INLINE_FUNCTION_LIST(COUNT_ENTRY)
13160       INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
13161 #undef COUNT_ENTRY
13162   Factory* factory = isolate->factory();
13163   Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
13164   int index = 0;
13165   bool inline_runtime_functions = false;
13166 #define ADD_ENTRY(Name, argc, ressize)                                       \
13167   {                                                                          \
13168     HandleScope inner;                                                       \
13169     Handle<String> name;                                                     \
13170     /* Inline runtime functions have an underscore in front of the name. */  \
13171     if (inline_runtime_functions) {                                          \
13172       name = factory->NewStringFromAscii(                                    \
13173           Vector<const char>("_" #Name, StrLength("_" #Name)));              \
13174     } else {                                                                 \
13175       name = factory->NewStringFromAscii(                                    \
13176           Vector<const char>(#Name, StrLength(#Name)));                      \
13177     }                                                                        \
13178     Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
13179     pair_elements->set(0, *name);                                            \
13180     pair_elements->set(1, Smi::FromInt(argc));                               \
13181     Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
13182     elements->set(index++, *pair);                                           \
13183   }
13184   inline_runtime_functions = false;
13185   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13186   inline_runtime_functions = true;
13187   INLINE_FUNCTION_LIST(ADD_ENTRY)
13188   INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13189 #undef ADD_ENTRY
13190   ASSERT_EQ(index, entry_count);
13191   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
13192   return *result;
13193 }
13194 #endif
13195 
13196 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Log)13197 RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
13198   ASSERT(args.length() == 2);
13199   CONVERT_ARG_CHECKED(String, format, 0);
13200   CONVERT_ARG_CHECKED(JSArray, elms, 1);
13201   String::FlatContent format_content = format->GetFlatContent();
13202   RUNTIME_ASSERT(format_content.IsAscii());
13203   Vector<const char> chars = format_content.ToAsciiVector();
13204   LOGGER->LogRuntime(chars, elms);
13205   return isolate->heap()->undefined_value();
13206 }
13207 
13208 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IS_VAR)13209 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
13210   UNREACHABLE();  // implemented as macro in the parser
13211   return NULL;
13212 }
13213 
13214 
13215 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
13216   RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
13217     CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
13218     return isolate->heap()->ToBoolean(obj->Has##Name());  \
13219   }
13220 
13221 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOnlyElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements)13222 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements)
13223 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
13224 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
13225 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
13226 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
13227 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
13228 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
13229 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
13230 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
13231 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
13232 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
13233 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
13234 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
13235 
13236 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
13237 
13238 
13239 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
13240   ASSERT(args.length() == 2);
13241   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
13242   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
13243   return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
13244 }
13245 
13246 // ----------------------------------------------------------------------------
13247 // Implementation of Runtime
13248 
13249 #define F(name, number_of_args, result_size)                             \
13250   { Runtime::k##name, Runtime::RUNTIME, #name,   \
13251     FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
13252 
13253 
13254 #define I(name, number_of_args, result_size)                             \
13255   { Runtime::kInline##name, Runtime::INLINE,     \
13256     "_" #name, NULL, number_of_args, result_size },
13257 
13258 static const Runtime::Function kIntrinsicFunctions[] = {
13259   RUNTIME_FUNCTION_LIST(F)
13260   INLINE_FUNCTION_LIST(I)
13261   INLINE_RUNTIME_FUNCTION_LIST(I)
13262 };
13263 
13264 
InitializeIntrinsicFunctionNames(Heap * heap,Object * dictionary)13265 MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
13266                                                        Object* dictionary) {
13267   ASSERT(Isolate::Current()->heap() == heap);
13268   ASSERT(dictionary != NULL);
13269   ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
13270   for (int i = 0; i < kNumFunctions; ++i) {
13271     Object* name_symbol;
13272     { MaybeObject* maybe_name_symbol =
13273           heap->LookupAsciiSymbol(kIntrinsicFunctions[i].name);
13274       if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
13275     }
13276     StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
13277     { MaybeObject* maybe_dictionary = string_dictionary->Add(
13278           String::cast(name_symbol),
13279           Smi::FromInt(i),
13280           PropertyDetails(NONE, NORMAL));
13281       if (!maybe_dictionary->ToObject(&dictionary)) {
13282         // Non-recoverable failure.  Calling code must restart heap
13283         // initialization.
13284         return maybe_dictionary;
13285       }
13286     }
13287   }
13288   return dictionary;
13289 }
13290 
13291 
FunctionForSymbol(Handle<String> name)13292 const Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
13293   Heap* heap = name->GetHeap();
13294   int entry = heap->intrinsic_function_names()->FindEntry(*name);
13295   if (entry != kNotFound) {
13296     Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
13297     int function_index = Smi::cast(smi_index)->value();
13298     return &(kIntrinsicFunctions[function_index]);
13299   }
13300   return NULL;
13301 }
13302 
13303 
FunctionForId(Runtime::FunctionId id)13304 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
13305   return &(kIntrinsicFunctions[static_cast<int>(id)]);
13306 }
13307 
13308 
PerformGC(Object * result)13309 void Runtime::PerformGC(Object* result) {
13310   Isolate* isolate = Isolate::Current();
13311   Failure* failure = Failure::cast(result);
13312   if (failure->IsRetryAfterGC()) {
13313     if (isolate->heap()->new_space()->AddFreshPage()) {
13314       return;
13315     }
13316 
13317     // Try to do a garbage collection; ignore it if it fails. The C
13318     // entry stub will throw an out-of-memory exception in that case.
13319     isolate->heap()->CollectGarbage(failure->allocation_space(),
13320                                     "Runtime::PerformGC");
13321   } else {
13322     // Handle last resort GC and make sure to allow future allocations
13323     // to grow the heap without causing GCs (if possible).
13324     isolate->counters()->gc_last_resort_from_js()->Increment();
13325     isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
13326                                        "Runtime::PerformGC");
13327   }
13328 }
13329 
13330 
13331 } }  // namespace v8::internal
13332