[V8] Add flag to avoid breakpoint relocation
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / runtime.cc
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
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
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]
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
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
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
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
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
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
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
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
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
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
1272 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1273   ASSERT(args.length() == 3);
1274   HandleScope scope(isolate);
1275
1276   Handle<Context> context = args.at<Context>(0);
1277   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
1278   CONVERT_SMI_ARG_CHECKED(flags, 2);
1279
1280   Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global());
1281   Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global());
1282
1283   // Traverse the name/value pairs and set the properties.
1284   int length = pairs->length();
1285   for (int i = 0; i < length; i += 3) {
1286     HandleScope scope(isolate);
1287     Handle<String> name(String::cast(pairs->get(i)));
1288     Handle<Object> value(pairs->get(i + 1), isolate);
1289     Handle<Object> is_qml_global(pairs->get(i + 2));
1290     ASSERT(is_qml_global->IsBoolean());
1291
1292     Handle<JSObject> global = is_qml_global->IsTrue() ? qml_global : js_global;
1293
1294     // We have to declare a global const property. To capture we only
1295     // assign to it when evaluating the assignment for "const x =
1296     // <expr>" the initial value is the hole.
1297     bool is_var = value->IsUndefined();
1298     bool is_const = value->IsTheHole();
1299     bool is_function = value->IsSharedFunctionInfo();
1300     bool is_module = value->IsJSModule();
1301     ASSERT(is_var + is_const + is_function + is_module == 1);
1302
1303     if (is_var || is_const) {
1304       // Lookup the property in the global object, and don't set the
1305       // value of the variable if the property is already there.
1306       // Do the lookup locally only, see ES5 errata.
1307       LookupResult lookup(isolate);
1308       if (FLAG_es52_globals)
1309         global->LocalLookup(*name, &lookup, true);
1310       else
1311         global->Lookup(*name, &lookup, true);
1312       if (lookup.IsProperty()) {
1313         // We found an existing property. Unless it was an interceptor
1314         // that claims the property is absent, skip this declaration.
1315         if (lookup.type() != INTERCEPTOR) continue;
1316         PropertyAttributes attributes = global->GetPropertyAttribute(*name);
1317         if (attributes != ABSENT) continue;
1318         // Fall-through and introduce the absent property by using
1319         // SetProperty.
1320       }
1321     } else if (is_function) {
1322       // Copy the function and update its context. Use it as value.
1323       Handle<SharedFunctionInfo> shared =
1324           Handle<SharedFunctionInfo>::cast(value);
1325       Handle<JSFunction> function =
1326           isolate->factory()->NewFunctionFromSharedFunctionInfo(
1327               shared, context, TENURED);
1328       value = function;
1329     }
1330
1331     LookupResult lookup(isolate);
1332     global->LocalLookup(*name, &lookup, true);
1333
1334     // Compute the property attributes. According to ECMA-262,
1335     // the property must be non-configurable except in eval.
1336     int attr = NONE;
1337     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
1338     if (!is_eval || is_module) {
1339       attr |= DONT_DELETE;
1340     }
1341     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
1342     if (is_const || is_module || (is_native && is_function)) {
1343       attr |= READ_ONLY;
1344     }
1345
1346     LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
1347
1348     if (!lookup.IsProperty() || is_function || is_module) {
1349       // If the local property exists, check that we can reconfigure it
1350       // as required for function declarations.
1351       if (lookup.IsProperty() && lookup.IsDontDelete()) {
1352         if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
1353             lookup.type() == CALLBACKS) {
1354           return ThrowRedeclarationError(
1355               isolate, is_function ? "function" : "module", name);
1356         }
1357         // If the existing property is not configurable, keep its attributes.
1358         attr = lookup.GetAttributes();
1359       }
1360       // Define or redefine own property.
1361       RETURN_IF_EMPTY_HANDLE(isolate,
1362           JSObject::SetLocalPropertyIgnoreAttributes(
1363               global, name, value, static_cast<PropertyAttributes>(attr)));
1364     } else {
1365       // Do a [[Put]] on the existing (own) property.
1366       RETURN_IF_EMPTY_HANDLE(isolate,
1367           JSObject::SetProperty(
1368               global, name, value, static_cast<PropertyAttributes>(attr),
1369               language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode,
1370               true));
1371     }
1372   }
1373
1374   ASSERT(!isolate->has_pending_exception());
1375   return isolate->heap()->undefined_value();
1376 }
1377
1378
1379 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1380   HandleScope scope(isolate);
1381   ASSERT(args.length() == 4);
1382
1383   // Declarations are always made in a function or global context.  In the
1384   // case of eval code, the context passed is the context of the caller,
1385   // which may be some nested context and not the declaration context.
1386   RUNTIME_ASSERT(args[0]->IsContext());
1387   Handle<Context> context(Context::cast(args[0])->declaration_context());
1388
1389   Handle<String> name(String::cast(args[1]));
1390   PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
1391   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1392   Handle<Object> initial_value(args[3], isolate);
1393
1394   int index;
1395   PropertyAttributes attributes;
1396   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
1397   BindingFlags binding_flags;
1398   Handle<Object> holder =
1399       context->Lookup(name, flags, &index, &attributes, &binding_flags);
1400
1401   if (attributes != ABSENT) {
1402     // The name was declared before; check for conflicting re-declarations.
1403     // Note: this is actually inconsistent with what happens for globals (where
1404     // we silently ignore such declarations).
1405     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1406       // Functions are not read-only.
1407       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1408       const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1409       return ThrowRedeclarationError(isolate, type, name);
1410     }
1411
1412     // Initialize it if necessary.
1413     if (*initial_value != NULL) {
1414       if (index >= 0) {
1415         ASSERT(holder.is_identical_to(context));
1416         if (((attributes & READ_ONLY) == 0) ||
1417             context->get(index)->IsTheHole()) {
1418           context->set(index, *initial_value);
1419         }
1420       } else {
1421         // Slow case: The property is in the context extension object of a
1422         // function context or the global object of a global context.
1423         Handle<JSObject> object = Handle<JSObject>::cast(holder);
1424         RETURN_IF_EMPTY_HANDLE(
1425             isolate,
1426             JSReceiver::SetProperty(object, name, initial_value, mode,
1427                                     kNonStrictMode));
1428       }
1429     }
1430
1431   } else {
1432     // The property is not in the function context. It needs to be
1433     // "declared" in the function context's extension context or as a
1434     // property of the the global object.
1435     Handle<JSObject> object;
1436     if (context->has_extension()) {
1437       object = Handle<JSObject>(JSObject::cast(context->extension()));
1438     } else {
1439       // Context extension objects are allocated lazily.
1440       ASSERT(context->IsFunctionContext());
1441       object = isolate->factory()->NewJSObject(
1442           isolate->context_extension_function());
1443       context->set_extension(*object);
1444     }
1445     ASSERT(*object != NULL);
1446
1447     // Declare the property by setting it to the initial value if provided,
1448     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
1449     // constant declarations).
1450     ASSERT(!object->HasLocalProperty(*name));
1451     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
1452     if (*initial_value != NULL) value = initial_value;
1453     // Declaring a const context slot is a conflicting declaration if
1454     // there is a callback with that name in a prototype. It is
1455     // allowed to introduce const variables in
1456     // JSContextExtensionObjects. They are treated specially in
1457     // SetProperty and no setters are invoked for those since they are
1458     // not real JSObjects.
1459     if (initial_value->IsTheHole() &&
1460         !object->IsJSContextExtensionObject()) {
1461       LookupResult lookup(isolate);
1462       object->Lookup(*name, &lookup);
1463       if (lookup.IsFound() && (lookup.type() == CALLBACKS)) {
1464         return ThrowRedeclarationError(isolate, "const", name);
1465       }
1466     }
1467     if (object->IsJSGlobalObject()) {
1468       // Define own property on the global object.
1469       RETURN_IF_EMPTY_HANDLE(isolate,
1470          JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
1471     } else {
1472       RETURN_IF_EMPTY_HANDLE(isolate,
1473          JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
1474     }
1475   }
1476
1477   return isolate->heap()->undefined_value();
1478 }
1479
1480
1481 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
1482   NoHandleAllocation nha;
1483   // args[0] == name
1484   // args[1] == language_mode
1485   // args[2] == qml_mode
1486   // args[3] == value (optional)
1487
1488   // Determine if we need to assign to the variable if it already
1489   // exists (based on the number of arguments).
1490   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
1491   bool assign = args.length() == 4;
1492
1493   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1494   RUNTIME_ASSERT(args[1]->IsSmi());
1495   CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
1496   StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
1497       ? kNonStrictMode : kStrictMode;
1498
1499   RUNTIME_ASSERT(args[2]->IsSmi());
1500   int qml_mode = Smi::cast(args[2])->value();
1501
1502   JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
1503
1504   // According to ECMA-262, section 12.2, page 62, the property must
1505   // not be deletable.
1506   PropertyAttributes attributes = DONT_DELETE;
1507
1508   // Lookup the property locally in the global object. If it isn't
1509   // there, there is a property with this name in the prototype chain.
1510   // We follow Safari and Firefox behavior and only set the property
1511   // locally if there is an explicit initialization value that we have
1512   // to assign to the property.
1513   // Note that objects can have hidden prototypes, so we need to traverse
1514   // the whole chain of hidden prototypes to do a 'local' lookup.
1515   Object* object = global;
1516   LookupResult lookup(isolate);
1517   while (object->IsJSObject() &&
1518          JSObject::cast(object)->map()->is_hidden_prototype()) {
1519     JSObject* raw_holder = JSObject::cast(object);
1520     raw_holder->LocalLookup(*name, &lookup, true);
1521     if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
1522       HandleScope handle_scope(isolate);
1523       Handle<JSObject> holder(raw_holder);
1524       PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
1525       // Update the raw pointer in case it's changed due to GC.
1526       raw_holder = *holder;
1527       if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1528         // Found an interceptor that's not read only.
1529         if (assign) {
1530           return raw_holder->SetProperty(
1531               &lookup, *name, args[3], attributes, strict_mode_flag);
1532         } else {
1533           return isolate->heap()->undefined_value();
1534         }
1535       }
1536     }
1537     object = raw_holder->GetPrototype();
1538   }
1539
1540   // Reload global in case the loop above performed a GC.
1541   global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
1542   if (assign) {
1543     return global->SetProperty(
1544         *name, args[3], attributes, strict_mode_flag, true);
1545   }
1546   return isolate->heap()->undefined_value();
1547 }
1548
1549
1550 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
1551   // All constants are declared with an initial value. The name
1552   // of the constant is the first argument and the initial value
1553   // is the second.
1554   RUNTIME_ASSERT(args.length() == 3);
1555   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1556   Handle<Object> value = args.at<Object>(1);
1557
1558   RUNTIME_ASSERT(args[2]->IsSmi());
1559   int qml_mode = Smi::cast(args[2])->value();
1560
1561   // Get the current global object from top.
1562   JSObject* global = qml_mode?isolate->context()->qml_global():isolate->context()->global();
1563
1564   // According to ECMA-262, section 12.2, page 62, the property must
1565   // not be deletable. Since it's a const, it must be READ_ONLY too.
1566   PropertyAttributes attributes =
1567       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1568
1569   // Lookup the property locally in the global object. If it isn't
1570   // there, we add the property and take special precautions to always
1571   // add it as a local property even in case of callbacks in the
1572   // prototype chain (this rules out using SetProperty).
1573   // We use SetLocalPropertyIgnoreAttributes instead
1574   LookupResult lookup(isolate);
1575   global->LocalLookup(*name, &lookup);
1576   if (!lookup.IsProperty()) {
1577     return global->SetLocalPropertyIgnoreAttributes(*name,
1578                                                     *value,
1579                                                     attributes);
1580   }
1581
1582   if (!lookup.IsReadOnly()) {
1583     // Restore global object from context (in case of GC) and continue
1584     // with setting the value.
1585     HandleScope handle_scope(isolate);
1586     Handle<JSObject> global(qml_mode?isolate->context()->qml_global():isolate->context()->global());
1587
1588     // BUG 1213575: Handle the case where we have to set a read-only
1589     // property through an interceptor and only do it if it's
1590     // uninitialized, e.g. the hole. Nirk...
1591     // Passing non-strict mode because the property is writable.
1592     RETURN_IF_EMPTY_HANDLE(
1593         isolate,
1594         JSReceiver::SetProperty(global, name, value, attributes,
1595                                 kNonStrictMode));
1596     return *value;
1597   }
1598
1599   // Set the value, but only if we're assigning the initial value to a
1600   // constant. For now, we determine this by checking if the
1601   // current value is the hole.
1602   // Strict mode handling not needed (const is disallowed in strict mode).
1603   PropertyType type = lookup.type();
1604   if (type == FIELD) {
1605     FixedArray* properties = global->properties();
1606     int index = lookup.GetFieldIndex();
1607     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
1608       properties->set(index, *value);
1609     }
1610   } else if (type == NORMAL) {
1611     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
1612         !lookup.IsReadOnly()) {
1613       global->SetNormalizedProperty(&lookup, *value);
1614     }
1615   } else {
1616     // Ignore re-initialization of constants that have already been
1617     // assigned a function value.
1618     ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
1619   }
1620
1621   // Use the set value as the result of the operation.
1622   return *value;
1623 }
1624
1625
1626 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
1627   HandleScope scope(isolate);
1628   ASSERT(args.length() == 3);
1629
1630   Handle<Object> value(args[0], isolate);
1631   ASSERT(!value->IsTheHole());
1632
1633   // Initializations are always done in a function or global context.
1634   RUNTIME_ASSERT(args[1]->IsContext());
1635   Handle<Context> context(Context::cast(args[1])->declaration_context());
1636
1637   Handle<String> name(String::cast(args[2]));
1638
1639   int index;
1640   PropertyAttributes attributes;
1641   ContextLookupFlags flags = FOLLOW_CHAINS;
1642   BindingFlags binding_flags;
1643   Handle<Object> holder =
1644       context->Lookup(name, flags, &index, &attributes, &binding_flags);
1645
1646   if (index >= 0) {
1647     ASSERT(holder->IsContext());
1648     // Property was found in a context.  Perform the assignment if we
1649     // found some non-constant or an uninitialized constant.
1650     Handle<Context> context = Handle<Context>::cast(holder);
1651     if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
1652       context->set(index, *value);
1653     }
1654     return *value;
1655   }
1656
1657   // The property could not be found, we introduce it as a property of the
1658   // global object.
1659   if (attributes == ABSENT) {
1660     Handle<JSObject> global = Handle<JSObject>(
1661         isolate->context()->global());
1662     // Strict mode not needed (const disallowed in strict mode).
1663     RETURN_IF_EMPTY_HANDLE(
1664         isolate,
1665         JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
1666     return *value;
1667   }
1668
1669   // The property was present in some function's context extension object,
1670   // as a property on the subject of a with, or as a property of the global
1671   // object.
1672   //
1673   // In most situations, eval-introduced consts should still be present in
1674   // the context extension object.  However, because declaration and
1675   // initialization are separate, the property might have been deleted
1676   // before we reach the initialization point.
1677   //
1678   // Example:
1679   //
1680   //    function f() { eval("delete x; const x;"); }
1681   //
1682   // In that case, the initialization behaves like a normal assignment.
1683   Handle<JSObject> object = Handle<JSObject>::cast(holder);
1684
1685   if (*object == context->extension()) {
1686     // This is the property that was introduced by the const declaration.
1687     // Set it if it hasn't been set before.  NOTE: We cannot use
1688     // GetProperty() to get the current value as it 'unholes' the value.
1689     LookupResult lookup(isolate);
1690     object->LocalLookupRealNamedProperty(*name, &lookup);
1691     ASSERT(lookup.IsFound());  // the property was declared
1692     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
1693
1694     PropertyType type = lookup.type();
1695     if (type == FIELD) {
1696       FixedArray* properties = object->properties();
1697       int index = lookup.GetFieldIndex();
1698       if (properties->get(index)->IsTheHole()) {
1699         properties->set(index, *value);
1700       }
1701     } else if (type == NORMAL) {
1702       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
1703         object->SetNormalizedProperty(&lookup, *value);
1704       }
1705     } else {
1706       // We should not reach here. Any real, named property should be
1707       // either a field or a dictionary slot.
1708       UNREACHABLE();
1709     }
1710   } else {
1711     // The property was found on some other object.  Set it if it is not a
1712     // read-only property.
1713     if ((attributes & READ_ONLY) == 0) {
1714       // Strict mode not needed (const disallowed in strict mode).
1715       RETURN_IF_EMPTY_HANDLE(
1716           isolate,
1717           JSReceiver::SetProperty(object, name, value, attributes,
1718                                   kNonStrictMode));
1719     }
1720   }
1721
1722   return *value;
1723 }
1724
1725
1726 RUNTIME_FUNCTION(MaybeObject*,
1727                  Runtime_OptimizeObjectForAddingMultipleProperties) {
1728   HandleScope scope(isolate);
1729   ASSERT(args.length() == 2);
1730   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1731   CONVERT_SMI_ARG_CHECKED(properties, 1);
1732   if (object->HasFastProperties()) {
1733     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
1734   }
1735   return *object;
1736 }
1737
1738
1739 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
1740   HandleScope scope(isolate);
1741   ASSERT(args.length() == 4);
1742   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
1743   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
1744   // Due to the way the JS calls are constructed this must be less than the
1745   // length of a string, i.e. it is always a Smi.  We check anyway for security.
1746   CONVERT_SMI_ARG_CHECKED(index, 2);
1747   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
1748   RUNTIME_ASSERT(last_match_info->HasFastElements());
1749   RUNTIME_ASSERT(index >= 0);
1750   RUNTIME_ASSERT(index <= subject->length());
1751   isolate->counters()->regexp_entry_runtime()->Increment();
1752   Handle<Object> result = RegExpImpl::Exec(regexp,
1753                                            subject,
1754                                            index,
1755                                            last_match_info);
1756   if (result.is_null()) return Failure::Exception();
1757   return *result;
1758 }
1759
1760
1761 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
1762   ASSERT(args.length() == 3);
1763   CONVERT_SMI_ARG_CHECKED(elements_count, 0);
1764   if (elements_count < 0 ||
1765       elements_count > FixedArray::kMaxLength ||
1766       !Smi::IsValid(elements_count)) {
1767     return isolate->ThrowIllegalOperation();
1768   }
1769   Object* new_object;
1770   { MaybeObject* maybe_new_object =
1771         isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
1772     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1773   }
1774   FixedArray* elements = FixedArray::cast(new_object);
1775   { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
1776       JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
1777     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1778   }
1779   {
1780     AssertNoAllocation no_gc;
1781     HandleScope scope(isolate);
1782     reinterpret_cast<HeapObject*>(new_object)->
1783         set_map(isolate->global_context()->regexp_result_map());
1784   }
1785   JSArray* array = JSArray::cast(new_object);
1786   array->set_properties(isolate->heap()->empty_fixed_array());
1787   array->set_elements(elements);
1788   array->set_length(Smi::FromInt(elements_count));
1789   // Write in-object properties after the length of the array.
1790   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
1791   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
1792   return array;
1793 }
1794
1795
1796 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
1797   AssertNoAllocation no_alloc;
1798   ASSERT(args.length() == 5);
1799   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1800   CONVERT_ARG_CHECKED(String, source, 1);
1801   // If source is the empty string we set it to "(?:)" instead as
1802   // suggested by ECMA-262, 5th, section 15.10.4.1.
1803   if (source->length() == 0) source = isolate->heap()->query_colon_symbol();
1804
1805   Object* global = args[2];
1806   if (!global->IsTrue()) global = isolate->heap()->false_value();
1807
1808   Object* ignoreCase = args[3];
1809   if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
1810
1811   Object* multiline = args[4];
1812   if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
1813
1814   Map* map = regexp->map();
1815   Object* constructor = map->constructor();
1816   if (constructor->IsJSFunction() &&
1817       JSFunction::cast(constructor)->initial_map() == map) {
1818     // If we still have the original map, set in-object properties directly.
1819     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1820     // Both true and false are immovable immortal objects so no need for write
1821     // barrier.
1822     regexp->InObjectPropertyAtPut(
1823         JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
1824     regexp->InObjectPropertyAtPut(
1825         JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
1826     regexp->InObjectPropertyAtPut(
1827         JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
1828     regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1829                                   Smi::FromInt(0),
1830                                   SKIP_WRITE_BARRIER);  // It's a Smi.
1831     return regexp;
1832   }
1833
1834   // Map has changed, so use generic, but slower, method.
1835   PropertyAttributes final =
1836       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
1837   PropertyAttributes writable =
1838       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1839   Heap* heap = isolate->heap();
1840   MaybeObject* result;
1841   result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
1842                                                     source,
1843                                                     final);
1844   ASSERT(!result->IsFailure());
1845   result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
1846                                                     global,
1847                                                     final);
1848   ASSERT(!result->IsFailure());
1849   result =
1850       regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
1851                                                ignoreCase,
1852                                                final);
1853   ASSERT(!result->IsFailure());
1854   result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
1855                                                     multiline,
1856                                                     final);
1857   ASSERT(!result->IsFailure());
1858   result =
1859       regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
1860                                                Smi::FromInt(0),
1861                                                writable);
1862   ASSERT(!result->IsFailure());
1863   USE(result);
1864   return regexp;
1865 }
1866
1867
1868 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
1869   HandleScope scope(isolate);
1870   ASSERT(args.length() == 1);
1871   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
1872   // This is necessary to enable fast checks for absence of elements
1873   // on Array.prototype and below.
1874   prototype->set_elements(isolate->heap()->empty_fixed_array());
1875   return Smi::FromInt(0);
1876 }
1877
1878
1879 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
1880                                          Handle<JSObject> holder,
1881                                          const char* name,
1882                                          Builtins::Name builtin_name) {
1883   Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
1884   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
1885   Handle<JSFunction> optimized =
1886       isolate->factory()->NewFunction(key,
1887                                       JS_OBJECT_TYPE,
1888                                       JSObject::kHeaderSize,
1889                                       code,
1890                                       false);
1891   optimized->shared()->DontAdaptArguments();
1892   JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
1893   return optimized;
1894 }
1895
1896
1897 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
1898   HandleScope scope(isolate);
1899   ASSERT(args.length() == 1);
1900   CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
1901
1902   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
1903   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
1904   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1905   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1906   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1907   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1908   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1909
1910   return *holder;
1911 }
1912
1913
1914 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
1915   ASSERT(args.length() == 1);
1916   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
1917
1918   if (!callable->IsJSFunction()) {
1919     HandleScope scope(isolate);
1920     bool threw = false;
1921     Handle<Object> delegate =
1922         Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
1923     if (threw) return Failure::Exception();
1924     callable = JSFunction::cast(*delegate);
1925   }
1926   JSFunction* function = JSFunction::cast(callable);
1927
1928   SharedFunctionInfo* shared = function->shared();
1929   if (shared->native() || !shared->is_classic_mode()) {
1930     return isolate->heap()->undefined_value();
1931   }
1932   // Returns undefined for strict or native functions, or
1933   // the associated global receiver for "normal" functions.
1934
1935   Context* global_context =
1936       function->context()->global()->global_context();
1937   return global_context->global()->global_receiver();
1938 }
1939
1940
1941 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1942   HandleScope scope(isolate);
1943   ASSERT(args.length() == 4);
1944   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
1945   int index = args.smi_at(1);
1946   Handle<String> pattern = args.at<String>(2);
1947   Handle<String> flags = args.at<String>(3);
1948
1949   // Get the RegExp function from the context in the literals array.
1950   // This is the RegExp function from the context in which the
1951   // function was created.  We do not use the RegExp function from the
1952   // current global context because this might be the RegExp function
1953   // from another context which we should not have access to.
1954   Handle<JSFunction> constructor =
1955       Handle<JSFunction>(
1956           JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
1957   // Compute the regular expression literal.
1958   bool has_pending_exception;
1959   Handle<Object> regexp =
1960       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
1961                                       &has_pending_exception);
1962   if (has_pending_exception) {
1963     ASSERT(isolate->has_pending_exception());
1964     return Failure::Exception();
1965   }
1966   literals->set(index, *regexp);
1967   return *regexp;
1968 }
1969
1970
1971 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
1972   NoHandleAllocation ha;
1973   ASSERT(args.length() == 1);
1974
1975   CONVERT_ARG_CHECKED(JSFunction, f, 0);
1976   return f->shared()->name();
1977 }
1978
1979
1980 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
1981   NoHandleAllocation ha;
1982   ASSERT(args.length() == 2);
1983
1984   CONVERT_ARG_CHECKED(JSFunction, f, 0);
1985   CONVERT_ARG_CHECKED(String, name, 1);
1986   f->shared()->set_name(name);
1987   return isolate->heap()->undefined_value();
1988 }
1989
1990
1991 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
1992   NoHandleAllocation ha;
1993   ASSERT(args.length() == 1);
1994   CONVERT_ARG_CHECKED(JSFunction, f, 0);
1995   return isolate->heap()->ToBoolean(
1996       f->shared()->name_should_print_as_anonymous());
1997 }
1998
1999
2000 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2001   NoHandleAllocation ha;
2002   ASSERT(args.length() == 1);
2003   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2004   f->shared()->set_name_should_print_as_anonymous(true);
2005   return isolate->heap()->undefined_value();
2006 }
2007
2008
2009 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2010   NoHandleAllocation ha;
2011   ASSERT(args.length() == 1);
2012
2013   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2014   Object* obj = f->RemovePrototype();
2015   if (obj->IsFailure()) return obj;
2016
2017   return isolate->heap()->undefined_value();
2018 }
2019
2020
2021 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2022   HandleScope scope(isolate);
2023   ASSERT(args.length() == 1);
2024
2025   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2026   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2027   if (!script->IsScript()) return isolate->heap()->undefined_value();
2028
2029   return *GetScriptWrapper(Handle<Script>::cast(script));
2030 }
2031
2032
2033 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2034   HandleScope scope(isolate);
2035   ASSERT(args.length() == 1);
2036
2037   CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2038   Handle<SharedFunctionInfo> shared(f->shared());
2039   return *shared->GetSourceCode();
2040 }
2041
2042
2043 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2044   NoHandleAllocation ha;
2045   ASSERT(args.length() == 1);
2046
2047   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2048   int pos = fun->shared()->start_position();
2049   return Smi::FromInt(pos);
2050 }
2051
2052
2053 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2054   ASSERT(args.length() == 2);
2055
2056   CONVERT_ARG_CHECKED(Code, code, 0);
2057   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2058
2059   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2060
2061   Address pc = code->address() + offset;
2062   return Smi::FromInt(code->SourcePosition(pc));
2063 }
2064
2065
2066 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2067   NoHandleAllocation ha;
2068   ASSERT(args.length() == 2);
2069
2070   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2071   CONVERT_ARG_CHECKED(String, name, 1);
2072   fun->SetInstanceClassName(name);
2073   return isolate->heap()->undefined_value();
2074 }
2075
2076
2077 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2078   NoHandleAllocation ha;
2079   ASSERT(args.length() == 2);
2080
2081   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2082   CONVERT_SMI_ARG_CHECKED(length, 1);
2083   fun->shared()->set_length(length);
2084   return isolate->heap()->undefined_value();
2085 }
2086
2087
2088 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2089   NoHandleAllocation ha;
2090   ASSERT(args.length() == 2);
2091
2092   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2093   ASSERT(fun->should_have_prototype());
2094   Object* obj;
2095   { MaybeObject* maybe_obj =
2096         Accessors::FunctionSetPrototype(fun, args[1], NULL);
2097     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2098   }
2099   return args[0];  // return TOS
2100 }
2101
2102
2103 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2104   NoHandleAllocation ha;
2105   RUNTIME_ASSERT(args.length() == 1);
2106   CONVERT_ARG_CHECKED(JSFunction, function, 0);
2107
2108   MaybeObject* maybe_name =
2109       isolate->heap()->AllocateStringFromAscii(CStrVector("prototype"));
2110   String* name;
2111   if (!maybe_name->To(&name)) return maybe_name;
2112
2113   if (function->HasFastProperties()) {
2114     // Construct a new field descriptor with updated attributes.
2115     DescriptorArray* instance_desc = function->map()->instance_descriptors();
2116     int index = instance_desc->Search(name);
2117     ASSERT(index != DescriptorArray::kNotFound);
2118     PropertyDetails details = instance_desc->GetDetails(index);
2119     CallbacksDescriptor new_desc(name,
2120         instance_desc->GetValue(index),
2121         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2122         details.index());
2123     // Construct a new field descriptors array containing the new descriptor.
2124     Object* descriptors_unchecked;
2125     { MaybeObject* maybe_descriptors_unchecked =
2126         instance_desc->CopyInsert(&new_desc, REMOVE_TRANSITIONS);
2127       if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
2128         return maybe_descriptors_unchecked;
2129       }
2130     }
2131     DescriptorArray* new_descriptors =
2132         DescriptorArray::cast(descriptors_unchecked);
2133     // Create a new map featuring the new field descriptors array.
2134     Object* map_unchecked;
2135     { MaybeObject* maybe_map_unchecked = function->map()->CopyDropDescriptors();
2136       if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
2137         return maybe_map_unchecked;
2138       }
2139     }
2140     Map* new_map = Map::cast(map_unchecked);
2141     new_map->set_instance_descriptors(new_descriptors);
2142     function->set_map(new_map);
2143   } else {  // Dictionary properties.
2144     // Directly manipulate the property details.
2145     int entry = function->property_dictionary()->FindEntry(name);
2146     ASSERT(entry != StringDictionary::kNotFound);
2147     PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2148     PropertyDetails new_details(
2149         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2150         details.type(),
2151         details.index());
2152     function->property_dictionary()->DetailsAtPut(entry, new_details);
2153   }
2154   return function;
2155 }
2156
2157
2158 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2159   NoHandleAllocation ha;
2160   ASSERT(args.length() == 1);
2161
2162   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2163   return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2164 }
2165
2166
2167 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2168   NoHandleAllocation ha;
2169   ASSERT(args.length() == 1);
2170
2171   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2172   return isolate->heap()->ToBoolean(f->IsBuiltin());
2173 }
2174
2175
2176 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2177   HandleScope scope(isolate);
2178   ASSERT(args.length() == 2);
2179
2180   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2181   Handle<Object> code = args.at<Object>(1);
2182
2183   Handle<Context> context(target->context());
2184
2185   if (!code->IsNull()) {
2186     RUNTIME_ASSERT(code->IsJSFunction());
2187     Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
2188     Handle<SharedFunctionInfo> shared(fun->shared());
2189
2190     if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
2191       return Failure::Exception();
2192     }
2193     // Since we don't store the source for this we should never
2194     // optimize this.
2195     shared->code()->set_optimizable(false);
2196     // Set the code, scope info, formal parameter count,
2197     // and the length of the target function.
2198     target->shared()->set_code(shared->code());
2199     target->ReplaceCode(shared->code());
2200     target->shared()->set_scope_info(shared->scope_info());
2201     target->shared()->set_length(shared->length());
2202     target->shared()->set_formal_parameter_count(
2203         shared->formal_parameter_count());
2204     // Set the source code of the target function to undefined.
2205     // SetCode is only used for built-in constructors like String,
2206     // Array, and Object, and some web code
2207     // doesn't like seeing source code for constructors.
2208     target->shared()->set_script(isolate->heap()->undefined_value());
2209     target->shared()->code()->set_optimizable(false);
2210     // Clear the optimization hints related to the compiled code as these are no
2211     // longer valid when the code is overwritten.
2212     target->shared()->ClearThisPropertyAssignmentsInfo();
2213     context = Handle<Context>(fun->context());
2214
2215     // Make sure we get a fresh copy of the literal vector to avoid
2216     // cross context contamination.
2217     int number_of_literals = fun->NumberOfLiterals();
2218     Handle<FixedArray> literals =
2219         isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2220     if (number_of_literals > 0) {
2221       // Insert the object, regexp and array functions in the literals
2222       // array prefix.  These are the functions that will be used when
2223       // creating object, regexp and array literals.
2224       literals->set(JSFunction::kLiteralGlobalContextIndex,
2225                     context->global_context());
2226     }
2227     target->set_literals(*literals);
2228     target->set_next_function_link(isolate->heap()->undefined_value());
2229
2230     if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) {
2231       isolate->logger()->LogExistingFunction(
2232           shared, Handle<Code>(shared->code()));
2233     }
2234   }
2235
2236   target->set_context(*context);
2237   return *target;
2238 }
2239
2240
2241 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2242   HandleScope scope(isolate);
2243   ASSERT(args.length() == 2);
2244   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2245   CONVERT_SMI_ARG_CHECKED(num, 1);
2246   RUNTIME_ASSERT(num >= 0);
2247   SetExpectedNofProperties(function, num);
2248   return isolate->heap()->undefined_value();
2249 }
2250
2251
2252 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
2253                                                  Object* char_code) {
2254   uint32_t code;
2255   if (char_code->ToArrayIndex(&code)) {
2256     if (code <= 0xffff) {
2257       return isolate->heap()->LookupSingleCharacterStringFromCode(code);
2258     }
2259   }
2260   return isolate->heap()->empty_string();
2261 }
2262
2263
2264 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
2265   NoHandleAllocation ha;
2266   ASSERT(args.length() == 2);
2267
2268   CONVERT_ARG_CHECKED(String, subject, 0);
2269   Object* index = args[1];
2270   RUNTIME_ASSERT(index->IsNumber());
2271
2272   uint32_t i = 0;
2273   if (index->IsSmi()) {
2274     int value = Smi::cast(index)->value();
2275     if (value < 0) return isolate->heap()->nan_value();
2276     i = value;
2277   } else {
2278     ASSERT(index->IsHeapNumber());
2279     double value = HeapNumber::cast(index)->value();
2280     i = static_cast<uint32_t>(DoubleToInteger(value));
2281   }
2282
2283   // Flatten the string.  If someone wants to get a char at an index
2284   // in a cons string, it is likely that more indices will be
2285   // accessed.
2286   Object* flat;
2287   { MaybeObject* maybe_flat = subject->TryFlatten();
2288     if (!maybe_flat->ToObject(&flat)) return maybe_flat;
2289   }
2290   subject = String::cast(flat);
2291
2292   if (i >= static_cast<uint32_t>(subject->length())) {
2293     return isolate->heap()->nan_value();
2294   }
2295
2296   return Smi::FromInt(subject->Get(i));
2297 }
2298
2299
2300 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
2301   NoHandleAllocation ha;
2302   ASSERT(args.length() == 1);
2303   return CharFromCode(isolate, args[0]);
2304 }
2305
2306
2307 class FixedArrayBuilder {
2308  public:
2309   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
2310       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
2311         length_(0),
2312         has_non_smi_elements_(false) {
2313     // Require a non-zero initial size. Ensures that doubling the size to
2314     // extend the array will work.
2315     ASSERT(initial_capacity > 0);
2316   }
2317
2318   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
2319       : array_(backing_store),
2320         length_(0),
2321         has_non_smi_elements_(false) {
2322     // Require a non-zero initial size. Ensures that doubling the size to
2323     // extend the array will work.
2324     ASSERT(backing_store->length() > 0);
2325   }
2326
2327   bool HasCapacity(int elements) {
2328     int length = array_->length();
2329     int required_length = length_ + elements;
2330     return (length >= required_length);
2331   }
2332
2333   void EnsureCapacity(int elements) {
2334     int length = array_->length();
2335     int required_length = length_ + elements;
2336     if (length < required_length) {
2337       int new_length = length;
2338       do {
2339         new_length *= 2;
2340       } while (new_length < required_length);
2341       Handle<FixedArray> extended_array =
2342           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
2343       array_->CopyTo(0, *extended_array, 0, length_);
2344       array_ = extended_array;
2345     }
2346   }
2347
2348   void Add(Object* value) {
2349     ASSERT(!value->IsSmi());
2350     ASSERT(length_ < capacity());
2351     array_->set(length_, value);
2352     length_++;
2353     has_non_smi_elements_ = true;
2354   }
2355
2356   void Add(Smi* value) {
2357     ASSERT(value->IsSmi());
2358     ASSERT(length_ < capacity());
2359     array_->set(length_, value);
2360     length_++;
2361   }
2362
2363   Handle<FixedArray> array() {
2364     return array_;
2365   }
2366
2367   int length() {
2368     return length_;
2369   }
2370
2371   int capacity() {
2372     return array_->length();
2373   }
2374
2375   Handle<JSArray> ToJSArray() {
2376     Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_);
2377     result_array->set_length(Smi::FromInt(length_));
2378     return result_array;
2379   }
2380
2381   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
2382     FACTORY->SetContent(target_array, array_);
2383     target_array->set_length(Smi::FromInt(length_));
2384     return target_array;
2385   }
2386
2387  private:
2388   Handle<FixedArray> array_;
2389   int length_;
2390   bool has_non_smi_elements_;
2391 };
2392
2393
2394 // Forward declarations.
2395 const int kStringBuilderConcatHelperLengthBits = 11;
2396 const int kStringBuilderConcatHelperPositionBits = 19;
2397
2398 template <typename schar>
2399 static inline void StringBuilderConcatHelper(String*,
2400                                              schar*,
2401                                              FixedArray*,
2402                                              int);
2403
2404 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
2405     StringBuilderSubstringLength;
2406 typedef BitField<int,
2407                  kStringBuilderConcatHelperLengthBits,
2408                  kStringBuilderConcatHelperPositionBits>
2409     StringBuilderSubstringPosition;
2410
2411
2412 class ReplacementStringBuilder {
2413  public:
2414   ReplacementStringBuilder(Heap* heap,
2415                            Handle<String> subject,
2416                            int estimated_part_count)
2417       : heap_(heap),
2418         array_builder_(heap->isolate(), estimated_part_count),
2419         subject_(subject),
2420         character_count_(0),
2421         is_ascii_(subject->IsAsciiRepresentation()) {
2422     // Require a non-zero initial size. Ensures that doubling the size to
2423     // extend the array will work.
2424     ASSERT(estimated_part_count > 0);
2425   }
2426
2427   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
2428                                      int from,
2429                                      int to) {
2430     ASSERT(from >= 0);
2431     int length = to - from;
2432     ASSERT(length > 0);
2433     if (StringBuilderSubstringLength::is_valid(length) &&
2434         StringBuilderSubstringPosition::is_valid(from)) {
2435       int encoded_slice = StringBuilderSubstringLength::encode(length) |
2436           StringBuilderSubstringPosition::encode(from);
2437       builder->Add(Smi::FromInt(encoded_slice));
2438     } else {
2439       // Otherwise encode as two smis.
2440       builder->Add(Smi::FromInt(-length));
2441       builder->Add(Smi::FromInt(from));
2442     }
2443   }
2444
2445
2446   void EnsureCapacity(int elements) {
2447     array_builder_.EnsureCapacity(elements);
2448   }
2449
2450
2451   void AddSubjectSlice(int from, int to) {
2452     AddSubjectSlice(&array_builder_, from, to);
2453     IncrementCharacterCount(to - from);
2454   }
2455
2456
2457   void AddString(Handle<String> string) {
2458     int length = string->length();
2459     ASSERT(length > 0);
2460     AddElement(*string);
2461     if (!string->IsAsciiRepresentation()) {
2462       is_ascii_ = false;
2463     }
2464     IncrementCharacterCount(length);
2465   }
2466
2467
2468   Handle<String> ToString() {
2469     if (array_builder_.length() == 0) {
2470       return heap_->isolate()->factory()->empty_string();
2471     }
2472
2473     Handle<String> joined_string;
2474     if (is_ascii_) {
2475       Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_);
2476       AssertNoAllocation no_alloc;
2477       char* char_buffer = seq->GetChars();
2478       StringBuilderConcatHelper(*subject_,
2479                                 char_buffer,
2480                                 *array_builder_.array(),
2481                                 array_builder_.length());
2482       joined_string = Handle<String>::cast(seq);
2483     } else {
2484       // Non-ASCII.
2485       Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
2486       AssertNoAllocation no_alloc;
2487       uc16* char_buffer = seq->GetChars();
2488       StringBuilderConcatHelper(*subject_,
2489                                 char_buffer,
2490                                 *array_builder_.array(),
2491                                 array_builder_.length());
2492       joined_string = Handle<String>::cast(seq);
2493     }
2494     return joined_string;
2495   }
2496
2497
2498   void IncrementCharacterCount(int by) {
2499     if (character_count_ > String::kMaxLength - by) {
2500       V8::FatalProcessOutOfMemory("String.replace result too large.");
2501     }
2502     character_count_ += by;
2503   }
2504
2505   Handle<JSArray> GetParts() {
2506     return array_builder_.ToJSArray();
2507   }
2508
2509  private:
2510   Handle<SeqAsciiString> NewRawAsciiString(int length) {
2511     return heap_->isolate()->factory()->NewRawAsciiString(length);
2512   }
2513
2514
2515   Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
2516     return heap_->isolate()->factory()->NewRawTwoByteString(length);
2517   }
2518
2519
2520   void AddElement(Object* element) {
2521     ASSERT(element->IsSmi() || element->IsString());
2522     ASSERT(array_builder_.capacity() > array_builder_.length());
2523     array_builder_.Add(element);
2524   }
2525
2526   Heap* heap_;
2527   FixedArrayBuilder array_builder_;
2528   Handle<String> subject_;
2529   int character_count_;
2530   bool is_ascii_;
2531 };
2532
2533
2534 class CompiledReplacement {
2535  public:
2536   CompiledReplacement()
2537       : parts_(1), replacement_substrings_(0), simple_hint_(false) {}
2538
2539   void Compile(Handle<String> replacement,
2540                int capture_count,
2541                int subject_length);
2542
2543   void Apply(ReplacementStringBuilder* builder,
2544              int match_from,
2545              int match_to,
2546              Handle<JSArray> last_match_info);
2547
2548   // Number of distinct parts of the replacement pattern.
2549   int parts() {
2550     return parts_.length();
2551   }
2552
2553   bool simple_hint() {
2554     return simple_hint_;
2555   }
2556
2557  private:
2558   enum PartType {
2559     SUBJECT_PREFIX = 1,
2560     SUBJECT_SUFFIX,
2561     SUBJECT_CAPTURE,
2562     REPLACEMENT_SUBSTRING,
2563     REPLACEMENT_STRING,
2564
2565     NUMBER_OF_PART_TYPES
2566   };
2567
2568   struct ReplacementPart {
2569     static inline ReplacementPart SubjectMatch() {
2570       return ReplacementPart(SUBJECT_CAPTURE, 0);
2571     }
2572     static inline ReplacementPart SubjectCapture(int capture_index) {
2573       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
2574     }
2575     static inline ReplacementPart SubjectPrefix() {
2576       return ReplacementPart(SUBJECT_PREFIX, 0);
2577     }
2578     static inline ReplacementPart SubjectSuffix(int subject_length) {
2579       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
2580     }
2581     static inline ReplacementPart ReplacementString() {
2582       return ReplacementPart(REPLACEMENT_STRING, 0);
2583     }
2584     static inline ReplacementPart ReplacementSubString(int from, int to) {
2585       ASSERT(from >= 0);
2586       ASSERT(to > from);
2587       return ReplacementPart(-from, to);
2588     }
2589
2590     // If tag <= 0 then it is the negation of a start index of a substring of
2591     // the replacement pattern, otherwise it's a value from PartType.
2592     ReplacementPart(int tag, int data)
2593         : tag(tag), data(data) {
2594       // Must be non-positive or a PartType value.
2595       ASSERT(tag < NUMBER_OF_PART_TYPES);
2596     }
2597     // Either a value of PartType or a non-positive number that is
2598     // the negation of an index into the replacement string.
2599     int tag;
2600     // The data value's interpretation depends on the value of tag:
2601     // tag == SUBJECT_PREFIX ||
2602     // tag == SUBJECT_SUFFIX:  data is unused.
2603     // tag == SUBJECT_CAPTURE: data is the number of the capture.
2604     // tag == REPLACEMENT_SUBSTRING ||
2605     // tag == REPLACEMENT_STRING:    data is index into array of substrings
2606     //                               of the replacement string.
2607     // tag <= 0: Temporary representation of the substring of the replacement
2608     //           string ranging over -tag .. data.
2609     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2610     //           substring objects.
2611     int data;
2612   };
2613
2614   template<typename Char>
2615   static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2616                                       Vector<Char> characters,
2617                                       int capture_count,
2618                                       int subject_length) {
2619     int length = characters.length();
2620     int last = 0;
2621     for (int i = 0; i < length; i++) {
2622       Char c = characters[i];
2623       if (c == '$') {
2624         int next_index = i + 1;
2625         if (next_index == length) {  // No next character!
2626           break;
2627         }
2628         Char c2 = characters[next_index];
2629         switch (c2) {
2630         case '$':
2631           if (i > last) {
2632             // There is a substring before. Include the first "$".
2633             parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
2634             last = next_index + 1;  // Continue after the second "$".
2635           } else {
2636             // Let the next substring start with the second "$".
2637             last = next_index;
2638           }
2639           i = next_index;
2640           break;
2641         case '`':
2642           if (i > last) {
2643             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2644           }
2645           parts->Add(ReplacementPart::SubjectPrefix());
2646           i = next_index;
2647           last = i + 1;
2648           break;
2649         case '\'':
2650           if (i > last) {
2651             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2652           }
2653           parts->Add(ReplacementPart::SubjectSuffix(subject_length));
2654           i = next_index;
2655           last = i + 1;
2656           break;
2657         case '&':
2658           if (i > last) {
2659             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2660           }
2661           parts->Add(ReplacementPart::SubjectMatch());
2662           i = next_index;
2663           last = i + 1;
2664           break;
2665         case '0':
2666         case '1':
2667         case '2':
2668         case '3':
2669         case '4':
2670         case '5':
2671         case '6':
2672         case '7':
2673         case '8':
2674         case '9': {
2675           int capture_ref = c2 - '0';
2676           if (capture_ref > capture_count) {
2677             i = next_index;
2678             continue;
2679           }
2680           int second_digit_index = next_index + 1;
2681           if (second_digit_index < length) {
2682             // Peek ahead to see if we have two digits.
2683             Char c3 = characters[second_digit_index];
2684             if ('0' <= c3 && c3 <= '9') {  // Double digits.
2685               int double_digit_ref = capture_ref * 10 + c3 - '0';
2686               if (double_digit_ref <= capture_count) {
2687                 next_index = second_digit_index;
2688                 capture_ref = double_digit_ref;
2689               }
2690             }
2691           }
2692           if (capture_ref > 0) {
2693             if (i > last) {
2694               parts->Add(ReplacementPart::ReplacementSubString(last, i));
2695             }
2696             ASSERT(capture_ref <= capture_count);
2697             parts->Add(ReplacementPart::SubjectCapture(capture_ref));
2698             last = next_index + 1;
2699           }
2700           i = next_index;
2701           break;
2702         }
2703         default:
2704           i = next_index;
2705           break;
2706         }
2707       }
2708     }
2709     if (length > last) {
2710       if (last == 0) {
2711         parts->Add(ReplacementPart::ReplacementString());
2712         return true;
2713       } else {
2714         parts->Add(ReplacementPart::ReplacementSubString(last, length));
2715       }
2716     }
2717     return false;
2718   }
2719
2720   ZoneList<ReplacementPart> parts_;
2721   ZoneList<Handle<String> > replacement_substrings_;
2722   bool simple_hint_;
2723 };
2724
2725
2726 void CompiledReplacement::Compile(Handle<String> replacement,
2727                                   int capture_count,
2728                                   int subject_length) {
2729   {
2730     AssertNoAllocation no_alloc;
2731     String::FlatContent content = replacement->GetFlatContent();
2732     ASSERT(content.IsFlat());
2733     if (content.IsAscii()) {
2734       simple_hint_ = ParseReplacementPattern(&parts_,
2735                                              content.ToAsciiVector(),
2736                                              capture_count,
2737                                              subject_length);
2738     } else {
2739       ASSERT(content.IsTwoByte());
2740       simple_hint_ = ParseReplacementPattern(&parts_,
2741                                              content.ToUC16Vector(),
2742                                              capture_count,
2743                                              subject_length);
2744     }
2745   }
2746   Isolate* isolate = replacement->GetIsolate();
2747   // Find substrings of replacement string and create them as String objects.
2748   int substring_index = 0;
2749   for (int i = 0, n = parts_.length(); i < n; i++) {
2750     int tag = parts_[i].tag;
2751     if (tag <= 0) {  // A replacement string slice.
2752       int from = -tag;
2753       int to = parts_[i].data;
2754       replacement_substrings_.Add(
2755           isolate->factory()->NewSubString(replacement, from, to));
2756       parts_[i].tag = REPLACEMENT_SUBSTRING;
2757       parts_[i].data = substring_index;
2758       substring_index++;
2759     } else if (tag == REPLACEMENT_STRING) {
2760       replacement_substrings_.Add(replacement);
2761       parts_[i].data = substring_index;
2762       substring_index++;
2763     }
2764   }
2765 }
2766
2767
2768 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
2769                                 int match_from,
2770                                 int match_to,
2771                                 Handle<JSArray> last_match_info) {
2772   for (int i = 0, n = parts_.length(); i < n; i++) {
2773     ReplacementPart part = parts_[i];
2774     switch (part.tag) {
2775       case SUBJECT_PREFIX:
2776         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2777         break;
2778       case SUBJECT_SUFFIX: {
2779         int subject_length = part.data;
2780         if (match_to < subject_length) {
2781           builder->AddSubjectSlice(match_to, subject_length);
2782         }
2783         break;
2784       }
2785       case SUBJECT_CAPTURE: {
2786         int capture = part.data;
2787         FixedArray* match_info = FixedArray::cast(last_match_info->elements());
2788         int from = RegExpImpl::GetCapture(match_info, capture * 2);
2789         int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
2790         if (from >= 0 && to > from) {
2791           builder->AddSubjectSlice(from, to);
2792         }
2793         break;
2794       }
2795       case REPLACEMENT_SUBSTRING:
2796       case REPLACEMENT_STRING:
2797         builder->AddString(replacement_substrings_[part.data]);
2798         break;
2799       default:
2800         UNREACHABLE();
2801     }
2802   }
2803 }
2804
2805
2806 void FindAsciiStringIndices(Vector<const char> subject,
2807                             char pattern,
2808                             ZoneList<int>* indices,
2809                             unsigned int limit) {
2810   ASSERT(limit > 0);
2811   // Collect indices of pattern in subject using memchr.
2812   // Stop after finding at most limit values.
2813   const char* subject_start = reinterpret_cast<const char*>(subject.start());
2814   const char* subject_end = subject_start + subject.length();
2815   const char* pos = subject_start;
2816   while (limit > 0) {
2817     pos = reinterpret_cast<const char*>(
2818         memchr(pos, pattern, subject_end - pos));
2819     if (pos == NULL) return;
2820     indices->Add(static_cast<int>(pos - subject_start));
2821     pos++;
2822     limit--;
2823   }
2824 }
2825
2826
2827 template <typename SubjectChar, typename PatternChar>
2828 void FindStringIndices(Isolate* isolate,
2829                        Vector<const SubjectChar> subject,
2830                        Vector<const PatternChar> pattern,
2831                        ZoneList<int>* indices,
2832                        unsigned int limit) {
2833   ASSERT(limit > 0);
2834   // Collect indices of pattern in subject.
2835   // Stop after finding at most limit values.
2836   int pattern_length = pattern.length();
2837   int index = 0;
2838   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2839   while (limit > 0) {
2840     index = search.Search(subject, index);
2841     if (index < 0) return;
2842     indices->Add(index);
2843     index += pattern_length;
2844     limit--;
2845   }
2846 }
2847
2848
2849 void FindStringIndicesDispatch(Isolate* isolate,
2850                                String* subject,
2851                                String* pattern,
2852                                ZoneList<int>* indices,
2853                                unsigned int limit) {
2854   {
2855     AssertNoAllocation no_gc;
2856     String::FlatContent subject_content = subject->GetFlatContent();
2857     String::FlatContent pattern_content = pattern->GetFlatContent();
2858     ASSERT(subject_content.IsFlat());
2859     ASSERT(pattern_content.IsFlat());
2860     if (subject_content.IsAscii()) {
2861       Vector<const char> subject_vector = subject_content.ToAsciiVector();
2862       if (pattern_content.IsAscii()) {
2863         Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
2864         if (pattern_vector.length() == 1) {
2865           FindAsciiStringIndices(subject_vector,
2866                                  pattern_vector[0],
2867                                  indices,
2868                                  limit);
2869         } else {
2870           FindStringIndices(isolate,
2871                             subject_vector,
2872                             pattern_vector,
2873                             indices,
2874                             limit);
2875         }
2876       } else {
2877         FindStringIndices(isolate,
2878                           subject_vector,
2879                           pattern_content.ToUC16Vector(),
2880                           indices,
2881                           limit);
2882       }
2883     } else {
2884       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
2885       if (pattern_content.IsAscii()) {
2886         FindStringIndices(isolate,
2887                           subject_vector,
2888                           pattern_content.ToAsciiVector(),
2889                           indices,
2890                           limit);
2891       } else {
2892         FindStringIndices(isolate,
2893                           subject_vector,
2894                           pattern_content.ToUC16Vector(),
2895                           indices,
2896                           limit);
2897       }
2898     }
2899   }
2900 }
2901
2902
2903 // Two smis before and after the match, for very long strings.
2904 const int kMaxBuilderEntriesPerRegExpMatch = 5;
2905
2906
2907 static void SetLastMatchInfoNoCaptures(Handle<String> subject,
2908                                        Handle<JSArray> last_match_info,
2909                                        int match_start,
2910                                        int match_end) {
2911   // Fill last_match_info with a single capture.
2912   last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
2913   AssertNoAllocation no_gc;
2914   FixedArray* elements = FixedArray::cast(last_match_info->elements());
2915   RegExpImpl::SetLastCaptureCount(elements, 2);
2916   RegExpImpl::SetLastInput(elements, *subject);
2917   RegExpImpl::SetLastSubject(elements, *subject);
2918   RegExpImpl::SetCapture(elements, 0, match_start);
2919   RegExpImpl::SetCapture(elements, 1, match_end);
2920 }
2921
2922
2923 template <typename SubjectChar, typename PatternChar>
2924 static bool SearchStringMultiple(Isolate* isolate,
2925                                  Vector<const SubjectChar> subject,
2926                                  Vector<const PatternChar> pattern,
2927                                  String* pattern_string,
2928                                  FixedArrayBuilder* builder,
2929                                  int* match_pos) {
2930   int pos = *match_pos;
2931   int subject_length = subject.length();
2932   int pattern_length = pattern.length();
2933   int max_search_start = subject_length - pattern_length;
2934   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2935   while (pos <= max_search_start) {
2936     if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
2937       *match_pos = pos;
2938       return false;
2939     }
2940     // Position of end of previous match.
2941     int match_end = pos + pattern_length;
2942     int new_pos = search.Search(subject, match_end);
2943     if (new_pos >= 0) {
2944       // A match.
2945       if (new_pos > match_end) {
2946         ReplacementStringBuilder::AddSubjectSlice(builder,
2947             match_end,
2948             new_pos);
2949       }
2950       pos = new_pos;
2951       builder->Add(pattern_string);
2952     } else {
2953       break;
2954     }
2955   }
2956
2957   if (pos < max_search_start) {
2958     ReplacementStringBuilder::AddSubjectSlice(builder,
2959                                               pos + pattern_length,
2960                                               subject_length);
2961   }
2962   *match_pos = pos;
2963   return true;
2964 }
2965
2966
2967
2968
2969 template<typename ResultSeqString>
2970 MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString(
2971     Isolate* isolate,
2972     Handle<String> subject,
2973     Handle<JSRegExp> pattern_regexp,
2974     Handle<String> replacement,
2975     Handle<JSArray> last_match_info) {
2976   ASSERT(subject->IsFlat());
2977   ASSERT(replacement->IsFlat());
2978
2979   ZoneScope zone_space(isolate, DELETE_ON_EXIT);
2980   ZoneList<int> indices(8);
2981   ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
2982   String* pattern =
2983       String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
2984   int subject_len = subject->length();
2985   int pattern_len = pattern->length();
2986   int replacement_len = replacement->length();
2987
2988   FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff);
2989
2990   int matches = indices.length();
2991   if (matches == 0) return *subject;
2992
2993   int result_len = (replacement_len - pattern_len) * matches + subject_len;
2994   int subject_pos = 0;
2995   int result_pos = 0;
2996
2997   Handle<ResultSeqString> result;
2998   if (ResultSeqString::kHasAsciiEncoding) {
2999     result = Handle<ResultSeqString>::cast(
3000         isolate->factory()->NewRawAsciiString(result_len));
3001   } else {
3002     result = Handle<ResultSeqString>::cast(
3003         isolate->factory()->NewRawTwoByteString(result_len));
3004   }
3005
3006   for (int i = 0; i < matches; i++) {
3007     // Copy non-matched subject content.
3008     if (subject_pos < indices.at(i)) {
3009       String::WriteToFlat(*subject,
3010                           result->GetChars() + result_pos,
3011                           subject_pos,
3012                           indices.at(i));
3013       result_pos += indices.at(i) - subject_pos;
3014     }
3015
3016     // Replace match.
3017     if (replacement_len > 0) {
3018       String::WriteToFlat(*replacement,
3019                           result->GetChars() + result_pos,
3020                           0,
3021                           replacement_len);
3022       result_pos += replacement_len;
3023     }
3024
3025     subject_pos = indices.at(i) + pattern_len;
3026   }
3027   // Add remaining subject content at the end.
3028   if (subject_pos < subject_len) {
3029     String::WriteToFlat(*subject,
3030                         result->GetChars() + result_pos,
3031                         subject_pos,
3032                         subject_len);
3033   }
3034
3035   SetLastMatchInfoNoCaptures(subject,
3036                              last_match_info,
3037                              indices.at(matches - 1),
3038                              indices.at(matches - 1) + pattern_len);
3039
3040   return *result;
3041 }
3042
3043
3044 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
3045     Isolate* isolate,
3046     String* subject,
3047     JSRegExp* regexp,
3048     String* replacement,
3049     JSArray* last_match_info) {
3050   ASSERT(subject->IsFlat());
3051   ASSERT(replacement->IsFlat());
3052
3053   HandleScope handles(isolate);
3054
3055   int length = subject->length();
3056   Handle<String> subject_handle(subject);
3057   Handle<JSRegExp> regexp_handle(regexp);
3058   Handle<String> replacement_handle(replacement);
3059   Handle<JSArray> last_match_info_handle(last_match_info);
3060   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
3061                                           subject_handle,
3062                                           0,
3063                                           last_match_info_handle);
3064   if (match.is_null()) {
3065     return Failure::Exception();
3066   }
3067   if (match->IsNull()) {
3068     return *subject_handle;
3069   }
3070
3071   int capture_count = regexp_handle->CaptureCount();
3072
3073   // CompiledReplacement uses zone allocation.
3074   ZoneScope zone(isolate, DELETE_ON_EXIT);
3075   CompiledReplacement compiled_replacement;
3076   compiled_replacement.Compile(replacement_handle,
3077                                capture_count,
3078                                length);
3079
3080   bool is_global = regexp_handle->GetFlags().is_global();
3081
3082   // Shortcut for simple non-regexp global replacements
3083   if (is_global &&
3084       regexp_handle->TypeTag() == JSRegExp::ATOM &&
3085       compiled_replacement.simple_hint()) {
3086     if (subject_handle->HasOnlyAsciiChars() &&
3087         replacement_handle->HasOnlyAsciiChars()) {
3088       return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3089           isolate,
3090           subject_handle,
3091           regexp_handle,
3092           replacement_handle,
3093           last_match_info_handle);
3094     } else {
3095       return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3096           isolate,
3097           subject_handle,
3098           regexp_handle,
3099           replacement_handle,
3100           last_match_info_handle);
3101     }
3102   }
3103
3104   // Guessing the number of parts that the final result string is built
3105   // from. Global regexps can match any number of times, so we guess
3106   // conservatively.
3107   int expected_parts =
3108       (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
3109   ReplacementStringBuilder builder(isolate->heap(),
3110                                    subject_handle,
3111                                    expected_parts);
3112
3113   // Index of end of last match.
3114   int prev = 0;
3115
3116   // Number of parts added by compiled replacement plus preceeding
3117   // string and possibly suffix after last match.  It is possible for
3118   // all components to use two elements when encoded as two smis.
3119   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3120   bool matched = true;
3121   do {
3122     ASSERT(last_match_info_handle->HasFastElements());
3123     // Increase the capacity of the builder before entering local handle-scope,
3124     // so its internal buffer can safely allocate a new handle if it grows.
3125     builder.EnsureCapacity(parts_added_per_loop);
3126
3127     HandleScope loop_scope(isolate);
3128     int start, end;
3129     {
3130       AssertNoAllocation match_info_array_is_not_in_a_handle;
3131       FixedArray* match_info_array =
3132           FixedArray::cast(last_match_info_handle->elements());
3133
3134       ASSERT_EQ(capture_count * 2 + 2,
3135                 RegExpImpl::GetLastCaptureCount(match_info_array));
3136       start = RegExpImpl::GetCapture(match_info_array, 0);
3137       end = RegExpImpl::GetCapture(match_info_array, 1);
3138     }
3139
3140     if (prev < start) {
3141       builder.AddSubjectSlice(prev, start);
3142     }
3143     compiled_replacement.Apply(&builder,
3144                                start,
3145                                end,
3146                                last_match_info_handle);
3147     prev = end;
3148
3149     // Only continue checking for global regexps.
3150     if (!is_global) break;
3151
3152     // Continue from where the match ended, unless it was an empty match.
3153     int next = end;
3154     if (start == end) {
3155       next = end + 1;
3156       if (next > length) break;
3157     }
3158
3159     match = RegExpImpl::Exec(regexp_handle,
3160                              subject_handle,
3161                              next,
3162                              last_match_info_handle);
3163     if (match.is_null()) {
3164       return Failure::Exception();
3165     }
3166     matched = !match->IsNull();
3167   } while (matched);
3168
3169   if (prev < length) {
3170     builder.AddSubjectSlice(prev, length);
3171   }
3172
3173   return *(builder.ToString());
3174 }
3175
3176
3177 template <typename ResultSeqString>
3178 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
3179     Isolate* isolate,
3180     String* subject,
3181     JSRegExp* regexp,
3182     JSArray* last_match_info) {
3183   ASSERT(subject->IsFlat());
3184
3185   HandleScope handles(isolate);
3186
3187   Handle<String> subject_handle(subject);
3188   Handle<JSRegExp> regexp_handle(regexp);
3189   Handle<JSArray> last_match_info_handle(last_match_info);
3190
3191   // Shortcut for simple non-regexp global replacements
3192   if (regexp_handle->GetFlags().is_global() &&
3193       regexp_handle->TypeTag() == JSRegExp::ATOM) {
3194     Handle<String> empty_string_handle(HEAP->empty_string());
3195     if (subject_handle->HasOnlyAsciiChars()) {
3196       return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3197           isolate,
3198           subject_handle,
3199           regexp_handle,
3200           empty_string_handle,
3201           last_match_info_handle);
3202     } else {
3203       return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3204           isolate,
3205           subject_handle,
3206           regexp_handle,
3207           empty_string_handle,
3208           last_match_info_handle);
3209     }
3210   }
3211
3212   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
3213                                           subject_handle,
3214                                           0,
3215                                           last_match_info_handle);
3216   if (match.is_null()) return Failure::Exception();
3217   if (match->IsNull()) return *subject_handle;
3218
3219   ASSERT(last_match_info_handle->HasFastElements());
3220
3221   int start, end;
3222   {
3223     AssertNoAllocation match_info_array_is_not_in_a_handle;
3224     FixedArray* match_info_array =
3225         FixedArray::cast(last_match_info_handle->elements());
3226
3227     start = RegExpImpl::GetCapture(match_info_array, 0);
3228     end = RegExpImpl::GetCapture(match_info_array, 1);
3229   }
3230
3231   bool global = regexp_handle->GetFlags().is_global();
3232
3233   if (start == end && !global) return *subject_handle;
3234
3235   int length = subject_handle->length();
3236   int new_length = length - (end - start);
3237   if (new_length == 0) {
3238     return isolate->heap()->empty_string();
3239   }
3240   Handle<ResultSeqString> answer;
3241   if (ResultSeqString::kHasAsciiEncoding) {
3242     answer = Handle<ResultSeqString>::cast(
3243         isolate->factory()->NewRawAsciiString(new_length));
3244   } else {
3245     answer = Handle<ResultSeqString>::cast(
3246         isolate->factory()->NewRawTwoByteString(new_length));
3247   }
3248
3249   // If the regexp isn't global, only match once.
3250   if (!global) {
3251     if (start > 0) {
3252       String::WriteToFlat(*subject_handle,
3253                           answer->GetChars(),
3254                           0,
3255                           start);
3256     }
3257     if (end < length) {
3258       String::WriteToFlat(*subject_handle,
3259                           answer->GetChars() + start,
3260                           end,
3261                           length);
3262     }
3263     return *answer;
3264   }
3265
3266   int prev = 0;  // Index of end of last match.
3267   int next = 0;  // Start of next search (prev unless last match was empty).
3268   int position = 0;
3269
3270   do {
3271     if (prev < start) {
3272       // Add substring subject[prev;start] to answer string.
3273       String::WriteToFlat(*subject_handle,
3274                           answer->GetChars() + position,
3275                           prev,
3276                           start);
3277       position += start - prev;
3278     }
3279     prev = end;
3280     next = end;
3281     // Continue from where the match ended, unless it was an empty match.
3282     if (start == end) {
3283       next++;
3284       if (next > length) break;
3285     }
3286     match = RegExpImpl::Exec(regexp_handle,
3287                              subject_handle,
3288                              next,
3289                              last_match_info_handle);
3290     if (match.is_null()) return Failure::Exception();
3291     if (match->IsNull()) break;
3292
3293     ASSERT(last_match_info_handle->HasFastElements());
3294     HandleScope loop_scope(isolate);
3295     {
3296       AssertNoAllocation match_info_array_is_not_in_a_handle;
3297       FixedArray* match_info_array =
3298           FixedArray::cast(last_match_info_handle->elements());
3299       start = RegExpImpl::GetCapture(match_info_array, 0);
3300       end = RegExpImpl::GetCapture(match_info_array, 1);
3301     }
3302   } while (true);
3303
3304   if (prev < length) {
3305     // Add substring subject[prev;length] to answer string.
3306     String::WriteToFlat(*subject_handle,
3307                         answer->GetChars() + position,
3308                         prev,
3309                         length);
3310     position += length - prev;
3311   }
3312
3313   if (position == 0) {
3314     return isolate->heap()->empty_string();
3315   }
3316
3317   // Shorten string and fill
3318   int string_size = ResultSeqString::SizeFor(position);
3319   int allocated_string_size = ResultSeqString::SizeFor(new_length);
3320   int delta = allocated_string_size - string_size;
3321
3322   answer->set_length(position);
3323   if (delta == 0) return *answer;
3324
3325   Address end_of_string = answer->address() + string_size;
3326   isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
3327   if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
3328     MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
3329   }
3330
3331   return *answer;
3332 }
3333
3334
3335 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
3336   ASSERT(args.length() == 4);
3337
3338   CONVERT_ARG_CHECKED(String, subject, 0);
3339   if (!subject->IsFlat()) {
3340     Object* flat_subject;
3341     { MaybeObject* maybe_flat_subject = subject->TryFlatten();
3342       if (!maybe_flat_subject->ToObject(&flat_subject)) {
3343         return maybe_flat_subject;
3344       }
3345     }
3346     subject = String::cast(flat_subject);
3347   }
3348
3349   CONVERT_ARG_CHECKED(String, replacement, 2);
3350   if (!replacement->IsFlat()) {
3351     Object* flat_replacement;
3352     { MaybeObject* maybe_flat_replacement = replacement->TryFlatten();
3353       if (!maybe_flat_replacement->ToObject(&flat_replacement)) {
3354         return maybe_flat_replacement;
3355       }
3356     }
3357     replacement = String::cast(flat_replacement);
3358   }
3359
3360   CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
3361   CONVERT_ARG_CHECKED(JSArray, last_match_info, 3);
3362
3363   ASSERT(last_match_info->HasFastElements());
3364
3365   if (replacement->length() == 0) {
3366     if (subject->HasOnlyAsciiChars()) {
3367       return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
3368           isolate, subject, regexp, last_match_info);
3369     } else {
3370       return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
3371           isolate, subject, regexp, last_match_info);
3372     }
3373   }
3374
3375   return StringReplaceRegExpWithString(isolate,
3376                                        subject,
3377                                        regexp,
3378                                        replacement,
3379                                        last_match_info);
3380 }
3381
3382
3383 Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate,
3384                                                        Handle<String> subject,
3385                                                        Handle<String> search,
3386                                                        Handle<String> replace,
3387                                                        bool* found,
3388                                                        int recursion_limit) {
3389   if (recursion_limit == 0) return Handle<String>::null();
3390   if (subject->IsConsString()) {
3391     ConsString* cons = ConsString::cast(*subject);
3392     Handle<String> first = Handle<String>(cons->first());
3393     Handle<String> second = Handle<String>(cons->second());
3394     Handle<String> new_first =
3395         StringReplaceOneCharWithString(isolate,
3396                                        first,
3397                                        search,
3398                                        replace,
3399                                        found,
3400                                        recursion_limit - 1);
3401     if (*found) return isolate->factory()->NewConsString(new_first, second);
3402     if (new_first.is_null()) return new_first;
3403
3404     Handle<String> new_second =
3405         StringReplaceOneCharWithString(isolate,
3406                                        second,
3407                                        search,
3408                                        replace,
3409                                        found,
3410                                        recursion_limit - 1);
3411     if (*found) return isolate->factory()->NewConsString(first, new_second);
3412     if (new_second.is_null()) return new_second;
3413
3414     return subject;
3415   } else {
3416     int index = StringMatch(isolate, subject, search, 0);
3417     if (index == -1) return subject;
3418     *found = true;
3419     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
3420     Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
3421     Handle<String> second =
3422         isolate->factory()->NewSubString(subject, index + 1, subject->length());
3423     return isolate->factory()->NewConsString(cons1, second);
3424   }
3425 }
3426
3427
3428 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
3429   ASSERT(args.length() == 3);
3430   HandleScope scope(isolate);
3431   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3432   CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
3433   CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
3434
3435   // If the cons string tree is too deep, we simply abort the recursion and
3436   // retry with a flattened subject string.
3437   const int kRecursionLimit = 0x1000;
3438   bool found = false;
3439   Handle<String> result =
3440       Runtime::StringReplaceOneCharWithString(isolate,
3441                                               subject,
3442                                               search,
3443                                               replace,
3444                                               &found,
3445                                               kRecursionLimit);
3446   if (!result.is_null()) return *result;
3447   return *Runtime::StringReplaceOneCharWithString(isolate,
3448                                                   FlattenGetString(subject),
3449                                                   search,
3450                                                   replace,
3451                                                   &found,
3452                                                   kRecursionLimit);
3453 }
3454
3455
3456 // Perform string match of pattern on subject, starting at start index.
3457 // Caller must ensure that 0 <= start_index <= sub->length(),
3458 // and should check that pat->length() + start_index <= sub->length().
3459 int Runtime::StringMatch(Isolate* isolate,
3460                          Handle<String> sub,
3461                          Handle<String> pat,
3462                          int start_index) {
3463   ASSERT(0 <= start_index);
3464   ASSERT(start_index <= sub->length());
3465
3466   int pattern_length = pat->length();
3467   if (pattern_length == 0) return start_index;
3468
3469   int subject_length = sub->length();
3470   if (start_index + pattern_length > subject_length) return -1;
3471
3472   if (!sub->IsFlat()) FlattenString(sub);
3473   if (!pat->IsFlat()) FlattenString(pat);
3474
3475   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
3476   // Extract flattened substrings of cons strings before determining asciiness.
3477   String::FlatContent seq_sub = sub->GetFlatContent();
3478   String::FlatContent seq_pat = pat->GetFlatContent();
3479
3480   // dispatch on type of strings
3481   if (seq_pat.IsAscii()) {
3482     Vector<const char> pat_vector = seq_pat.ToAsciiVector();
3483     if (seq_sub.IsAscii()) {
3484       return SearchString(isolate,
3485                           seq_sub.ToAsciiVector(),
3486                           pat_vector,
3487                           start_index);
3488     }
3489     return SearchString(isolate,
3490                         seq_sub.ToUC16Vector(),
3491                         pat_vector,
3492                         start_index);
3493   }
3494   Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
3495   if (seq_sub.IsAscii()) {
3496     return SearchString(isolate,
3497                         seq_sub.ToAsciiVector(),
3498                         pat_vector,
3499                         start_index);
3500   }
3501   return SearchString(isolate,
3502                       seq_sub.ToUC16Vector(),
3503                       pat_vector,
3504                       start_index);
3505 }
3506
3507
3508 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
3509   HandleScope scope(isolate);  // create a new handle scope
3510   ASSERT(args.length() == 3);
3511
3512   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3513   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3514
3515   Object* index = args[2];
3516   uint32_t start_index;
3517   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3518
3519   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
3520   int position =
3521       Runtime::StringMatch(isolate, sub, pat, start_index);
3522   return Smi::FromInt(position);
3523 }
3524
3525
3526 template <typename schar, typename pchar>
3527 static int StringMatchBackwards(Vector<const schar> subject,
3528                                 Vector<const pchar> pattern,
3529                                 int idx) {
3530   int pattern_length = pattern.length();
3531   ASSERT(pattern_length >= 1);
3532   ASSERT(idx + pattern_length <= subject.length());
3533
3534   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
3535     for (int i = 0; i < pattern_length; i++) {
3536       uc16 c = pattern[i];
3537       if (c > String::kMaxAsciiCharCode) {
3538         return -1;
3539       }
3540     }
3541   }
3542
3543   pchar pattern_first_char = pattern[0];
3544   for (int i = idx; i >= 0; i--) {
3545     if (subject[i] != pattern_first_char) continue;
3546     int j = 1;
3547     while (j < pattern_length) {
3548       if (pattern[j] != subject[i+j]) {
3549         break;
3550       }
3551       j++;
3552     }
3553     if (j == pattern_length) {
3554       return i;
3555     }
3556   }
3557   return -1;
3558 }
3559
3560 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
3561   HandleScope scope(isolate);  // create a new handle scope
3562   ASSERT(args.length() == 3);
3563
3564   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3565   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3566
3567   Object* index = args[2];
3568   uint32_t start_index;
3569   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3570
3571   uint32_t pat_length = pat->length();
3572   uint32_t sub_length = sub->length();
3573
3574   if (start_index + pat_length > sub_length) {
3575     start_index = sub_length - pat_length;
3576   }
3577
3578   if (pat_length == 0) {
3579     return Smi::FromInt(start_index);
3580   }
3581
3582   if (!sub->IsFlat()) FlattenString(sub);
3583   if (!pat->IsFlat()) FlattenString(pat);
3584
3585   int position = -1;
3586   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
3587
3588   String::FlatContent sub_content = sub->GetFlatContent();
3589   String::FlatContent pat_content = pat->GetFlatContent();
3590
3591   if (pat_content.IsAscii()) {
3592     Vector<const char> pat_vector = pat_content.ToAsciiVector();
3593     if (sub_content.IsAscii()) {
3594       position = StringMatchBackwards(sub_content.ToAsciiVector(),
3595                                       pat_vector,
3596                                       start_index);
3597     } else {
3598       position = StringMatchBackwards(sub_content.ToUC16Vector(),
3599                                       pat_vector,
3600                                       start_index);
3601     }
3602   } else {
3603     Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
3604     if (sub_content.IsAscii()) {
3605       position = StringMatchBackwards(sub_content.ToAsciiVector(),
3606                                       pat_vector,
3607                                       start_index);
3608     } else {
3609       position = StringMatchBackwards(sub_content.ToUC16Vector(),
3610                                       pat_vector,
3611                                       start_index);
3612     }
3613   }
3614
3615   return Smi::FromInt(position);
3616 }
3617
3618
3619 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
3620   NoHandleAllocation ha;
3621   ASSERT(args.length() == 2);
3622
3623   CONVERT_ARG_CHECKED(String, str1, 0);
3624   CONVERT_ARG_CHECKED(String, str2, 1);
3625
3626   if (str1 == str2) return Smi::FromInt(0);  // Equal.
3627   int str1_length = str1->length();
3628   int str2_length = str2->length();
3629
3630   // Decide trivial cases without flattening.
3631   if (str1_length == 0) {
3632     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
3633     return Smi::FromInt(-str2_length);
3634   } else {
3635     if (str2_length == 0) return Smi::FromInt(str1_length);
3636   }
3637
3638   int end = str1_length < str2_length ? str1_length : str2_length;
3639
3640   // No need to flatten if we are going to find the answer on the first
3641   // character.  At this point we know there is at least one character
3642   // in each string, due to the trivial case handling above.
3643   int d = str1->Get(0) - str2->Get(0);
3644   if (d != 0) return Smi::FromInt(d);
3645
3646   str1->TryFlatten();
3647   str2->TryFlatten();
3648
3649   StringInputBuffer& buf1 =
3650       *isolate->runtime_state()->string_locale_compare_buf1();
3651   StringInputBuffer& buf2 =
3652       *isolate->runtime_state()->string_locale_compare_buf2();
3653
3654   buf1.Reset(str1);
3655   buf2.Reset(str2);
3656
3657   for (int i = 0; i < end; i++) {
3658     uint16_t char1 = buf1.GetNext();
3659     uint16_t char2 = buf2.GetNext();
3660     if (char1 != char2) return Smi::FromInt(char1 - char2);
3661   }
3662
3663   return Smi::FromInt(str1_length - str2_length);
3664 }
3665
3666
3667 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
3668   NoHandleAllocation ha;
3669   ASSERT(args.length() == 3);
3670
3671   CONVERT_ARG_CHECKED(String, value, 0);
3672   int start, end;
3673   // We have a fast integer-only case here to avoid a conversion to double in
3674   // the common case where from and to are Smis.
3675   if (args[1]->IsSmi() && args[2]->IsSmi()) {
3676     CONVERT_SMI_ARG_CHECKED(from_number, 1);
3677     CONVERT_SMI_ARG_CHECKED(to_number, 2);
3678     start = from_number;
3679     end = to_number;
3680   } else {
3681     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
3682     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
3683     start = FastD2I(from_number);
3684     end = FastD2I(to_number);
3685   }
3686   RUNTIME_ASSERT(end >= start);
3687   RUNTIME_ASSERT(start >= 0);
3688   RUNTIME_ASSERT(end <= value->length());
3689   isolate->counters()->sub_string_runtime()->Increment();
3690   return value->SubString(start, end);
3691 }
3692
3693
3694 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
3695   ASSERT_EQ(3, args.length());
3696
3697   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3698   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
3699   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
3700   HandleScope handles;
3701
3702   Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
3703
3704   if (match.is_null()) {
3705     return Failure::Exception();
3706   }
3707   if (match->IsNull()) {
3708     return isolate->heap()->null_value();
3709   }
3710   int length = subject->length();
3711
3712   ZoneScope zone_space(isolate, DELETE_ON_EXIT);
3713   ZoneList<int> offsets(8);
3714   int start;
3715   int end;
3716   do {
3717     {
3718       AssertNoAllocation no_alloc;
3719       FixedArray* elements = FixedArray::cast(regexp_info->elements());
3720       start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
3721       end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
3722     }
3723     offsets.Add(start);
3724     offsets.Add(end);
3725     if (start == end) if (++end > length) break;
3726     match = RegExpImpl::Exec(regexp, subject, end, regexp_info);
3727     if (match.is_null()) {
3728       return Failure::Exception();
3729     }
3730   } while (!match->IsNull());
3731   int matches = offsets.length() / 2;
3732   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
3733   Handle<String> substring = isolate->factory()->
3734     NewSubString(subject, offsets.at(0), offsets.at(1));
3735   elements->set(0, *substring);
3736   for (int i = 1; i < matches ; i++) {
3737     int from = offsets.at(i * 2);
3738     int to = offsets.at(i * 2 + 1);
3739     Handle<String> substring = isolate->factory()->
3740         NewProperSubString(subject, from, to);
3741     elements->set(i, *substring);
3742   }
3743   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
3744   result->set_length(Smi::FromInt(matches));
3745   return *result;
3746 }
3747
3748
3749 static bool SearchStringMultiple(Isolate* isolate,
3750                                  Handle<String> subject,
3751                                  Handle<String> pattern,
3752                                  Handle<JSArray> last_match_info,
3753                                  FixedArrayBuilder* builder) {
3754   ASSERT(subject->IsFlat());
3755   ASSERT(pattern->IsFlat());
3756
3757   // Treating as if a previous match was before first character.
3758   int match_pos = -pattern->length();
3759
3760   for (;;) {  // Break when search complete.
3761     builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3762     AssertNoAllocation no_gc;
3763     String::FlatContent subject_content = subject->GetFlatContent();
3764     String::FlatContent pattern_content = pattern->GetFlatContent();
3765     if (subject_content.IsAscii()) {
3766       Vector<const char> subject_vector = subject_content.ToAsciiVector();
3767       if (pattern_content.IsAscii()) {
3768         if (SearchStringMultiple(isolate,
3769                                  subject_vector,
3770                                  pattern_content.ToAsciiVector(),
3771                                  *pattern,
3772                                  builder,
3773                                  &match_pos)) break;
3774       } else {
3775         if (SearchStringMultiple(isolate,
3776                                  subject_vector,
3777                                  pattern_content.ToUC16Vector(),
3778                                  *pattern,
3779                                  builder,
3780                                  &match_pos)) break;
3781       }
3782     } else {
3783       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3784       if (pattern_content.IsAscii()) {
3785         if (SearchStringMultiple(isolate,
3786                                  subject_vector,
3787                                  pattern_content.ToAsciiVector(),
3788                                  *pattern,
3789                                  builder,
3790                                  &match_pos)) break;
3791       } else {
3792         if (SearchStringMultiple(isolate,
3793                                  subject_vector,
3794                                  pattern_content.ToUC16Vector(),
3795                                  *pattern,
3796                                  builder,
3797                                  &match_pos)) break;
3798       }
3799     }
3800   }
3801
3802   if (match_pos >= 0) {
3803     SetLastMatchInfoNoCaptures(subject,
3804                                last_match_info,
3805                                match_pos,
3806                                match_pos + pattern->length());
3807     return true;
3808   }
3809   return false;  // No matches at all.
3810 }
3811
3812
3813 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
3814     Isolate* isolate,
3815     Handle<String> subject,
3816     Handle<JSRegExp> regexp,
3817     Handle<JSArray> last_match_array,
3818     FixedArrayBuilder* builder) {
3819   ASSERT(subject->IsFlat());
3820   int match_start = -1;
3821   int match_end = 0;
3822   int pos = 0;
3823   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3824   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3825
3826   OffsetsVector registers(required_registers, isolate);
3827   Vector<int32_t> register_vector(registers.vector(), registers.length());
3828   int subject_length = subject->length();
3829   bool first = true;
3830
3831   for (;;) {  // Break on failure, return on exception.
3832     RegExpImpl::IrregexpResult result =
3833         RegExpImpl::IrregexpExecOnce(regexp,
3834                                      subject,
3835                                      pos,
3836                                      register_vector);
3837     if (result == RegExpImpl::RE_SUCCESS) {
3838       match_start = register_vector[0];
3839       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3840       if (match_end < match_start) {
3841         ReplacementStringBuilder::AddSubjectSlice(builder,
3842                                                   match_end,
3843                                                   match_start);
3844       }
3845       match_end = register_vector[1];
3846       HandleScope loop_scope(isolate);
3847       if (!first) {
3848         builder->Add(*isolate->factory()->NewProperSubString(subject,
3849                                                              match_start,
3850                                                              match_end));
3851       } else {
3852         builder->Add(*isolate->factory()->NewSubString(subject,
3853                                                        match_start,
3854                                                        match_end));
3855       }
3856       if (match_start != match_end) {
3857         pos = match_end;
3858       } else {
3859         pos = match_end + 1;
3860         if (pos > subject_length) break;
3861       }
3862     } else if (result == RegExpImpl::RE_FAILURE) {
3863       break;
3864     } else {
3865       ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3866       return result;
3867     }
3868     first = false;
3869   }
3870
3871   if (match_start >= 0) {
3872     if (match_end < subject_length) {
3873       ReplacementStringBuilder::AddSubjectSlice(builder,
3874                                                 match_end,
3875                                                 subject_length);
3876     }
3877     SetLastMatchInfoNoCaptures(subject,
3878                                last_match_array,
3879                                match_start,
3880                                match_end);
3881     return RegExpImpl::RE_SUCCESS;
3882   } else {
3883     return RegExpImpl::RE_FAILURE;  // No matches at all.
3884   }
3885 }
3886
3887
3888 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
3889 // separate last match info.  See comment on that function.
3890 static RegExpImpl::IrregexpResult SearchRegExpMultiple(
3891     Isolate* isolate,
3892     Handle<String> subject,
3893     Handle<JSRegExp> regexp,
3894     Handle<JSArray> last_match_array,
3895     FixedArrayBuilder* builder) {
3896
3897   ASSERT(subject->IsFlat());
3898   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3899   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3900
3901   OffsetsVector registers(required_registers, isolate);
3902   Vector<int32_t> register_vector(registers.vector(), registers.length());
3903
3904   RegExpImpl::IrregexpResult result =
3905       RegExpImpl::IrregexpExecOnce(regexp,
3906                                    subject,
3907                                    0,
3908                                    register_vector);
3909
3910   int capture_count = regexp->CaptureCount();
3911   int subject_length = subject->length();
3912
3913   // Position to search from.
3914   int pos = 0;
3915   // End of previous match. Differs from pos if match was empty.
3916   int match_end = 0;
3917   if (result == RegExpImpl::RE_SUCCESS) {
3918     bool first = true;
3919     do {
3920       int match_start = register_vector[0];
3921       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3922       if (match_end < match_start) {
3923         ReplacementStringBuilder::AddSubjectSlice(builder,
3924                                                   match_end,
3925                                                   match_start);
3926       }
3927       match_end = register_vector[1];
3928
3929       {
3930         // Avoid accumulating new handles inside loop.
3931         HandleScope temp_scope(isolate);
3932         // Arguments array to replace function is match, captures, index and
3933         // subject, i.e., 3 + capture count in total.
3934         Handle<FixedArray> elements =
3935             isolate->factory()->NewFixedArray(3 + capture_count);
3936         Handle<String> match;
3937         if (!first) {
3938           match = isolate->factory()->NewProperSubString(subject,
3939                                                          match_start,
3940                                                          match_end);
3941         } else {
3942           match = isolate->factory()->NewSubString(subject,
3943                                                    match_start,
3944                                                    match_end);
3945         }
3946         elements->set(0, *match);
3947         for (int i = 1; i <= capture_count; i++) {
3948           int start = register_vector[i * 2];
3949           if (start >= 0) {
3950             int end = register_vector[i * 2 + 1];
3951             ASSERT(start <= end);
3952             Handle<String> substring;
3953             if (!first) {
3954               substring = isolate->factory()->NewProperSubString(subject,
3955                                                                  start,
3956                                                                  end);
3957             } else {
3958               substring = isolate->factory()->NewSubString(subject, start, end);
3959             }
3960             elements->set(i, *substring);
3961           } else {
3962             ASSERT(register_vector[i * 2 + 1] < 0);
3963             elements->set(i, isolate->heap()->undefined_value());
3964           }
3965         }
3966         elements->set(capture_count + 1, Smi::FromInt(match_start));
3967         elements->set(capture_count + 2, *subject);
3968         builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
3969       }
3970
3971       if (match_end > match_start) {
3972         pos = match_end;
3973       } else {
3974         pos = match_end + 1;
3975         if (pos > subject_length) {
3976           break;
3977         }
3978       }
3979
3980       result = RegExpImpl::IrregexpExecOnce(regexp,
3981                                             subject,
3982                                             pos,
3983                                             register_vector);
3984       first = false;
3985     } while (result == RegExpImpl::RE_SUCCESS);
3986
3987     if (result != RegExpImpl::RE_EXCEPTION) {
3988       // Finished matching, with at least one match.
3989       if (match_end < subject_length) {
3990         ReplacementStringBuilder::AddSubjectSlice(builder,
3991                                                   match_end,
3992                                                   subject_length);
3993       }
3994
3995       int last_match_capture_count = (capture_count + 1) * 2;
3996       int last_match_array_size =
3997           last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3998       last_match_array->EnsureSize(last_match_array_size);
3999       AssertNoAllocation no_gc;
4000       FixedArray* elements = FixedArray::cast(last_match_array->elements());
4001       // We have to set this even though the rest of the last match array is
4002       // ignored.
4003       RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
4004       // These are also read without consulting the override.
4005       RegExpImpl::SetLastSubject(elements, *subject);
4006       RegExpImpl::SetLastInput(elements, *subject);
4007       return RegExpImpl::RE_SUCCESS;
4008     }
4009   }
4010   // No matches at all, return failure or exception result directly.
4011   return result;
4012 }
4013
4014
4015 // This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4016 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4017 // set any other last match array info.
4018 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4019   ASSERT(args.length() == 4);
4020   HandleScope handles(isolate);
4021
4022   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4023   if (!subject->IsFlat()) FlattenString(subject);
4024   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4025   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4026   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4027
4028   ASSERT(last_match_info->HasFastElements());
4029   ASSERT(regexp->GetFlags().is_global());
4030   Handle<FixedArray> result_elements;
4031   if (result_array->HasFastElements()) {
4032     result_elements =
4033         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4034   }
4035   if (result_elements.is_null() || result_elements->length() < 16) {
4036     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4037   }
4038   FixedArrayBuilder builder(result_elements);
4039
4040   if (regexp->TypeTag() == JSRegExp::ATOM) {
4041     Handle<String> pattern(
4042         String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
4043     ASSERT(pattern->IsFlat());
4044     if (SearchStringMultiple(isolate, subject, pattern,
4045                              last_match_info, &builder)) {
4046       return *builder.ToJSArray(result_array);
4047     }
4048     return isolate->heap()->null_value();
4049   }
4050
4051   ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
4052
4053   RegExpImpl::IrregexpResult result;
4054   if (regexp->CaptureCount() == 0) {
4055     result = SearchRegExpNoCaptureMultiple(isolate,
4056                                            subject,
4057                                            regexp,
4058                                            last_match_info,
4059                                            &builder);
4060   } else {
4061     result = SearchRegExpMultiple(isolate,
4062                                   subject,
4063                                   regexp,
4064                                   last_match_info,
4065                                   &builder);
4066   }
4067   if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
4068   if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value();
4069   ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
4070   return Failure::Exception();
4071 }
4072
4073
4074 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4075   NoHandleAllocation ha;
4076   ASSERT(args.length() == 2);
4077   CONVERT_SMI_ARG_CHECKED(radix, 1);
4078   RUNTIME_ASSERT(2 <= radix && radix <= 36);
4079
4080   // Fast case where the result is a one character string.
4081   if (args[0]->IsSmi()) {
4082     int value = args.smi_at(0);
4083     if (value >= 0 && value < radix) {
4084       // Character array used for conversion.
4085       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4086       return isolate->heap()->
4087           LookupSingleCharacterStringFromCode(kCharTable[value]);
4088     }
4089   }
4090
4091   // Slow case.
4092   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4093   if (isnan(value)) {
4094     return *isolate->factory()->nan_symbol();
4095   }
4096   if (isinf(value)) {
4097     if (value < 0) {
4098       return *isolate->factory()->minus_infinity_symbol();
4099     }
4100     return *isolate->factory()->infinity_symbol();
4101   }
4102   char* str = DoubleToRadixCString(value, radix);
4103   MaybeObject* result =
4104       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4105   DeleteArray(str);
4106   return result;
4107 }
4108
4109
4110 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4111   NoHandleAllocation ha;
4112   ASSERT(args.length() == 2);
4113
4114   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4115   if (isnan(value)) {
4116     return *isolate->factory()->nan_symbol();
4117   }
4118   if (isinf(value)) {
4119     if (value < 0) {
4120       return *isolate->factory()->minus_infinity_symbol();
4121     }
4122     return *isolate->factory()->infinity_symbol();
4123   }
4124   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4125   int f = FastD2I(f_number);
4126   RUNTIME_ASSERT(f >= 0);
4127   char* str = DoubleToFixedCString(value, f);
4128   MaybeObject* res =
4129       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4130   DeleteArray(str);
4131   return res;
4132 }
4133
4134
4135 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4136   NoHandleAllocation ha;
4137   ASSERT(args.length() == 2);
4138
4139   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4140   if (isnan(value)) {
4141     return *isolate->factory()->nan_symbol();
4142   }
4143   if (isinf(value)) {
4144     if (value < 0) {
4145       return *isolate->factory()->minus_infinity_symbol();
4146     }
4147     return *isolate->factory()->infinity_symbol();
4148   }
4149   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4150   int f = FastD2I(f_number);
4151   RUNTIME_ASSERT(f >= -1 && f <= 20);
4152   char* str = DoubleToExponentialCString(value, f);
4153   MaybeObject* res =
4154       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4155   DeleteArray(str);
4156   return res;
4157 }
4158
4159
4160 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4161   NoHandleAllocation ha;
4162   ASSERT(args.length() == 2);
4163
4164   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4165   if (isnan(value)) {
4166     return *isolate->factory()->nan_symbol();
4167   }
4168   if (isinf(value)) {
4169     if (value < 0) {
4170       return *isolate->factory()->minus_infinity_symbol();
4171     }
4172     return *isolate->factory()->infinity_symbol();
4173   }
4174   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4175   int f = FastD2I(f_number);
4176   RUNTIME_ASSERT(f >= 1 && f <= 21);
4177   char* str = DoubleToPrecisionCString(value, f);
4178   MaybeObject* res =
4179       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4180   DeleteArray(str);
4181   return res;
4182 }
4183
4184
4185 // Returns a single character string where first character equals
4186 // string->Get(index).
4187 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4188   if (index < static_cast<uint32_t>(string->length())) {
4189     string->TryFlatten();
4190     return LookupSingleCharacterStringFromCode(
4191         string->Get(index));
4192   }
4193   return Execution::CharAt(string, index);
4194 }
4195
4196
4197 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4198                                          Handle<Object> object,
4199                                          uint32_t index) {
4200   // Handle [] indexing on Strings
4201   if (object->IsString()) {
4202     Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4203     if (!result->IsUndefined()) return *result;
4204   }
4205
4206   // Handle [] indexing on String objects
4207   if (object->IsStringObjectWithCharacterAt(index)) {
4208     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4209     Handle<Object> result =
4210         GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4211     if (!result->IsUndefined()) return *result;
4212   }
4213
4214   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4215     return object->GetPrototype()->GetElement(index);
4216   }
4217
4218   return object->GetElement(index);
4219 }
4220
4221
4222 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4223                                         Handle<Object> object,
4224                                         Handle<Object> key) {
4225   HandleScope scope(isolate);
4226
4227   if (object->IsUndefined() || object->IsNull()) {
4228     Handle<Object> args[2] = { key, object };
4229     Handle<Object> error =
4230         isolate->factory()->NewTypeError("non_object_property_load",
4231                                          HandleVector(args, 2));
4232     return isolate->Throw(*error);
4233   }
4234
4235   // Check if the given key is an array index.
4236   uint32_t index;
4237   if (key->ToArrayIndex(&index)) {
4238     return GetElementOrCharAt(isolate, object, index);
4239   }
4240
4241   // Convert the key to a string - possibly by calling back into JavaScript.
4242   Handle<String> name;
4243   if (key->IsString()) {
4244     name = Handle<String>::cast(key);
4245   } else {
4246     bool has_pending_exception = false;
4247     Handle<Object> converted =
4248         Execution::ToString(key, &has_pending_exception);
4249     if (has_pending_exception) return Failure::Exception();
4250     name = Handle<String>::cast(converted);
4251   }
4252
4253   // Check if the name is trivially convertible to an index and get
4254   // the element if so.
4255   if (name->AsArrayIndex(&index)) {
4256     return GetElementOrCharAt(isolate, object, index);
4257   } else {
4258     return object->GetProperty(*name);
4259   }
4260 }
4261
4262
4263 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4264   NoHandleAllocation ha;
4265   ASSERT(args.length() == 2);
4266
4267   Handle<Object> object = args.at<Object>(0);
4268   Handle<Object> key = args.at<Object>(1);
4269
4270   return Runtime::GetObjectProperty(isolate, object, key);
4271 }
4272
4273
4274 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
4275 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4276   NoHandleAllocation ha;
4277   ASSERT(args.length() == 2);
4278
4279   // Fast cases for getting named properties of the receiver JSObject
4280   // itself.
4281   //
4282   // The global proxy objects has to be excluded since LocalLookup on
4283   // the global proxy object can return a valid result even though the
4284   // global proxy object never has properties.  This is the case
4285   // because the global proxy object forwards everything to its hidden
4286   // prototype including local lookups.
4287   //
4288   // Additionally, we need to make sure that we do not cache results
4289   // for objects that require access checks.
4290   if (args[0]->IsJSObject()) {
4291     if (!args[0]->IsJSGlobalProxy() &&
4292         !args[0]->IsAccessCheckNeeded() &&
4293         args[1]->IsString()) {
4294       JSObject* receiver = JSObject::cast(args[0]);
4295       String* key = String::cast(args[1]);
4296       if (receiver->HasFastProperties()) {
4297         // Attempt to use lookup cache.
4298         Map* receiver_map = receiver->map();
4299         KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4300         int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4301         if (offset != -1) {
4302           Object* value = receiver->FastPropertyAt(offset);
4303           return value->IsTheHole()
4304               ? isolate->heap()->undefined_value()
4305               : value;
4306         }
4307         // Lookup cache miss.  Perform lookup and update the cache if
4308         // appropriate.
4309         LookupResult result(isolate);
4310         receiver->LocalLookup(key, &result);
4311         if (result.IsFound() && result.type() == FIELD) {
4312           int offset = result.GetFieldIndex();
4313           keyed_lookup_cache->Update(receiver_map, key, offset);
4314           return receiver->FastPropertyAt(offset);
4315         }
4316       } else {
4317         // Attempt dictionary lookup.
4318         StringDictionary* dictionary = receiver->property_dictionary();
4319         int entry = dictionary->FindEntry(key);
4320         if ((entry != StringDictionary::kNotFound) &&
4321             (dictionary->DetailsAt(entry).type() == NORMAL)) {
4322           Object* value = dictionary->ValueAt(entry);
4323           if (!receiver->IsGlobalObject()) return value;
4324           value = JSGlobalPropertyCell::cast(value)->value();
4325           if (!value->IsTheHole()) return value;
4326           // If value is the hole do the general lookup.
4327         }
4328       }
4329     } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4330       // JSObject without a string key. If the key is a Smi, check for a
4331       // definite out-of-bounds access to elements, which is a strong indicator
4332       // that subsequent accesses will also call the runtime. Proactively
4333       // transition elements to FAST_ELEMENTS to avoid excessive boxing of
4334       // doubles for those future calls in the case that the elements would
4335       // become FAST_DOUBLE_ELEMENTS.
4336       Handle<JSObject> js_object(args.at<JSObject>(0));
4337       ElementsKind elements_kind = js_object->GetElementsKind();
4338       if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4339           elements_kind == FAST_DOUBLE_ELEMENTS) {
4340         FixedArrayBase* elements = js_object->elements();
4341         if (args.at<Smi>(1)->value() >= elements->length()) {
4342           MaybeObject* maybe_object = TransitionElements(js_object,
4343                                                          FAST_ELEMENTS,
4344                                                          isolate);
4345           if (maybe_object->IsFailure()) return maybe_object;
4346         }
4347       }
4348     }
4349   } else if (args[0]->IsString() && args[1]->IsSmi()) {
4350     // Fast case for string indexing using [] with a smi index.
4351     HandleScope scope(isolate);
4352     Handle<String> str = args.at<String>(0);
4353     int index = args.smi_at(1);
4354     if (index >= 0 && index < str->length()) {
4355       Handle<Object> result = GetCharAt(str, index);
4356       return *result;
4357     }
4358   }
4359
4360   // Fall back to GetObjectProperty.
4361   return Runtime::GetObjectProperty(isolate,
4362                                     args.at<Object>(0),
4363                                     args.at<Object>(1));
4364 }
4365
4366
4367 static bool IsValidAccessor(Handle<Object> obj) {
4368   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4369 }
4370
4371
4372 // Implements part of 8.12.9 DefineOwnProperty.
4373 // There are 3 cases that lead here:
4374 // Step 4b - define a new accessor property.
4375 // Steps 9c & 12 - replace an existing data property with an accessor property.
4376 // Step 12 - update an existing accessor property with an accessor or generic
4377 //           descriptor.
4378 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4379   ASSERT(args.length() == 5);
4380   HandleScope scope(isolate);
4381   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4382   RUNTIME_ASSERT(!obj->IsNull());
4383   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4384   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4385   RUNTIME_ASSERT(IsValidAccessor(getter));
4386   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4387   RUNTIME_ASSERT(IsValidAccessor(setter));
4388   CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4389   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4390   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4391
4392   bool fast = obj->HasFastProperties();
4393   JSObject::DefineAccessor(obj, name, getter, setter, attr);
4394   if (fast) JSObject::TransformToFastProperties(obj, 0);
4395   return isolate->heap()->undefined_value();
4396 }
4397
4398 // Implements part of 8.12.9 DefineOwnProperty.
4399 // There are 3 cases that lead here:
4400 // Step 4a - define a new data property.
4401 // Steps 9b & 12 - replace an existing accessor property with a data property.
4402 // Step 12 - update an existing data property with a data or generic
4403 //           descriptor.
4404 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4405   ASSERT(args.length() == 4);
4406   HandleScope scope(isolate);
4407   CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4408   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4409   CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4410   CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4411   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4412   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4413
4414   LookupResult result(isolate);
4415   js_object->LocalLookupRealNamedProperty(*name, &result);
4416
4417   // Special case for callback properties.
4418   if (result.IsFound() && result.type() == CALLBACKS) {
4419     Object* callback = result.GetCallbackObject();
4420     // To be compatible with Safari we do not change the value on API objects
4421     // in Object.defineProperty(). Firefox disagrees here, and actually changes
4422     // the value.
4423     if (callback->IsAccessorInfo()) {
4424       return isolate->heap()->undefined_value();
4425     }
4426     // Avoid redefining foreign callback as data property, just use the stored
4427     // setter to update the value instead.
4428     // TODO(mstarzinger): So far this only works if property attributes don't
4429     // change, this should be fixed once we cleanup the underlying code.
4430     if (callback->IsForeign() && result.GetAttributes() == attr) {
4431       return js_object->SetPropertyWithCallback(callback,
4432                                                 *name,
4433                                                 *obj_value,
4434                                                 result.holder(),
4435                                                 kStrictMode);
4436     }
4437   }
4438
4439   // Take special care when attributes are different and there is already
4440   // a property. For simplicity we normalize the property which enables us
4441   // to not worry about changing the instance_descriptor and creating a new
4442   // map. The current version of SetObjectProperty does not handle attributes
4443   // correctly in the case where a property is a field and is reset with
4444   // new attributes.
4445   if (result.IsProperty() &&
4446       (attr != result.GetAttributes() || result.type() == CALLBACKS)) {
4447     // New attributes - normalize to avoid writing to instance descriptor
4448     if (js_object->IsJSGlobalProxy()) {
4449       // Since the result is a property, the prototype will exist so
4450       // we don't have to check for null.
4451       js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
4452     }
4453     JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
4454     // Use IgnoreAttributes version since a readonly property may be
4455     // overridden and SetProperty does not allow this.
4456     return js_object->SetLocalPropertyIgnoreAttributes(*name,
4457                                                        *obj_value,
4458                                                        attr);
4459   }
4460
4461   return Runtime::ForceSetObjectProperty(isolate,
4462                                          js_object,
4463                                          name,
4464                                          obj_value,
4465                                          attr);
4466 }
4467
4468
4469 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
4470                                         Handle<Object> object,
4471                                         Handle<Object> key,
4472                                         Handle<Object> value,
4473                                         PropertyAttributes attr,
4474                                         StrictModeFlag strict_mode) {
4475   SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
4476   HandleScope scope(isolate);
4477
4478   if (object->IsUndefined() || object->IsNull()) {
4479     Handle<Object> args[2] = { key, object };
4480     Handle<Object> error =
4481         isolate->factory()->NewTypeError("non_object_property_store",
4482                                          HandleVector(args, 2));
4483     return isolate->Throw(*error);
4484   }
4485
4486   if (object->IsJSProxy()) {
4487     bool has_pending_exception = false;
4488     Handle<Object> name = Execution::ToString(key, &has_pending_exception);
4489     if (has_pending_exception) return Failure::Exception();
4490     return JSProxy::cast(*object)->SetProperty(
4491         String::cast(*name), *value, attr, strict_mode);
4492   }
4493
4494   // If the object isn't a JavaScript object, we ignore the store.
4495   if (!object->IsJSObject()) return *value;
4496
4497   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4498
4499   // Check if the given key is an array index.
4500   uint32_t index;
4501   if (key->ToArrayIndex(&index)) {
4502     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4503     // of a string using [] notation.  We need to support this too in
4504     // JavaScript.
4505     // In the case of a String object we just need to redirect the assignment to
4506     // the underlying string if the index is in range.  Since the underlying
4507     // string does nothing with the assignment then we can ignore such
4508     // assignments.
4509     if (js_object->IsStringObjectWithCharacterAt(index)) {
4510       return *value;
4511     }
4512
4513     Handle<Object> result = JSObject::SetElement(
4514         js_object, index, value, attr, strict_mode, set_mode);
4515     if (result.is_null()) return Failure::Exception();
4516     return *value;
4517   }
4518
4519   if (key->IsString()) {
4520     Handle<Object> result;
4521     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4522       result = JSObject::SetElement(
4523           js_object, index, value, attr, strict_mode, set_mode);
4524     } else {
4525       Handle<String> key_string = Handle<String>::cast(key);
4526       key_string->TryFlatten();
4527       result = JSReceiver::SetProperty(
4528           js_object, key_string, value, attr, strict_mode);
4529     }
4530     if (result.is_null()) return Failure::Exception();
4531     return *value;
4532   }
4533
4534   // Call-back into JavaScript to convert the key to a string.
4535   bool has_pending_exception = false;
4536   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4537   if (has_pending_exception) return Failure::Exception();
4538   Handle<String> name = Handle<String>::cast(converted);
4539
4540   if (name->AsArrayIndex(&index)) {
4541     return js_object->SetElement(
4542         index, *value, attr, strict_mode, true, set_mode);
4543   } else {
4544     return js_object->SetProperty(*name, *value, attr, strict_mode);
4545   }
4546 }
4547
4548
4549 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
4550                                              Handle<JSObject> js_object,
4551                                              Handle<Object> key,
4552                                              Handle<Object> value,
4553                                              PropertyAttributes attr) {
4554   HandleScope scope(isolate);
4555
4556   // Check if the given key is an array index.
4557   uint32_t index;
4558   if (key->ToArrayIndex(&index)) {
4559     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4560     // of a string using [] notation.  We need to support this too in
4561     // JavaScript.
4562     // In the case of a String object we just need to redirect the assignment to
4563     // the underlying string if the index is in range.  Since the underlying
4564     // string does nothing with the assignment then we can ignore such
4565     // assignments.
4566     if (js_object->IsStringObjectWithCharacterAt(index)) {
4567       return *value;
4568     }
4569
4570     return js_object->SetElement(
4571         index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4572   }
4573
4574   if (key->IsString()) {
4575     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4576       return js_object->SetElement(
4577           index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4578     } else {
4579       Handle<String> key_string = Handle<String>::cast(key);
4580       key_string->TryFlatten();
4581       return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4582                                                          *value,
4583                                                          attr);
4584     }
4585   }
4586
4587   // Call-back into JavaScript to convert the key to a string.
4588   bool has_pending_exception = false;
4589   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4590   if (has_pending_exception) return Failure::Exception();
4591   Handle<String> name = Handle<String>::cast(converted);
4592
4593   if (name->AsArrayIndex(&index)) {
4594     return js_object->SetElement(
4595         index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4596   } else {
4597     return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4598   }
4599 }
4600
4601
4602 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
4603                                                 Handle<JSReceiver> receiver,
4604                                                 Handle<Object> key) {
4605   HandleScope scope(isolate);
4606
4607   // Check if the given key is an array index.
4608   uint32_t index;
4609   if (key->ToArrayIndex(&index)) {
4610     // In Firefox/SpiderMonkey, Safari and Opera you can access the
4611     // characters of a string using [] notation.  In the case of a
4612     // String object we just need to redirect the deletion to the
4613     // underlying string if the index is in range.  Since the
4614     // underlying string does nothing with the deletion, we can ignore
4615     // such deletions.
4616     if (receiver->IsStringObjectWithCharacterAt(index)) {
4617       return isolate->heap()->true_value();
4618     }
4619
4620     return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
4621   }
4622
4623   Handle<String> key_string;
4624   if (key->IsString()) {
4625     key_string = Handle<String>::cast(key);
4626   } else {
4627     // Call-back into JavaScript to convert the key to a string.
4628     bool has_pending_exception = false;
4629     Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4630     if (has_pending_exception) return Failure::Exception();
4631     key_string = Handle<String>::cast(converted);
4632   }
4633
4634   key_string->TryFlatten();
4635   return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
4636 }
4637
4638
4639 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
4640   NoHandleAllocation ha;
4641   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
4642
4643   Handle<Object> object = args.at<Object>(0);
4644   Handle<Object> key = args.at<Object>(1);
4645   Handle<Object> value = args.at<Object>(2);
4646   CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
4647   RUNTIME_ASSERT(
4648       (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4649   // Compute attributes.
4650   PropertyAttributes attributes =
4651       static_cast<PropertyAttributes>(unchecked_attributes);
4652
4653   StrictModeFlag strict_mode = kNonStrictMode;
4654   if (args.length() == 5) {
4655     CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
4656     strict_mode = strict_mode_flag;
4657   }
4658
4659   return Runtime::SetObjectProperty(isolate,
4660                                     object,
4661                                     key,
4662                                     value,
4663                                     attributes,
4664                                     strict_mode);
4665 }
4666
4667
4668 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
4669   NoHandleAllocation ha;
4670   RUNTIME_ASSERT(args.length() == 1);
4671   Handle<Object> object = args.at<Object>(0);
4672   return TransitionElements(object, FAST_DOUBLE_ELEMENTS, isolate);
4673 }
4674
4675
4676 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) {
4677   NoHandleAllocation ha;
4678   RUNTIME_ASSERT(args.length() == 1);
4679   Handle<Object> object = args.at<Object>(0);
4680   return TransitionElements(object, FAST_ELEMENTS, isolate);
4681 }
4682
4683
4684 // Set the native flag on the function.
4685 // This is used to decide if we should transform null and undefined
4686 // into the global object when doing call and apply.
4687 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
4688   NoHandleAllocation ha;
4689   RUNTIME_ASSERT(args.length() == 1);
4690
4691   Handle<Object> object = args.at<Object>(0);
4692
4693   if (object->IsJSFunction()) {
4694     JSFunction* func = JSFunction::cast(*object);
4695     func->shared()->set_native(true);
4696   }
4697   return isolate->heap()->undefined_value();
4698 }
4699
4700
4701 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
4702   RUNTIME_ASSERT(args.length() == 5);
4703   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
4704   CONVERT_SMI_ARG_CHECKED(store_index, 1);
4705   Handle<Object> value = args.at<Object>(2);
4706   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
4707   CONVERT_SMI_ARG_CHECKED(literal_index, 4);
4708   HandleScope scope;
4709
4710   Object* raw_boilerplate_object = literals->get(literal_index);
4711   Handle<JSArray> boilerplate(JSArray::cast(raw_boilerplate_object));
4712 #if DEBUG
4713   ElementsKind elements_kind = object->GetElementsKind();
4714 #endif
4715   ASSERT(elements_kind <= FAST_DOUBLE_ELEMENTS);
4716   // Smis should never trigger transitions.
4717   ASSERT(!value->IsSmi());
4718
4719   if (value->IsNumber()) {
4720     ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS);
4721     JSObject::TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS);
4722     if (IsMoreGeneralElementsKindTransition(boilerplate->GetElementsKind(),
4723                                             FAST_DOUBLE_ELEMENTS)) {
4724       JSObject::TransitionElementsKind(boilerplate, FAST_DOUBLE_ELEMENTS);
4725     }
4726     ASSERT(object->GetElementsKind() == FAST_DOUBLE_ELEMENTS);
4727     FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
4728     HeapNumber* number = HeapNumber::cast(*value);
4729     double_array->set(store_index, number->Number());
4730   } else {
4731     ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4732            elements_kind == FAST_DOUBLE_ELEMENTS);
4733     JSObject::TransitionElementsKind(object, FAST_ELEMENTS);
4734     if (IsMoreGeneralElementsKindTransition(boilerplate->GetElementsKind(),
4735                                             FAST_ELEMENTS)) {
4736       JSObject::TransitionElementsKind(boilerplate, FAST_ELEMENTS);
4737     }
4738     FixedArray* object_array = FixedArray::cast(object->elements());
4739     object_array->set(store_index, *value);
4740   }
4741   return *object;
4742 }
4743
4744
4745 // Check whether debugger and is about to step into the callback that is passed
4746 // to a built-in function such as Array.forEach.
4747 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
4748   if (!isolate->IsDebuggerActive()) return isolate->heap()->false_value();
4749   CONVERT_ARG_CHECKED(Object, callback, 0);
4750   // We do not step into the callback if it's a builtin or not even a function.
4751   if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
4752     return isolate->heap()->false_value();
4753   }
4754   return isolate->heap()->true_value();
4755 }
4756
4757
4758 // Set one shot breakpoints for the callback function that is passed to a
4759 // built-in function such as Array.forEach to enable stepping into the callback.
4760 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
4761   Debug* debug = isolate->debug();
4762   if (!debug->IsStepping()) return NULL;
4763   CONVERT_ARG_CHECKED(Object, callback, 0);
4764   HandleScope scope(isolate);
4765   Handle<SharedFunctionInfo> shared_info(JSFunction::cast(callback)->shared());
4766   // When leaving the callback, step out has been activated, but not performed
4767   // if we do not leave the builtin.  To be able to step into the callback
4768   // again, we need to clear the step out at this point.
4769   debug->ClearStepOut();
4770   debug->FloodWithOneShot(shared_info);
4771   return NULL;
4772 }
4773
4774
4775 // Set a local property, even if it is READ_ONLY.  If the property does not
4776 // exist, it will be added with attributes NONE.
4777 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
4778   NoHandleAllocation ha;
4779   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
4780   CONVERT_ARG_CHECKED(JSObject, object, 0);
4781   CONVERT_ARG_CHECKED(String, name, 1);
4782   // Compute attributes.
4783   PropertyAttributes attributes = NONE;
4784   if (args.length() == 4) {
4785     CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
4786     // Only attribute bits should be set.
4787     RUNTIME_ASSERT(
4788         (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4789     attributes = static_cast<PropertyAttributes>(unchecked_value);
4790   }
4791
4792   return object->
4793       SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
4794 }
4795
4796
4797 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
4798   NoHandleAllocation ha;
4799   ASSERT(args.length() == 3);
4800
4801   CONVERT_ARG_CHECKED(JSReceiver, object, 0);
4802   CONVERT_ARG_CHECKED(String, key, 1);
4803   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
4804   return object->DeleteProperty(key, (strict_mode == kStrictMode)
4805                                       ? JSReceiver::STRICT_DELETION
4806                                       : JSReceiver::NORMAL_DELETION);
4807 }
4808
4809
4810 static Object* HasLocalPropertyImplementation(Isolate* isolate,
4811                                               Handle<JSObject> object,
4812                                               Handle<String> key) {
4813   if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
4814   // Handle hidden prototypes.  If there's a hidden prototype above this thing
4815   // then we have to check it for properties, because they are supposed to
4816   // look like they are on this object.
4817   Handle<Object> proto(object->GetPrototype());
4818   if (proto->IsJSObject() &&
4819       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
4820     return HasLocalPropertyImplementation(isolate,
4821                                           Handle<JSObject>::cast(proto),
4822                                           key);
4823   }
4824   return isolate->heap()->false_value();
4825 }
4826
4827
4828 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
4829   NoHandleAllocation ha;
4830   ASSERT(args.length() == 2);
4831   CONVERT_ARG_CHECKED(String, key, 1);
4832
4833   uint32_t index;
4834   const bool key_is_array_index = key->AsArrayIndex(&index);
4835
4836   Object* obj = args[0];
4837   // Only JS objects can have properties.
4838   if (obj->IsJSObject()) {
4839     JSObject* object = JSObject::cast(obj);
4840     // Fast case: either the key is a real named property or it is not
4841     // an array index and there are no interceptors or hidden
4842     // prototypes.
4843     if (object->HasRealNamedProperty(key)) return isolate->heap()->true_value();
4844     Map* map = object->map();
4845     if (!key_is_array_index &&
4846         !map->has_named_interceptor() &&
4847         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
4848       return isolate->heap()->false_value();
4849     }
4850     // Slow case.
4851     HandleScope scope(isolate);
4852     return HasLocalPropertyImplementation(isolate,
4853                                           Handle<JSObject>(object),
4854                                           Handle<String>(key));
4855   } else if (obj->IsString() && key_is_array_index) {
4856     // Well, there is one exception:  Handle [] on strings.
4857     String* string = String::cast(obj);
4858     if (index < static_cast<uint32_t>(string->length())) {
4859       return isolate->heap()->true_value();
4860     }
4861   }
4862   return isolate->heap()->false_value();
4863 }
4864
4865
4866 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
4867   NoHandleAllocation na;
4868   ASSERT(args.length() == 2);
4869   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4870   CONVERT_ARG_CHECKED(String, key, 1);
4871
4872   bool result = receiver->HasProperty(key);
4873   if (isolate->has_pending_exception()) return Failure::Exception();
4874   return isolate->heap()->ToBoolean(result);
4875 }
4876
4877
4878 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
4879   NoHandleAllocation na;
4880   ASSERT(args.length() == 2);
4881   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4882   CONVERT_SMI_ARG_CHECKED(index, 1);
4883
4884   bool result = receiver->HasElement(index);
4885   if (isolate->has_pending_exception()) return Failure::Exception();
4886   return isolate->heap()->ToBoolean(result);
4887 }
4888
4889
4890 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
4891   NoHandleAllocation ha;
4892   ASSERT(args.length() == 2);
4893
4894   CONVERT_ARG_CHECKED(JSObject, object, 0);
4895   CONVERT_ARG_CHECKED(String, key, 1);
4896
4897   uint32_t index;
4898   if (key->AsArrayIndex(&index)) {
4899     JSObject::LocalElementType type = object->HasLocalElement(index);
4900     switch (type) {
4901       case JSObject::UNDEFINED_ELEMENT:
4902       case JSObject::STRING_CHARACTER_ELEMENT:
4903         return isolate->heap()->false_value();
4904       case JSObject::INTERCEPTED_ELEMENT:
4905       case JSObject::FAST_ELEMENT:
4906         return isolate->heap()->true_value();
4907       case JSObject::DICTIONARY_ELEMENT: {
4908         if (object->IsJSGlobalProxy()) {
4909           Object* proto = object->GetPrototype();
4910           if (proto->IsNull()) {
4911             return isolate->heap()->false_value();
4912           }
4913           ASSERT(proto->IsJSGlobalObject());
4914           object = JSObject::cast(proto);
4915         }
4916         FixedArray* elements = FixedArray::cast(object->elements());
4917         SeededNumberDictionary* dictionary = NULL;
4918         if (elements->map() ==
4919             isolate->heap()->non_strict_arguments_elements_map()) {
4920           dictionary = SeededNumberDictionary::cast(elements->get(1));
4921         } else {
4922           dictionary = SeededNumberDictionary::cast(elements);
4923         }
4924         int entry = dictionary->FindEntry(index);
4925         ASSERT(entry != SeededNumberDictionary::kNotFound);
4926         PropertyDetails details = dictionary->DetailsAt(entry);
4927         return isolate->heap()->ToBoolean(!details.IsDontEnum());
4928       }
4929     }
4930   }
4931
4932   PropertyAttributes att = object->GetLocalPropertyAttribute(key);
4933   return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
4934 }
4935
4936
4937 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
4938   HandleScope scope(isolate);
4939   ASSERT(args.length() == 1);
4940   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
4941   bool threw = false;
4942   Handle<JSArray> result = GetKeysFor(object, &threw);
4943   if (threw) return Failure::Exception();
4944   return *result;
4945 }
4946
4947
4948 // Returns either a FixedArray as Runtime_GetPropertyNames,
4949 // or, if the given object has an enum cache that contains
4950 // all enumerable properties of the object and its prototypes
4951 // have none, the map of the object. This is used to speed up
4952 // the check for deletions during a for-in.
4953 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
4954   ASSERT(args.length() == 1);
4955
4956   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
4957
4958   if (raw_object->IsSimpleEnum()) return raw_object->map();
4959
4960   HandleScope scope(isolate);
4961   Handle<JSReceiver> object(raw_object);
4962   bool threw = false;
4963   Handle<FixedArray> content =
4964       GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
4965   if (threw) return Failure::Exception();
4966
4967   // Test again, since cache may have been built by preceding call.
4968   if (object->IsSimpleEnum()) return object->map();
4969
4970   return *content;
4971 }
4972
4973
4974 // Find the length of the prototype chain that is to to handled as one. If a
4975 // prototype object is hidden it is to be viewed as part of the the object it
4976 // is prototype for.
4977 static int LocalPrototypeChainLength(JSObject* obj) {
4978   int count = 1;
4979   Object* proto = obj->GetPrototype();
4980   while (proto->IsJSObject() &&
4981          JSObject::cast(proto)->map()->is_hidden_prototype()) {
4982     count++;
4983     proto = JSObject::cast(proto)->GetPrototype();
4984   }
4985   return count;
4986 }
4987
4988
4989 // Return the names of the local named properties.
4990 // args[0]: object
4991 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
4992   HandleScope scope(isolate);
4993   ASSERT(args.length() == 1);
4994   if (!args[0]->IsJSObject()) {
4995     return isolate->heap()->undefined_value();
4996   }
4997   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4998
4999   // Skip the global proxy as it has no properties and always delegates to the
5000   // real global object.
5001   if (obj->IsJSGlobalProxy()) {
5002     // Only collect names if access is permitted.
5003     if (obj->IsAccessCheckNeeded() &&
5004         !isolate->MayNamedAccess(*obj,
5005                                  isolate->heap()->undefined_value(),
5006                                  v8::ACCESS_KEYS)) {
5007       isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
5008       return *isolate->factory()->NewJSArray(0);
5009     }
5010     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5011   }
5012
5013   // Find the number of objects making up this.
5014   int length = LocalPrototypeChainLength(*obj);
5015
5016   // Find the number of local properties for each of the objects.
5017   ScopedVector<int> local_property_count(length);
5018   int total_property_count = 0;
5019   Handle<JSObject> jsproto = obj;
5020   for (int i = 0; i < length; i++) {
5021     // Only collect names if access is permitted.
5022     if (jsproto->IsAccessCheckNeeded() &&
5023         !isolate->MayNamedAccess(*jsproto,
5024                                  isolate->heap()->undefined_value(),
5025                                  v8::ACCESS_KEYS)) {
5026       isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
5027       return *isolate->factory()->NewJSArray(0);
5028     }
5029     int n;
5030     n = jsproto->NumberOfLocalProperties();
5031     local_property_count[i] = n;
5032     total_property_count += n;
5033     if (i < length - 1) {
5034       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5035     }
5036   }
5037
5038   // Allocate an array with storage for all the property names.
5039   Handle<FixedArray> names =
5040       isolate->factory()->NewFixedArray(total_property_count);
5041
5042   // Get the property names.
5043   jsproto = obj;
5044   int proto_with_hidden_properties = 0;
5045   int next_copy_index = 0;
5046   for (int i = 0; i < length; i++) {
5047     jsproto->GetLocalPropertyNames(*names, next_copy_index);
5048     next_copy_index += local_property_count[i];
5049     if (jsproto->HasHiddenProperties()) {
5050       proto_with_hidden_properties++;
5051     }
5052     if (i < length - 1) {
5053       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5054     }
5055   }
5056
5057   // Filter out name of hidden propeties object.
5058   if (proto_with_hidden_properties > 0) {
5059     Handle<FixedArray> old_names = names;
5060     names = isolate->factory()->NewFixedArray(
5061         names->length() - proto_with_hidden_properties);
5062     int dest_pos = 0;
5063     for (int i = 0; i < total_property_count; i++) {
5064       Object* name = old_names->get(i);
5065       if (name == isolate->heap()->hidden_symbol()) {
5066         continue;
5067       }
5068       names->set(dest_pos++, name);
5069     }
5070   }
5071
5072   return *isolate->factory()->NewJSArrayWithElements(names);
5073 }
5074
5075
5076 // Return the names of the local indexed properties.
5077 // args[0]: object
5078 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5079   HandleScope scope(isolate);
5080   ASSERT(args.length() == 1);
5081   if (!args[0]->IsJSObject()) {
5082     return isolate->heap()->undefined_value();
5083   }
5084   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5085
5086   int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5087   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5088   obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5089   return *isolate->factory()->NewJSArrayWithElements(names);
5090 }
5091
5092
5093 // Return information on whether an object has a named or indexed interceptor.
5094 // args[0]: object
5095 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5096   HandleScope scope(isolate);
5097   ASSERT(args.length() == 1);
5098   if (!args[0]->IsJSObject()) {
5099     return Smi::FromInt(0);
5100   }
5101   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5102
5103   int result = 0;
5104   if (obj->HasNamedInterceptor()) result |= 2;
5105   if (obj->HasIndexedInterceptor()) result |= 1;
5106
5107   return Smi::FromInt(result);
5108 }
5109
5110
5111 // Return property names from named interceptor.
5112 // args[0]: object
5113 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5114   HandleScope scope(isolate);
5115   ASSERT(args.length() == 1);
5116   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5117
5118   if (obj->HasNamedInterceptor()) {
5119     v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5120     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5121   }
5122   return isolate->heap()->undefined_value();
5123 }
5124
5125
5126 // Return element names from indexed interceptor.
5127 // args[0]: object
5128 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5129   HandleScope scope(isolate);
5130   ASSERT(args.length() == 1);
5131   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5132
5133   if (obj->HasIndexedInterceptor()) {
5134     v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5135     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5136   }
5137   return isolate->heap()->undefined_value();
5138 }
5139
5140
5141 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5142   ASSERT_EQ(args.length(), 1);
5143   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5144   HandleScope scope(isolate);
5145   Handle<JSObject> object(raw_object);
5146
5147   if (object->IsJSGlobalProxy()) {
5148     // Do access checks before going to the global object.
5149     if (object->IsAccessCheckNeeded() &&
5150         !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5151                              v8::ACCESS_KEYS)) {
5152       isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5153       return *isolate->factory()->NewJSArray(0);
5154     }
5155
5156     Handle<Object> proto(object->GetPrototype());
5157     // If proxy is detached we simply return an empty array.
5158     if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5159     object = Handle<JSObject>::cast(proto);
5160   }
5161
5162   bool threw = false;
5163   Handle<FixedArray> contents =
5164       GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5165   if (threw) return Failure::Exception();
5166
5167   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5168   // property array and since the result is mutable we have to create
5169   // a fresh clone on each invocation.
5170   int length = contents->length();
5171   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5172   for (int i = 0; i < length; i++) {
5173     Object* entry = contents->get(i);
5174     if (entry->IsString()) {
5175       copy->set(i, entry);
5176     } else {
5177       ASSERT(entry->IsNumber());
5178       HandleScope scope(isolate);
5179       Handle<Object> entry_handle(entry, isolate);
5180       Handle<Object> entry_str =
5181           isolate->factory()->NumberToString(entry_handle);
5182       copy->set(i, *entry_str);
5183     }
5184   }
5185   return *isolate->factory()->NewJSArrayWithElements(copy);
5186 }
5187
5188
5189 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5190   NoHandleAllocation ha;
5191   ASSERT(args.length() == 1);
5192
5193   // Compute the frame holding the arguments.
5194   JavaScriptFrameIterator it(isolate);
5195   it.AdvanceToArgumentsFrame();
5196   JavaScriptFrame* frame = it.frame();
5197
5198   // Get the actual number of provided arguments.
5199   const uint32_t n = frame->ComputeParametersCount();
5200
5201   // Try to convert the key to an index. If successful and within
5202   // index return the the argument from the frame.
5203   uint32_t index;
5204   if (args[0]->ToArrayIndex(&index) && index < n) {
5205     return frame->GetParameter(index);
5206   }
5207
5208   // Convert the key to a string.
5209   HandleScope scope(isolate);
5210   bool exception = false;
5211   Handle<Object> converted =
5212       Execution::ToString(args.at<Object>(0), &exception);
5213   if (exception) return Failure::Exception();
5214   Handle<String> key = Handle<String>::cast(converted);
5215
5216   // Try to convert the string key into an array index.
5217   if (key->AsArrayIndex(&index)) {
5218     if (index < n) {
5219       return frame->GetParameter(index);
5220     } else {
5221       return isolate->initial_object_prototype()->GetElement(index);
5222     }
5223   }
5224
5225   // Handle special arguments properties.
5226   if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
5227   if (key->Equals(isolate->heap()->callee_symbol())) {
5228     Object* function = frame->function();
5229     if (function->IsJSFunction() &&
5230         !JSFunction::cast(function)->shared()->is_classic_mode()) {
5231       return isolate->Throw(*isolate->factory()->NewTypeError(
5232           "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5233     }
5234     return function;
5235   }
5236
5237   // Lookup in the initial Object.prototype object.
5238   return isolate->initial_object_prototype()->GetProperty(*key);
5239 }
5240
5241
5242 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5243   ASSERT(args.length() == 1);
5244   Object* object = args[0];
5245   return (object->IsJSObject() && !object->IsGlobalObject())
5246       ? JSObject::cast(object)->TransformToFastProperties(0)
5247       : object;
5248 }
5249
5250
5251 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToSlowProperties) {
5252   ASSERT(args.length() == 1);
5253   Object* obj = args[0];
5254   return (obj->IsJSObject() && !obj->IsJSGlobalProxy())
5255       ? JSObject::cast(obj)->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0)
5256       : obj;
5257 }
5258
5259
5260 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5261   NoHandleAllocation ha;
5262   ASSERT(args.length() == 1);
5263
5264   return args[0]->ToBoolean();
5265 }
5266
5267
5268 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
5269 // Possible optimizations: put the type string into the oddballs.
5270 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
5271   NoHandleAllocation ha;
5272
5273   Object* obj = args[0];
5274   if (obj->IsNumber()) return isolate->heap()->number_symbol();
5275   HeapObject* heap_obj = HeapObject::cast(obj);
5276
5277   // typeof an undetectable object is 'undefined'
5278   if (heap_obj->map()->is_undetectable()) {
5279     return isolate->heap()->undefined_symbol();
5280   }
5281
5282   InstanceType instance_type = heap_obj->map()->instance_type();
5283   if (instance_type < FIRST_NONSTRING_TYPE) {
5284     return isolate->heap()->string_symbol();
5285   }
5286
5287   switch (instance_type) {
5288     case ODDBALL_TYPE:
5289       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
5290         return isolate->heap()->boolean_symbol();
5291       }
5292       if (heap_obj->IsNull()) {
5293         return FLAG_harmony_typeof
5294             ? isolate->heap()->null_symbol()
5295             : isolate->heap()->object_symbol();
5296       }
5297       ASSERT(heap_obj->IsUndefined());
5298       return isolate->heap()->undefined_symbol();
5299     case JS_FUNCTION_TYPE:
5300     case JS_FUNCTION_PROXY_TYPE:
5301       return isolate->heap()->function_symbol();
5302     default:
5303       // For any kind of object not handled above, the spec rule for
5304       // host objects gives that it is okay to return "object"
5305       return isolate->heap()->object_symbol();
5306   }
5307 }
5308
5309
5310 static bool AreDigits(const char*s, int from, int to) {
5311   for (int i = from; i < to; i++) {
5312     if (s[i] < '0' || s[i] > '9') return false;
5313   }
5314
5315   return true;
5316 }
5317
5318
5319 static int ParseDecimalInteger(const char*s, int from, int to) {
5320   ASSERT(to - from < 10);  // Overflow is not possible.
5321   ASSERT(from < to);
5322   int d = s[from] - '0';
5323
5324   for (int i = from + 1; i < to; i++) {
5325     d = 10 * d + (s[i] - '0');
5326   }
5327
5328   return d;
5329 }
5330
5331
5332 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
5333   NoHandleAllocation ha;
5334   ASSERT(args.length() == 1);
5335   CONVERT_ARG_CHECKED(String, subject, 0);
5336   subject->TryFlatten();
5337
5338   // Fast case: short integer or some sorts of junk values.
5339   int len = subject->length();
5340   if (subject->IsSeqAsciiString()) {
5341     if (len == 0) return Smi::FromInt(0);
5342
5343     char const* data = SeqAsciiString::cast(subject)->GetChars();
5344     bool minus = (data[0] == '-');
5345     int start_pos = (minus ? 1 : 0);
5346
5347     if (start_pos == len) {
5348       return isolate->heap()->nan_value();
5349     } else if (data[start_pos] > '9') {
5350       // Fast check for a junk value. A valid string may start from a
5351       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
5352       // the 'I' character ('Infinity'). All of that have codes not greater than
5353       // '9' except 'I'.
5354       if (data[start_pos] != 'I') {
5355         return isolate->heap()->nan_value();
5356       }
5357     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
5358       // The maximal/minimal smi has 10 digits. If the string has less digits we
5359       // know it will fit into the smi-data type.
5360       int d = ParseDecimalInteger(data, start_pos, len);
5361       if (minus) {
5362         if (d == 0) return isolate->heap()->minus_zero_value();
5363         d = -d;
5364       } else if (!subject->HasHashCode() &&
5365                  len <= String::kMaxArrayIndexSize &&
5366                  (len == 1 || data[0] != '0')) {
5367         // String hash is not calculated yet but all the data are present.
5368         // Update the hash field to speed up sequential convertions.
5369         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
5370 #ifdef DEBUG
5371         subject->Hash();  // Force hash calculation.
5372         ASSERT_EQ(static_cast<int>(subject->hash_field()),
5373                   static_cast<int>(hash));
5374 #endif
5375         subject->set_hash_field(hash);
5376       }
5377       return Smi::FromInt(d);
5378     }
5379   }
5380
5381   // Slower case.
5382   return isolate->heap()->NumberFromDouble(
5383       StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
5384 }
5385
5386
5387 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringFromCharCodeArray) {
5388   NoHandleAllocation ha;
5389   ASSERT(args.length() == 1);
5390
5391   CONVERT_ARG_CHECKED(JSArray, codes, 0);
5392   int length = Smi::cast(codes->length())->value();
5393
5394   // Check if the string can be ASCII.
5395   int i;
5396   for (i = 0; i < length; i++) {
5397     Object* element;
5398     { MaybeObject* maybe_element = codes->GetElement(i);
5399       // We probably can't get an exception here, but just in order to enforce
5400       // the checking of inputs in the runtime calls we check here.
5401       if (!maybe_element->ToObject(&element)) return maybe_element;
5402     }
5403     CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5404     if ((chr & 0xffff) > String::kMaxAsciiCharCode)
5405       break;
5406   }
5407
5408   MaybeObject* maybe_object = NULL;
5409   if (i == length) {  // The string is ASCII.
5410     maybe_object = isolate->heap()->AllocateRawAsciiString(length);
5411   } else {  // The string is not ASCII.
5412     maybe_object = isolate->heap()->AllocateRawTwoByteString(length);
5413   }
5414
5415   Object* object = NULL;
5416   if (!maybe_object->ToObject(&object)) return maybe_object;
5417   String* result = String::cast(object);
5418   for (int i = 0; i < length; i++) {
5419     Object* element;
5420     { MaybeObject* maybe_element = codes->GetElement(i);
5421       if (!maybe_element->ToObject(&element)) return maybe_element;
5422     }
5423     CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5424     result->Set(i, chr & 0xffff);
5425   }
5426   return result;
5427 }
5428
5429
5430 // kNotEscaped is generated by the following:
5431 //
5432 // #!/bin/perl
5433 // for (my $i = 0; $i < 256; $i++) {
5434 //   print "\n" if $i % 16 == 0;
5435 //   my $c = chr($i);
5436 //   my $escaped = 1;
5437 //   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
5438 //   print $escaped ? "0, " : "1, ";
5439 // }
5440
5441
5442 static bool IsNotEscaped(uint16_t character) {
5443   // Only for 8 bit characters, the rest are always escaped (in a different way)
5444   ASSERT(character < 256);
5445   static const char kNotEscaped[256] = {
5446     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5447     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5448     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
5449     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
5450     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5451     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
5452     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5453     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
5454     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5455     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5456     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5457     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5458     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5459     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5460     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5461     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5462   };
5463   return kNotEscaped[character] != 0;
5464 }
5465
5466
5467 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
5468   const char hex_chars[] = "0123456789ABCDEF";
5469   NoHandleAllocation ha;
5470   ASSERT(args.length() == 1);
5471   CONVERT_ARG_CHECKED(String, source, 0);
5472
5473   source->TryFlatten();
5474
5475   int escaped_length = 0;
5476   int length = source->length();
5477   {
5478     Access<StringInputBuffer> buffer(
5479         isolate->runtime_state()->string_input_buffer());
5480     buffer->Reset(source);
5481     while (buffer->has_more()) {
5482       uint16_t character = buffer->GetNext();
5483       if (character >= 256) {
5484         escaped_length += 6;
5485       } else if (IsNotEscaped(character)) {
5486         escaped_length++;
5487       } else {
5488         escaped_length += 3;
5489       }
5490       // We don't allow strings that are longer than a maximal length.
5491       ASSERT(String::kMaxLength < 0x7fffffff - 6);  // Cannot overflow.
5492       if (escaped_length > String::kMaxLength) {
5493         isolate->context()->mark_out_of_memory();
5494         return Failure::OutOfMemoryException();
5495       }
5496     }
5497   }
5498   // No length change implies no change.  Return original string if no change.
5499   if (escaped_length == length) {
5500     return source;
5501   }
5502   Object* o;
5503   { MaybeObject* maybe_o =
5504         isolate->heap()->AllocateRawAsciiString(escaped_length);
5505     if (!maybe_o->ToObject(&o)) return maybe_o;
5506   }
5507   String* destination = String::cast(o);
5508   int dest_position = 0;
5509
5510   Access<StringInputBuffer> buffer(
5511       isolate->runtime_state()->string_input_buffer());
5512   buffer->Rewind();
5513   while (buffer->has_more()) {
5514     uint16_t chr = buffer->GetNext();
5515     if (chr >= 256) {
5516       destination->Set(dest_position, '%');
5517       destination->Set(dest_position+1, 'u');
5518       destination->Set(dest_position+2, hex_chars[chr >> 12]);
5519       destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
5520       destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
5521       destination->Set(dest_position+5, hex_chars[chr & 0xf]);
5522       dest_position += 6;
5523     } else if (IsNotEscaped(chr)) {
5524       destination->Set(dest_position, chr);
5525       dest_position++;
5526     } else {
5527       destination->Set(dest_position, '%');
5528       destination->Set(dest_position+1, hex_chars[chr >> 4]);
5529       destination->Set(dest_position+2, hex_chars[chr & 0xf]);
5530       dest_position += 3;
5531     }
5532   }
5533   return destination;
5534 }
5535
5536
5537 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
5538   static const signed char kHexValue['g'] = {
5539     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5540     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5541     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5542     0,  1,  2,   3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
5543     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5544     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5545     -1, 10, 11, 12, 13, 14, 15 };
5546
5547   if (character1 > 'f') return -1;
5548   int hi = kHexValue[character1];
5549   if (hi == -1) return -1;
5550   if (character2 > 'f') return -1;
5551   int lo = kHexValue[character2];
5552   if (lo == -1) return -1;
5553   return (hi << 4) + lo;
5554 }
5555
5556
5557 static inline int Unescape(String* source,
5558                            int i,
5559                            int length,
5560                            int* step) {
5561   uint16_t character = source->Get(i);
5562   int32_t hi = 0;
5563   int32_t lo = 0;
5564   if (character == '%' &&
5565       i <= length - 6 &&
5566       source->Get(i + 1) == 'u' &&
5567       (hi = TwoDigitHex(source->Get(i + 2),
5568                         source->Get(i + 3))) != -1 &&
5569       (lo = TwoDigitHex(source->Get(i + 4),
5570                         source->Get(i + 5))) != -1) {
5571     *step = 6;
5572     return (hi << 8) + lo;
5573   } else if (character == '%' &&
5574       i <= length - 3 &&
5575       (lo = TwoDigitHex(source->Get(i + 1),
5576                         source->Get(i + 2))) != -1) {
5577     *step = 3;
5578     return lo;
5579   } else {
5580     *step = 1;
5581     return character;
5582   }
5583 }
5584
5585
5586 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
5587   NoHandleAllocation ha;
5588   ASSERT(args.length() == 1);
5589   CONVERT_ARG_CHECKED(String, source, 0);
5590
5591   source->TryFlatten();
5592
5593   bool ascii = true;
5594   int length = source->length();
5595
5596   int unescaped_length = 0;
5597   for (int i = 0; i < length; unescaped_length++) {
5598     int step;
5599     if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
5600       ascii = false;
5601     }
5602     i += step;
5603   }
5604
5605   // No length change implies no change.  Return original string if no change.
5606   if (unescaped_length == length)
5607     return source;
5608
5609   Object* o;
5610   { MaybeObject* maybe_o =
5611         ascii ?
5612         isolate->heap()->AllocateRawAsciiString(unescaped_length) :
5613         isolate->heap()->AllocateRawTwoByteString(unescaped_length);
5614     if (!maybe_o->ToObject(&o)) return maybe_o;
5615   }
5616   String* destination = String::cast(o);
5617
5618   int dest_position = 0;
5619   for (int i = 0; i < length; dest_position++) {
5620     int step;
5621     destination->Set(dest_position, Unescape(source, i, length, &step));
5622     i += step;
5623   }
5624   return destination;
5625 }
5626
5627
5628 static const unsigned int kQuoteTableLength = 128u;
5629
5630 static const int kJsonQuotesCharactersPerEntry = 8;
5631 static const char* const JsonQuotes =
5632     "\\u0000  \\u0001  \\u0002  \\u0003  "
5633     "\\u0004  \\u0005  \\u0006  \\u0007  "
5634     "\\b      \\t      \\n      \\u000b  "
5635     "\\f      \\r      \\u000e  \\u000f  "
5636     "\\u0010  \\u0011  \\u0012  \\u0013  "
5637     "\\u0014  \\u0015  \\u0016  \\u0017  "
5638     "\\u0018  \\u0019  \\u001a  \\u001b  "
5639     "\\u001c  \\u001d  \\u001e  \\u001f  "
5640     "        !       \\\"      #       "
5641     "$       %       &       '       "
5642     "(       )       *       +       "
5643     ",       -       .       /       "
5644     "0       1       2       3       "
5645     "4       5       6       7       "
5646     "8       9       :       ;       "
5647     "<       =       >       ?       "
5648     "@       A       B       C       "
5649     "D       E       F       G       "
5650     "H       I       J       K       "
5651     "L       M       N       O       "
5652     "P       Q       R       S       "
5653     "T       U       V       W       "
5654     "X       Y       Z       [       "
5655     "\\\\      ]       ^       _       "
5656     "`       a       b       c       "
5657     "d       e       f       g       "
5658     "h       i       j       k       "
5659     "l       m       n       o       "
5660     "p       q       r       s       "
5661     "t       u       v       w       "
5662     "x       y       z       {       "
5663     "|       }       ~       \177       ";
5664
5665
5666 // For a string that is less than 32k characters it should always be
5667 // possible to allocate it in new space.
5668 static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
5669
5670
5671 // Doing JSON quoting cannot make the string more than this many times larger.
5672 static const int kJsonQuoteWorstCaseBlowup = 6;
5673
5674 static const int kSpaceForQuotesAndComma = 3;
5675 static const int kSpaceForBrackets = 2;
5676
5677 // Covers the entire ASCII range (all other characters are unchanged by JSON
5678 // quoting).
5679 static const byte JsonQuoteLengths[kQuoteTableLength] = {
5680     6, 6, 6, 6, 6, 6, 6, 6,
5681     2, 2, 2, 6, 2, 2, 6, 6,
5682     6, 6, 6, 6, 6, 6, 6, 6,
5683     6, 6, 6, 6, 6, 6, 6, 6,
5684     1, 1, 2, 1, 1, 1, 1, 1,
5685     1, 1, 1, 1, 1, 1, 1, 1,
5686     1, 1, 1, 1, 1, 1, 1, 1,
5687     1, 1, 1, 1, 1, 1, 1, 1,
5688     1, 1, 1, 1, 1, 1, 1, 1,
5689     1, 1, 1, 1, 1, 1, 1, 1,
5690     1, 1, 1, 1, 1, 1, 1, 1,
5691     1, 1, 1, 1, 2, 1, 1, 1,
5692     1, 1, 1, 1, 1, 1, 1, 1,
5693     1, 1, 1, 1, 1, 1, 1, 1,
5694     1, 1, 1, 1, 1, 1, 1, 1,
5695     1, 1, 1, 1, 1, 1, 1, 1,
5696 };
5697
5698
5699 template <typename StringType>
5700 MaybeObject* AllocateRawString(Isolate* isolate, int length);
5701
5702
5703 template <>
5704 MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
5705   return isolate->heap()->AllocateRawTwoByteString(length);
5706 }
5707
5708
5709 template <>
5710 MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) {
5711   return isolate->heap()->AllocateRawAsciiString(length);
5712 }
5713
5714
5715 template <typename Char, typename StringType, bool comma>
5716 static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
5717                                         Vector<const Char> characters) {
5718   int length = characters.length();
5719   const Char* read_cursor = characters.start();
5720   const Char* end = read_cursor + length;
5721   const int kSpaceForQuotes = 2 + (comma ? 1 :0);
5722   int quoted_length = kSpaceForQuotes;
5723   while (read_cursor < end) {
5724     Char c = *(read_cursor++);
5725     if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5726       quoted_length++;
5727     } else {
5728       quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
5729     }
5730   }
5731   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5732                                                          quoted_length);
5733   Object* new_object;
5734   if (!new_alloc->ToObject(&new_object)) {
5735     return new_alloc;
5736   }
5737   StringType* new_string = StringType::cast(new_object);
5738
5739   Char* write_cursor = reinterpret_cast<Char*>(
5740       new_string->address() + SeqString::kHeaderSize);
5741   if (comma) *(write_cursor++) = ',';
5742   *(write_cursor++) = '"';
5743
5744   read_cursor = characters.start();
5745   while (read_cursor < end) {
5746     Char c = *(read_cursor++);
5747     if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5748       *(write_cursor++) = c;
5749     } else {
5750       int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5751       const char* replacement = JsonQuotes +
5752           static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5753       for (int i = 0; i < len; i++) {
5754         *write_cursor++ = *replacement++;
5755       }
5756     }
5757   }
5758   *(write_cursor++) = '"';
5759   return new_string;
5760 }
5761
5762
5763 template <typename SinkChar, typename SourceChar>
5764 static inline SinkChar* WriteQuoteJsonString(
5765     Isolate* isolate,
5766     SinkChar* write_cursor,
5767     Vector<const SourceChar> characters) {
5768   // SinkChar is only char if SourceChar is guaranteed to be char.
5769   ASSERT(sizeof(SinkChar) >= sizeof(SourceChar));
5770   const SourceChar* read_cursor = characters.start();
5771   const SourceChar* end = read_cursor + characters.length();
5772   *(write_cursor++) = '"';
5773   while (read_cursor < end) {
5774     SourceChar c = *(read_cursor++);
5775     if (sizeof(SourceChar) > 1u &&
5776         static_cast<unsigned>(c) >= kQuoteTableLength) {
5777       *(write_cursor++) = static_cast<SinkChar>(c);
5778     } else {
5779       int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5780       const char* replacement = JsonQuotes +
5781           static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5782       write_cursor[0] = replacement[0];
5783       if (len > 1) {
5784         write_cursor[1] = replacement[1];
5785         if (len > 2) {
5786           ASSERT(len == 6);
5787           write_cursor[2] = replacement[2];
5788           write_cursor[3] = replacement[3];
5789           write_cursor[4] = replacement[4];
5790           write_cursor[5] = replacement[5];
5791         }
5792       }
5793       write_cursor += len;
5794     }
5795   }
5796   *(write_cursor++) = '"';
5797   return write_cursor;
5798 }
5799
5800
5801 template <typename Char, typename StringType, bool comma>
5802 static MaybeObject* QuoteJsonString(Isolate* isolate,
5803                                     Vector<const Char> characters) {
5804   int length = characters.length();
5805   isolate->counters()->quote_json_char_count()->Increment(length);
5806   int worst_case_length =
5807         length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
5808   if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5809     return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5810   }
5811
5812   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5813                                                          worst_case_length);
5814   Object* new_object;
5815   if (!new_alloc->ToObject(&new_object)) {
5816     return new_alloc;
5817   }
5818   if (!isolate->heap()->new_space()->Contains(new_object)) {
5819     // Even if our string is small enough to fit in new space we still have to
5820     // handle it being allocated in old space as may happen in the third
5821     // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
5822     // CEntryStub::GenerateCore.
5823     return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5824   }
5825   StringType* new_string = StringType::cast(new_object);
5826   ASSERT(isolate->heap()->new_space()->Contains(new_string));
5827
5828   Char* write_cursor = reinterpret_cast<Char*>(
5829       new_string->address() + SeqString::kHeaderSize);
5830   if (comma) *(write_cursor++) = ',';
5831   write_cursor = WriteQuoteJsonString<Char, Char>(isolate,
5832                                                   write_cursor,
5833                                                   characters);
5834   int final_length = static_cast<int>(
5835       write_cursor - reinterpret_cast<Char*>(
5836           new_string->address() + SeqString::kHeaderSize));
5837   isolate->heap()->new_space()->
5838       template ShrinkStringAtAllocationBoundary<StringType>(
5839           new_string, final_length);
5840   return new_string;
5841 }
5842
5843
5844 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
5845   NoHandleAllocation ha;
5846   CONVERT_ARG_CHECKED(String, str, 0);
5847   if (!str->IsFlat()) {
5848     MaybeObject* try_flatten = str->TryFlatten();
5849     Object* flat;
5850     if (!try_flatten->ToObject(&flat)) {
5851       return try_flatten;
5852     }
5853     str = String::cast(flat);
5854     ASSERT(str->IsFlat());
5855   }
5856   String::FlatContent flat = str->GetFlatContent();
5857   ASSERT(flat.IsFlat());
5858   if (flat.IsTwoByte()) {
5859     return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
5860                                                           flat.ToUC16Vector());
5861   } else {
5862     return QuoteJsonString<char, SeqAsciiString, false>(isolate,
5863                                                         flat.ToAsciiVector());
5864   }
5865 }
5866
5867
5868 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
5869   NoHandleAllocation ha;
5870   CONVERT_ARG_CHECKED(String, str, 0);
5871   if (!str->IsFlat()) {
5872     MaybeObject* try_flatten = str->TryFlatten();
5873     Object* flat;
5874     if (!try_flatten->ToObject(&flat)) {
5875       return try_flatten;
5876     }
5877     str = String::cast(flat);
5878     ASSERT(str->IsFlat());
5879   }
5880   String::FlatContent flat = str->GetFlatContent();
5881   if (flat.IsTwoByte()) {
5882     return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
5883                                                          flat.ToUC16Vector());
5884   } else {
5885     return QuoteJsonString<char, SeqAsciiString, true>(isolate,
5886                                                        flat.ToAsciiVector());
5887   }
5888 }
5889
5890
5891 template <typename Char, typename StringType>
5892 static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
5893                                          FixedArray* array,
5894                                          int worst_case_length) {
5895   int length = array->length();
5896
5897   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5898                                                          worst_case_length);
5899   Object* new_object;
5900   if (!new_alloc->ToObject(&new_object)) {
5901     return new_alloc;
5902   }
5903   if (!isolate->heap()->new_space()->Contains(new_object)) {
5904     // Even if our string is small enough to fit in new space we still have to
5905     // handle it being allocated in old space as may happen in the third
5906     // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
5907     // CEntryStub::GenerateCore.
5908     return isolate->heap()->undefined_value();
5909   }
5910   AssertNoAllocation no_gc;
5911   StringType* new_string = StringType::cast(new_object);
5912   ASSERT(isolate->heap()->new_space()->Contains(new_string));
5913
5914   Char* write_cursor = reinterpret_cast<Char*>(
5915       new_string->address() + SeqString::kHeaderSize);
5916   *(write_cursor++) = '[';
5917   for (int i = 0; i < length; i++) {
5918     if (i != 0) *(write_cursor++) = ',';
5919     String* str = String::cast(array->get(i));
5920     String::FlatContent content = str->GetFlatContent();
5921     ASSERT(content.IsFlat());
5922     if (content.IsTwoByte()) {
5923       write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
5924                                                       write_cursor,
5925                                                       content.ToUC16Vector());
5926     } else {
5927       write_cursor = WriteQuoteJsonString<Char, char>(isolate,
5928                                                       write_cursor,
5929                                                       content.ToAsciiVector());
5930     }
5931   }
5932   *(write_cursor++) = ']';
5933
5934   int final_length = static_cast<int>(
5935       write_cursor - reinterpret_cast<Char*>(
5936           new_string->address() + SeqString::kHeaderSize));
5937   isolate->heap()->new_space()->
5938       template ShrinkStringAtAllocationBoundary<StringType>(
5939           new_string, final_length);
5940   return new_string;
5941 }
5942
5943
5944 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
5945   NoHandleAllocation ha;
5946   ASSERT(args.length() == 1);
5947   CONVERT_ARG_CHECKED(JSArray, array, 0);
5948
5949   if (!array->HasFastElements()) return isolate->heap()->undefined_value();
5950   FixedArray* elements = FixedArray::cast(array->elements());
5951   int n = elements->length();
5952   bool ascii = true;
5953   int total_length = 0;
5954
5955   for (int i = 0; i < n; i++) {
5956     Object* elt = elements->get(i);
5957     if (!elt->IsString()) return isolate->heap()->undefined_value();
5958     String* element = String::cast(elt);
5959     if (!element->IsFlat()) return isolate->heap()->undefined_value();
5960     total_length += element->length();
5961     if (ascii && element->IsTwoByteRepresentation()) {
5962       ascii = false;
5963     }
5964   }
5965
5966   int worst_case_length =
5967       kSpaceForBrackets + n * kSpaceForQuotesAndComma
5968       + total_length * kJsonQuoteWorstCaseBlowup;
5969
5970   if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5971     return isolate->heap()->undefined_value();
5972   }
5973
5974   if (ascii) {
5975     return QuoteJsonStringArray<char, SeqAsciiString>(isolate,
5976                                                       elements,
5977                                                       worst_case_length);
5978   } else {
5979     return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
5980                                                         elements,
5981                                                         worst_case_length);
5982   }
5983 }
5984
5985
5986 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
5987   NoHandleAllocation ha;
5988
5989   CONVERT_ARG_CHECKED(String, s, 0);
5990   CONVERT_SMI_ARG_CHECKED(radix, 1);
5991
5992   s->TryFlatten();
5993
5994   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
5995   double value = StringToInt(isolate->unicode_cache(), s, radix);
5996   return isolate->heap()->NumberFromDouble(value);
5997 }
5998
5999
6000 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6001   NoHandleAllocation ha;
6002   CONVERT_ARG_CHECKED(String, str, 0);
6003
6004   // ECMA-262 section 15.1.2.3, empty string is NaN
6005   double value = StringToDouble(isolate->unicode_cache(),
6006                                 str, ALLOW_TRAILING_JUNK, OS::nan_value());
6007
6008   // Create a number object from the value.
6009   return isolate->heap()->NumberFromDouble(value);
6010 }
6011
6012
6013 template <class Converter>
6014 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6015     Isolate* isolate,
6016     String* s,
6017     int length,
6018     int input_string_length,
6019     unibrow::Mapping<Converter, 128>* mapping) {
6020   // We try this twice, once with the assumption that the result is no longer
6021   // than the input and, if that assumption breaks, again with the exact
6022   // length.  This may not be pretty, but it is nicer than what was here before
6023   // and I hereby claim my vaffel-is.
6024   //
6025   // Allocate the resulting string.
6026   //
6027   // NOTE: This assumes that the upper/lower case of an ASCII
6028   // character is also ASCII.  This is currently the case, but it
6029   // might break in the future if we implement more context and locale
6030   // dependent upper/lower conversions.
6031   Object* o;
6032   { MaybeObject* maybe_o = s->IsAsciiRepresentation()
6033         ? isolate->heap()->AllocateRawAsciiString(length)
6034         : isolate->heap()->AllocateRawTwoByteString(length);
6035     if (!maybe_o->ToObject(&o)) return maybe_o;
6036   }
6037   String* result = String::cast(o);
6038   bool has_changed_character = false;
6039
6040   // Convert all characters to upper case, assuming that they will fit
6041   // in the buffer
6042   Access<StringInputBuffer> buffer(
6043       isolate->runtime_state()->string_input_buffer());
6044   buffer->Reset(s);
6045   unibrow::uchar chars[Converter::kMaxWidth];
6046   // We can assume that the string is not empty
6047   uc32 current = buffer->GetNext();
6048   for (int i = 0; i < length;) {
6049     bool has_next = buffer->has_more();
6050     uc32 next = has_next ? buffer->GetNext() : 0;
6051     int char_length = mapping->get(current, next, chars);
6052     if (char_length == 0) {
6053       // The case conversion of this character is the character itself.
6054       result->Set(i, current);
6055       i++;
6056     } else if (char_length == 1) {
6057       // Common case: converting the letter resulted in one character.
6058       ASSERT(static_cast<uc32>(chars[0]) != current);
6059       result->Set(i, chars[0]);
6060       has_changed_character = true;
6061       i++;
6062     } else if (length == input_string_length) {
6063       // We've assumed that the result would be as long as the
6064       // input but here is a character that converts to several
6065       // characters.  No matter, we calculate the exact length
6066       // of the result and try the whole thing again.
6067       //
6068       // Note that this leaves room for optimization.  We could just
6069       // memcpy what we already have to the result string.  Also,
6070       // the result string is the last object allocated we could
6071       // "realloc" it and probably, in the vast majority of cases,
6072       // extend the existing string to be able to hold the full
6073       // result.
6074       int next_length = 0;
6075       if (has_next) {
6076         next_length = mapping->get(next, 0, chars);
6077         if (next_length == 0) next_length = 1;
6078       }
6079       int current_length = i + char_length + next_length;
6080       while (buffer->has_more()) {
6081         current = buffer->GetNext();
6082         // NOTE: we use 0 as the next character here because, while
6083         // the next character may affect what a character converts to,
6084         // it does not in any case affect the length of what it convert
6085         // to.
6086         int char_length = mapping->get(current, 0, chars);
6087         if (char_length == 0) char_length = 1;
6088         current_length += char_length;
6089         if (current_length > Smi::kMaxValue) {
6090           isolate->context()->mark_out_of_memory();
6091           return Failure::OutOfMemoryException();
6092         }
6093       }
6094       // Try again with the real length.
6095       return Smi::FromInt(current_length);
6096     } else {
6097       for (int j = 0; j < char_length; j++) {
6098         result->Set(i, chars[j]);
6099         i++;
6100       }
6101       has_changed_character = true;
6102     }
6103     current = next;
6104   }
6105   if (has_changed_character) {
6106     return result;
6107   } else {
6108     // If we didn't actually change anything in doing the conversion
6109     // we simple return the result and let the converted string
6110     // become garbage; there is no reason to keep two identical strings
6111     // alive.
6112     return s;
6113   }
6114 }
6115
6116
6117 namespace {
6118
6119 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6120
6121
6122 // Given a word and two range boundaries returns a word with high bit
6123 // set in every byte iff the corresponding input byte was strictly in
6124 // the range (m, n). All the other bits in the result are cleared.
6125 // This function is only useful when it can be inlined and the
6126 // boundaries are statically known.
6127 // Requires: all bytes in the input word and the boundaries must be
6128 // ASCII (less than 0x7F).
6129 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6130   // Every byte in an ASCII string is less than or equal to 0x7F.
6131   ASSERT((w & (kOneInEveryByte * 0x7F)) == w);
6132   // Use strict inequalities since in edge cases the function could be
6133   // further simplified.
6134   ASSERT(0 < m && m < n && n < 0x7F);
6135   // Has high bit set in every w byte less than n.
6136   uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6137   // Has high bit set in every w byte greater than m.
6138   uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6139   return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6140 }
6141
6142
6143 enum AsciiCaseConversion {
6144   ASCII_TO_LOWER,
6145   ASCII_TO_UPPER
6146 };
6147
6148
6149 template <AsciiCaseConversion dir>
6150 struct FastAsciiConverter {
6151   static bool Convert(char* dst, char* src, int length) {
6152 #ifdef DEBUG
6153     char* saved_dst = dst;
6154     char* saved_src = src;
6155 #endif
6156     // We rely on the distance between upper and lower case letters
6157     // being a known power of 2.
6158     ASSERT('a' - 'A' == (1 << 5));
6159     // Boundaries for the range of input characters than require conversion.
6160     const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
6161     const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
6162     bool changed = false;
6163     char* const limit = src + length;
6164 #ifdef V8_HOST_CAN_READ_UNALIGNED
6165     // Process the prefix of the input that requires no conversion one
6166     // (machine) word at a time.
6167     while (src <= limit - sizeof(uintptr_t)) {
6168       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6169       if (AsciiRangeMask(w, lo, hi) != 0) {
6170         changed = true;
6171         break;
6172       }
6173       *reinterpret_cast<uintptr_t*>(dst) = w;
6174       src += sizeof(uintptr_t);
6175       dst += sizeof(uintptr_t);
6176     }
6177     // Process the remainder of the input performing conversion when
6178     // required one word at a time.
6179     while (src <= limit - sizeof(uintptr_t)) {
6180       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6181       uintptr_t m = AsciiRangeMask(w, lo, hi);
6182       // The mask has high (7th) bit set in every byte that needs
6183       // conversion and we know that the distance between cases is
6184       // 1 << 5.
6185       *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6186       src += sizeof(uintptr_t);
6187       dst += sizeof(uintptr_t);
6188     }
6189 #endif
6190     // Process the last few bytes of the input (or the whole input if
6191     // unaligned access is not supported).
6192     while (src < limit) {
6193       char c = *src;
6194       if (lo < c && c < hi) {
6195         c ^= (1 << 5);
6196         changed = true;
6197       }
6198       *dst = c;
6199       ++src;
6200       ++dst;
6201     }
6202 #ifdef DEBUG
6203     CheckConvert(saved_dst, saved_src, length, changed);
6204 #endif
6205     return changed;
6206   }
6207
6208 #ifdef DEBUG
6209   static void CheckConvert(char* dst, char* src, int length, bool changed) {
6210     bool expected_changed = false;
6211     for (int i = 0; i < length; i++) {
6212       if (dst[i] == src[i]) continue;
6213       expected_changed = true;
6214       if (dir == ASCII_TO_LOWER) {
6215         ASSERT('A' <= src[i] && src[i] <= 'Z');
6216         ASSERT(dst[i] == src[i] + ('a' - 'A'));
6217       } else {
6218         ASSERT(dir == ASCII_TO_UPPER);
6219         ASSERT('a' <= src[i] && src[i] <= 'z');
6220         ASSERT(dst[i] == src[i] - ('a' - 'A'));
6221       }
6222     }
6223     ASSERT(expected_changed == changed);
6224   }
6225 #endif
6226 };
6227
6228
6229 struct ToLowerTraits {
6230   typedef unibrow::ToLowercase UnibrowConverter;
6231
6232   typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6233 };
6234
6235
6236 struct ToUpperTraits {
6237   typedef unibrow::ToUppercase UnibrowConverter;
6238
6239   typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6240 };
6241
6242 }  // namespace
6243
6244
6245 template <typename ConvertTraits>
6246 MUST_USE_RESULT static MaybeObject* ConvertCase(
6247     Arguments args,
6248     Isolate* isolate,
6249     unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
6250   NoHandleAllocation ha;
6251   CONVERT_ARG_CHECKED(String, s, 0);
6252   s = s->TryFlattenGetString();
6253
6254   const int length = s->length();
6255   // Assume that the string is not empty; we need this assumption later
6256   if (length == 0) return s;
6257
6258   // Simpler handling of ASCII strings.
6259   //
6260   // NOTE: This assumes that the upper/lower case of an ASCII
6261   // character is also ASCII.  This is currently the case, but it
6262   // might break in the future if we implement more context and locale
6263   // dependent upper/lower conversions.
6264   if (s->IsSeqAsciiString()) {
6265     Object* o;
6266     { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length);
6267       if (!maybe_o->ToObject(&o)) return maybe_o;
6268     }
6269     SeqAsciiString* result = SeqAsciiString::cast(o);
6270     bool has_changed_character = ConvertTraits::AsciiConverter::Convert(
6271         result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length);
6272     return has_changed_character ? result : s;
6273   }
6274
6275   Object* answer;
6276   { MaybeObject* maybe_answer =
6277         ConvertCaseHelper(isolate, s, length, length, mapping);
6278     if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6279   }
6280   if (answer->IsSmi()) {
6281     // Retry with correct length.
6282     { MaybeObject* maybe_answer =
6283           ConvertCaseHelper(isolate,
6284                             s, Smi::cast(answer)->value(), length, mapping);
6285       if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6286     }
6287   }
6288   return answer;
6289 }
6290
6291
6292 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6293   return ConvertCase<ToLowerTraits>(
6294       args, isolate, isolate->runtime_state()->to_lower_mapping());
6295 }
6296
6297
6298 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6299   return ConvertCase<ToUpperTraits>(
6300       args, isolate, isolate->runtime_state()->to_upper_mapping());
6301 }
6302
6303
6304 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6305   return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6306 }
6307
6308
6309 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6310   NoHandleAllocation ha;
6311   ASSERT(args.length() == 3);
6312
6313   CONVERT_ARG_CHECKED(String, s, 0);
6314   CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6315   CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6316
6317   s->TryFlatten();
6318   int length = s->length();
6319
6320   int left = 0;
6321   if (trimLeft) {
6322     while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6323       left++;
6324     }
6325   }
6326
6327   int right = length;
6328   if (trimRight) {
6329     while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6330       right--;
6331     }
6332   }
6333   return s->SubString(left, right);
6334 }
6335
6336
6337 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6338   ASSERT(args.length() == 3);
6339   HandleScope handle_scope(isolate);
6340   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6341   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6342   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6343
6344   int subject_length = subject->length();
6345   int pattern_length = pattern->length();
6346   RUNTIME_ASSERT(pattern_length > 0);
6347
6348   if (limit == 0xffffffffu) {
6349     Handle<Object> cached_answer(StringSplitCache::Lookup(
6350         isolate->heap()->string_split_cache(),
6351         *subject,
6352         *pattern));
6353     if (*cached_answer != Smi::FromInt(0)) {
6354       Handle<JSArray> result =
6355           isolate->factory()->NewJSArrayWithElements(
6356               Handle<FixedArray>::cast(cached_answer));
6357       return *result;
6358     }
6359   }
6360
6361   // The limit can be very large (0xffffffffu), but since the pattern
6362   // isn't empty, we can never create more parts than ~half the length
6363   // of the subject.
6364
6365   if (!subject->IsFlat()) FlattenString(subject);
6366
6367   static const int kMaxInitialListCapacity = 16;
6368
6369   ZoneScope scope(isolate, DELETE_ON_EXIT);
6370
6371   // Find (up to limit) indices of separator and end-of-string in subject
6372   int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6373   ZoneList<int> indices(initial_capacity);
6374   if (!pattern->IsFlat()) FlattenString(pattern);
6375
6376   FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit);
6377
6378   if (static_cast<uint32_t>(indices.length()) < limit) {
6379     indices.Add(subject_length);
6380   }
6381
6382   // The list indices now contains the end of each part to create.
6383
6384   // Create JSArray of substrings separated by separator.
6385   int part_count = indices.length();
6386
6387   Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6388   MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
6389   if (maybe_result->IsFailure()) return maybe_result;
6390   result->set_length(Smi::FromInt(part_count));
6391
6392   ASSERT(result->HasFastElements());
6393
6394   if (part_count == 1 && indices.at(0) == subject_length) {
6395     FixedArray::cast(result->elements())->set(0, *subject);
6396     return *result;
6397   }
6398
6399   Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6400   int part_start = 0;
6401   for (int i = 0; i < part_count; i++) {
6402     HandleScope local_loop_handle;
6403     int part_end = indices.at(i);
6404     Handle<String> substring =
6405         isolate->factory()->NewProperSubString(subject, part_start, part_end);
6406     elements->set(i, *substring);
6407     part_start = part_end + pattern_length;
6408   }
6409
6410   if (limit == 0xffffffffu) {
6411     if (result->HasFastElements()) {
6412       StringSplitCache::Enter(isolate->heap(),
6413                               isolate->heap()->string_split_cache(),
6414                               *subject,
6415                               *pattern,
6416                               *elements);
6417     }
6418   }
6419
6420   return *result;
6421 }
6422
6423
6424 // Copies ASCII characters to the given fixed array looking up
6425 // one-char strings in the cache. Gives up on the first char that is
6426 // not in the cache and fills the remainder with smi zeros. Returns
6427 // the length of the successfully copied prefix.
6428 static int CopyCachedAsciiCharsToArray(Heap* heap,
6429                                        const char* chars,
6430                                        FixedArray* elements,
6431                                        int length) {
6432   AssertNoAllocation no_gc;
6433   FixedArray* ascii_cache = heap->single_character_string_cache();
6434   Object* undefined = heap->undefined_value();
6435   int i;
6436   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6437   for (i = 0; i < length; ++i) {
6438     Object* value = ascii_cache->get(chars[i]);
6439     if (value == undefined) break;
6440     elements->set(i, value, mode);
6441   }
6442   if (i < length) {
6443     ASSERT(Smi::FromInt(0) == 0);
6444     memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6445   }
6446 #ifdef DEBUG
6447   for (int j = 0; j < length; ++j) {
6448     Object* element = elements->get(j);
6449     ASSERT(element == Smi::FromInt(0) ||
6450            (element->IsString() && String::cast(element)->LooksValid()));
6451   }
6452 #endif
6453   return i;
6454 }
6455
6456
6457 // Converts a String to JSArray.
6458 // For example, "foo" => ["f", "o", "o"].
6459 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6460   HandleScope scope(isolate);
6461   ASSERT(args.length() == 2);
6462   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6463   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6464
6465   s = FlattenGetString(s);
6466   const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6467
6468   Handle<FixedArray> elements;
6469   int position = 0;
6470   if (s->IsFlat() && s->IsAsciiRepresentation()) {
6471     // Try using cached chars where possible.
6472     Object* obj;
6473     { MaybeObject* maybe_obj =
6474           isolate->heap()->AllocateUninitializedFixedArray(length);
6475       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6476     }
6477     elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6478     String::FlatContent content = s->GetFlatContent();
6479     if (content.IsAscii()) {
6480       Vector<const char> chars = content.ToAsciiVector();
6481       // Note, this will initialize all elements (not only the prefix)
6482       // to prevent GC from seeing partially initialized array.
6483       position = CopyCachedAsciiCharsToArray(isolate->heap(),
6484                                              chars.start(),
6485                                              *elements,
6486                                              length);
6487     } else {
6488       MemsetPointer(elements->data_start(),
6489                     isolate->heap()->undefined_value(),
6490                     length);
6491     }
6492   } else {
6493     elements = isolate->factory()->NewFixedArray(length);
6494   }
6495   for (int i = position; i < length; ++i) {
6496     Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
6497     elements->set(i, *str);
6498   }
6499
6500 #ifdef DEBUG
6501   for (int i = 0; i < length; ++i) {
6502     ASSERT(String::cast(elements->get(i))->length() == 1);
6503   }
6504 #endif
6505
6506   return *isolate->factory()->NewJSArrayWithElements(elements);
6507 }
6508
6509
6510 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6511   NoHandleAllocation ha;
6512   ASSERT(args.length() == 1);
6513   CONVERT_ARG_CHECKED(String, value, 0);
6514   return value->ToObject();
6515 }
6516
6517
6518 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6519   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6520   int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6521   return char_length == 0;
6522 }
6523
6524
6525 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6526   NoHandleAllocation ha;
6527   ASSERT(args.length() == 1);
6528
6529   Object* number = args[0];
6530   RUNTIME_ASSERT(number->IsNumber());
6531
6532   return isolate->heap()->NumberToString(number);
6533 }
6534
6535
6536 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6537   NoHandleAllocation ha;
6538   ASSERT(args.length() == 1);
6539
6540   Object* number = args[0];
6541   RUNTIME_ASSERT(number->IsNumber());
6542
6543   return isolate->heap()->NumberToString(number, false);
6544 }
6545
6546
6547 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6548   NoHandleAllocation ha;
6549   ASSERT(args.length() == 1);
6550
6551   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6552
6553   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6554   if (number > 0 && number <= Smi::kMaxValue) {
6555     return Smi::FromInt(static_cast<int>(number));
6556   }
6557   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6558 }
6559
6560
6561 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6562   NoHandleAllocation ha;
6563   ASSERT(args.length() == 1);
6564
6565   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6566
6567   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6568   if (number > 0 && number <= Smi::kMaxValue) {
6569     return Smi::FromInt(static_cast<int>(number));
6570   }
6571
6572   double double_value = DoubleToInteger(number);
6573   // Map both -0 and +0 to +0.
6574   if (double_value == 0) double_value = 0;
6575
6576   return isolate->heap()->NumberFromDouble(double_value);
6577 }
6578
6579
6580 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6581   NoHandleAllocation ha;
6582   ASSERT(args.length() == 1);
6583
6584   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6585   return isolate->heap()->NumberFromUint32(number);
6586 }
6587
6588
6589 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6590   NoHandleAllocation ha;
6591   ASSERT(args.length() == 1);
6592
6593   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6594
6595   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6596   if (number > 0 && number <= Smi::kMaxValue) {
6597     return Smi::FromInt(static_cast<int>(number));
6598   }
6599   return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6600 }
6601
6602
6603 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
6604 // a small integer.
6605 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6606   NoHandleAllocation ha;
6607   ASSERT(args.length() == 1);
6608
6609   Object* obj = args[0];
6610   if (obj->IsSmi()) {
6611     return obj;
6612   }
6613   if (obj->IsHeapNumber()) {
6614     double value = HeapNumber::cast(obj)->value();
6615     int int_value = FastD2I(value);
6616     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6617       return Smi::FromInt(int_value);
6618     }
6619   }
6620   return isolate->heap()->nan_value();
6621 }
6622
6623
6624 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6625   NoHandleAllocation ha;
6626   ASSERT(args.length() == 0);
6627   return isolate->heap()->AllocateHeapNumber(0);
6628 }
6629
6630
6631 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6632   NoHandleAllocation ha;
6633   ASSERT(args.length() == 2);
6634
6635   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6636   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6637   return isolate->heap()->NumberFromDouble(x + y);
6638 }
6639
6640
6641 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6642   NoHandleAllocation ha;
6643   ASSERT(args.length() == 2);
6644
6645   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6646   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6647   return isolate->heap()->NumberFromDouble(x - y);
6648 }
6649
6650
6651 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6652   NoHandleAllocation ha;
6653   ASSERT(args.length() == 2);
6654
6655   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6656   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6657   return isolate->heap()->NumberFromDouble(x * y);
6658 }
6659
6660
6661 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6662   NoHandleAllocation ha;
6663   ASSERT(args.length() == 1);
6664
6665   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6666   return isolate->heap()->NumberFromDouble(-x);
6667 }
6668
6669
6670 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6671   NoHandleAllocation ha;
6672   ASSERT(args.length() == 0);
6673
6674   return isolate->heap()->NumberFromDouble(9876543210.0);
6675 }
6676
6677
6678 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6679   NoHandleAllocation ha;
6680   ASSERT(args.length() == 2);
6681
6682   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6683   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6684   return isolate->heap()->NumberFromDouble(x / y);
6685 }
6686
6687
6688 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6689   NoHandleAllocation ha;
6690   ASSERT(args.length() == 2);
6691
6692   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6693   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6694
6695   x = modulo(x, y);
6696   // NumberFromDouble may return a Smi instead of a Number object
6697   return isolate->heap()->NumberFromDouble(x);
6698 }
6699
6700
6701 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6702   NoHandleAllocation ha;
6703   ASSERT(args.length() == 2);
6704   CONVERT_ARG_CHECKED(String, str1, 0);
6705   CONVERT_ARG_CHECKED(String, str2, 1);
6706   isolate->counters()->string_add_runtime()->Increment();
6707   return isolate->heap()->AllocateConsString(str1, str2);
6708 }
6709
6710
6711 template <typename sinkchar>
6712 static inline void StringBuilderConcatHelper(String* special,
6713                                              sinkchar* sink,
6714                                              FixedArray* fixed_array,
6715                                              int array_length) {
6716   int position = 0;
6717   for (int i = 0; i < array_length; i++) {
6718     Object* element = fixed_array->get(i);
6719     if (element->IsSmi()) {
6720       // Smi encoding of position and length.
6721       int encoded_slice = Smi::cast(element)->value();
6722       int pos;
6723       int len;
6724       if (encoded_slice > 0) {
6725         // Position and length encoded in one smi.
6726         pos = StringBuilderSubstringPosition::decode(encoded_slice);
6727         len = StringBuilderSubstringLength::decode(encoded_slice);
6728       } else {
6729         // Position and length encoded in two smis.
6730         Object* obj = fixed_array->get(++i);
6731         ASSERT(obj->IsSmi());
6732         pos = Smi::cast(obj)->value();
6733         len = -encoded_slice;
6734       }
6735       String::WriteToFlat(special,
6736                           sink + position,
6737                           pos,
6738                           pos + len);
6739       position += len;
6740     } else {
6741       String* string = String::cast(element);
6742       int element_length = string->length();
6743       String::WriteToFlat(string, sink + position, 0, element_length);
6744       position += element_length;
6745     }
6746   }
6747 }
6748
6749
6750 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
6751   NoHandleAllocation ha;
6752   ASSERT(args.length() == 3);
6753   CONVERT_ARG_CHECKED(JSArray, array, 0);
6754   if (!args[1]->IsSmi()) {
6755     isolate->context()->mark_out_of_memory();
6756     return Failure::OutOfMemoryException();
6757   }
6758   int array_length = args.smi_at(1);
6759   CONVERT_ARG_CHECKED(String, special, 2);
6760
6761   // This assumption is used by the slice encoding in one or two smis.
6762   ASSERT(Smi::kMaxValue >= String::kMaxLength);
6763
6764   MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
6765   if (maybe_result->IsFailure()) return maybe_result;
6766
6767   int special_length = special->length();
6768   if (!array->HasFastElements()) {
6769     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6770   }
6771   FixedArray* fixed_array = FixedArray::cast(array->elements());
6772   if (fixed_array->length() < array_length) {
6773     array_length = fixed_array->length();
6774   }
6775
6776   if (array_length == 0) {
6777     return isolate->heap()->empty_string();
6778   } else if (array_length == 1) {
6779     Object* first = fixed_array->get(0);
6780     if (first->IsString()) return first;
6781   }
6782
6783   bool ascii = special->HasOnlyAsciiChars();
6784   int position = 0;
6785   for (int i = 0; i < array_length; i++) {
6786     int increment = 0;
6787     Object* elt = fixed_array->get(i);
6788     if (elt->IsSmi()) {
6789       // Smi encoding of position and length.
6790       int smi_value = Smi::cast(elt)->value();
6791       int pos;
6792       int len;
6793       if (smi_value > 0) {
6794         // Position and length encoded in one smi.
6795         pos = StringBuilderSubstringPosition::decode(smi_value);
6796         len = StringBuilderSubstringLength::decode(smi_value);
6797       } else {
6798         // Position and length encoded in two smis.
6799         len = -smi_value;
6800         // Get the position and check that it is a positive smi.
6801         i++;
6802         if (i >= array_length) {
6803           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6804         }
6805         Object* next_smi = fixed_array->get(i);
6806         if (!next_smi->IsSmi()) {
6807           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6808         }
6809         pos = Smi::cast(next_smi)->value();
6810         if (pos < 0) {
6811           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6812         }
6813       }
6814       ASSERT(pos >= 0);
6815       ASSERT(len >= 0);
6816       if (pos > special_length || len > special_length - pos) {
6817         return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6818       }
6819       increment = len;
6820     } else if (elt->IsString()) {
6821       String* element = String::cast(elt);
6822       int element_length = element->length();
6823       increment = element_length;
6824       if (ascii && !element->HasOnlyAsciiChars()) {
6825         ascii = false;
6826       }
6827     } else {
6828       ASSERT(!elt->IsTheHole());
6829       return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6830     }
6831     if (increment > String::kMaxLength - position) {
6832       isolate->context()->mark_out_of_memory();
6833       return Failure::OutOfMemoryException();
6834     }
6835     position += increment;
6836   }
6837
6838   int length = position;
6839   Object* object;
6840
6841   if (ascii) {
6842     { MaybeObject* maybe_object =
6843           isolate->heap()->AllocateRawAsciiString(length);
6844       if (!maybe_object->ToObject(&object)) return maybe_object;
6845     }
6846     SeqAsciiString* answer = SeqAsciiString::cast(object);
6847     StringBuilderConcatHelper(special,
6848                               answer->GetChars(),
6849                               fixed_array,
6850                               array_length);
6851     return answer;
6852   } else {
6853     { MaybeObject* maybe_object =
6854           isolate->heap()->AllocateRawTwoByteString(length);
6855       if (!maybe_object->ToObject(&object)) return maybe_object;
6856     }
6857     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6858     StringBuilderConcatHelper(special,
6859                               answer->GetChars(),
6860                               fixed_array,
6861                               array_length);
6862     return answer;
6863   }
6864 }
6865
6866
6867 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
6868   NoHandleAllocation ha;
6869   ASSERT(args.length() == 3);
6870   CONVERT_ARG_CHECKED(JSArray, array, 0);
6871   if (!args[1]->IsSmi()) {
6872     isolate->context()->mark_out_of_memory();
6873     return Failure::OutOfMemoryException();
6874   }
6875   int array_length = args.smi_at(1);
6876   CONVERT_ARG_CHECKED(String, separator, 2);
6877
6878   if (!array->HasFastElements()) {
6879     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6880   }
6881   FixedArray* fixed_array = FixedArray::cast(array->elements());
6882   if (fixed_array->length() < array_length) {
6883     array_length = fixed_array->length();
6884   }
6885
6886   if (array_length == 0) {
6887     return isolate->heap()->empty_string();
6888   } else if (array_length == 1) {
6889     Object* first = fixed_array->get(0);
6890     if (first->IsString()) return first;
6891   }
6892
6893   int separator_length = separator->length();
6894   int max_nof_separators =
6895       (String::kMaxLength + separator_length - 1) / separator_length;
6896   if (max_nof_separators < (array_length - 1)) {
6897       isolate->context()->mark_out_of_memory();
6898       return Failure::OutOfMemoryException();
6899   }
6900   int length = (array_length - 1) * separator_length;
6901   for (int i = 0; i < array_length; i++) {
6902     Object* element_obj = fixed_array->get(i);
6903     if (!element_obj->IsString()) {
6904       // TODO(1161): handle this case.
6905       return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6906     }
6907     String* element = String::cast(element_obj);
6908     int increment = element->length();
6909     if (increment > String::kMaxLength - length) {
6910       isolate->context()->mark_out_of_memory();
6911       return Failure::OutOfMemoryException();
6912     }
6913     length += increment;
6914   }
6915
6916   Object* object;
6917   { MaybeObject* maybe_object =
6918         isolate->heap()->AllocateRawTwoByteString(length);
6919     if (!maybe_object->ToObject(&object)) return maybe_object;
6920   }
6921   SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6922
6923   uc16* sink = answer->GetChars();
6924 #ifdef DEBUG
6925   uc16* end = sink + length;
6926 #endif
6927
6928   String* first = String::cast(fixed_array->get(0));
6929   int first_length = first->length();
6930   String::WriteToFlat(first, sink, 0, first_length);
6931   sink += first_length;
6932
6933   for (int i = 1; i < array_length; i++) {
6934     ASSERT(sink + separator_length <= end);
6935     String::WriteToFlat(separator, sink, 0, separator_length);
6936     sink += separator_length;
6937
6938     String* element = String::cast(fixed_array->get(i));
6939     int element_length = element->length();
6940     ASSERT(sink + element_length <= end);
6941     String::WriteToFlat(element, sink, 0, element_length);
6942     sink += element_length;
6943   }
6944   ASSERT(sink == end);
6945
6946   ASSERT(!answer->HasOnlyAsciiChars());  // Use %_FastAsciiArrayJoin instead.
6947   return answer;
6948 }
6949
6950 template <typename Char>
6951 static void JoinSparseArrayWithSeparator(FixedArray* elements,
6952                                          int elements_length,
6953                                          uint32_t array_length,
6954                                          String* separator,
6955                                          Vector<Char> buffer) {
6956   int previous_separator_position = 0;
6957   int separator_length = separator->length();
6958   int cursor = 0;
6959   for (int i = 0; i < elements_length; i += 2) {
6960     int position = NumberToInt32(elements->get(i));
6961     String* string = String::cast(elements->get(i + 1));
6962     int string_length = string->length();
6963     if (string->length() > 0) {
6964       while (previous_separator_position < position) {
6965         String::WriteToFlat<Char>(separator, &buffer[cursor],
6966                                   0, separator_length);
6967         cursor += separator_length;
6968         previous_separator_position++;
6969       }
6970       String::WriteToFlat<Char>(string, &buffer[cursor],
6971                                 0, string_length);
6972       cursor += string->length();
6973     }
6974   }
6975   if (separator_length > 0) {
6976     // Array length must be representable as a signed 32-bit number,
6977     // otherwise the total string length would have been too large.
6978     ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
6979     int last_array_index = static_cast<int>(array_length - 1);
6980     while (previous_separator_position < last_array_index) {
6981       String::WriteToFlat<Char>(separator, &buffer[cursor],
6982                                 0, separator_length);
6983       cursor += separator_length;
6984       previous_separator_position++;
6985     }
6986   }
6987   ASSERT(cursor <= buffer.length());
6988 }
6989
6990
6991 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
6992   NoHandleAllocation ha;
6993   ASSERT(args.length() == 3);
6994   CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
6995   RUNTIME_ASSERT(elements_array->HasFastElements() ||
6996                  elements_array->HasFastSmiOnlyElements());
6997   CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
6998   CONVERT_ARG_CHECKED(String, separator, 2);
6999   // elements_array is fast-mode JSarray of alternating positions
7000   // (increasing order) and strings.
7001   // array_length is length of original array (used to add separators);
7002   // separator is string to put between elements. Assumed to be non-empty.
7003
7004   // Find total length of join result.
7005   int string_length = 0;
7006   bool is_ascii = separator->IsAsciiRepresentation();
7007   int max_string_length;
7008   if (is_ascii) {
7009     max_string_length = SeqAsciiString::kMaxLength;
7010   } else {
7011     max_string_length = SeqTwoByteString::kMaxLength;
7012   }
7013   bool overflow = false;
7014   CONVERT_NUMBER_CHECKED(int, elements_length,
7015                          Int32, elements_array->length());
7016   RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7017   FixedArray* elements = FixedArray::cast(elements_array->elements());
7018   for (int i = 0; i < elements_length; i += 2) {
7019     RUNTIME_ASSERT(elements->get(i)->IsNumber());
7020     RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7021     String* string = String::cast(elements->get(i + 1));
7022     int length = string->length();
7023     if (is_ascii && !string->IsAsciiRepresentation()) {
7024       is_ascii = false;
7025       max_string_length = SeqTwoByteString::kMaxLength;
7026     }
7027     if (length > max_string_length ||
7028         max_string_length - length < string_length) {
7029       overflow = true;
7030       break;
7031     }
7032     string_length += length;
7033   }
7034   int separator_length = separator->length();
7035   if (!overflow && separator_length > 0) {
7036     if (array_length <= 0x7fffffffu) {
7037       int separator_count = static_cast<int>(array_length) - 1;
7038       int remaining_length = max_string_length - string_length;
7039       if ((remaining_length / separator_length) >= separator_count) {
7040         string_length += separator_length * (array_length - 1);
7041       } else {
7042         // Not room for the separators within the maximal string length.
7043         overflow = true;
7044       }
7045     } else {
7046       // Nonempty separator and at least 2^31-1 separators necessary
7047       // means that the string is too large to create.
7048       STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7049       overflow = true;
7050     }
7051   }
7052   if (overflow) {
7053     // Throw OutOfMemory exception for creating too large a string.
7054     V8::FatalProcessOutOfMemory("Array join result too large.");
7055   }
7056
7057   if (is_ascii) {
7058     MaybeObject* result_allocation =
7059         isolate->heap()->AllocateRawAsciiString(string_length);
7060     if (result_allocation->IsFailure()) return result_allocation;
7061     SeqAsciiString* result_string =
7062         SeqAsciiString::cast(result_allocation->ToObjectUnchecked());
7063     JoinSparseArrayWithSeparator<char>(elements,
7064                                        elements_length,
7065                                        array_length,
7066                                        separator,
7067                                        Vector<char>(result_string->GetChars(),
7068                                                     string_length));
7069     return result_string;
7070   } else {
7071     MaybeObject* result_allocation =
7072         isolate->heap()->AllocateRawTwoByteString(string_length);
7073     if (result_allocation->IsFailure()) return result_allocation;
7074     SeqTwoByteString* result_string =
7075         SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7076     JoinSparseArrayWithSeparator<uc16>(elements,
7077                                        elements_length,
7078                                        array_length,
7079                                        separator,
7080                                        Vector<uc16>(result_string->GetChars(),
7081                                                     string_length));
7082     return result_string;
7083   }
7084 }
7085
7086
7087 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7088   NoHandleAllocation ha;
7089   ASSERT(args.length() == 2);
7090
7091   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7092   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7093   return isolate->heap()->NumberFromInt32(x | y);
7094 }
7095
7096
7097 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7098   NoHandleAllocation ha;
7099   ASSERT(args.length() == 2);
7100
7101   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7102   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7103   return isolate->heap()->NumberFromInt32(x & y);
7104 }
7105
7106
7107 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7108   NoHandleAllocation ha;
7109   ASSERT(args.length() == 2);
7110
7111   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7112   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7113   return isolate->heap()->NumberFromInt32(x ^ y);
7114 }
7115
7116
7117 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
7118   NoHandleAllocation ha;
7119   ASSERT(args.length() == 1);
7120
7121   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7122   return isolate->heap()->NumberFromInt32(~x);
7123 }
7124
7125
7126 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7127   NoHandleAllocation ha;
7128   ASSERT(args.length() == 2);
7129
7130   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7131   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7132   return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7133 }
7134
7135
7136 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7137   NoHandleAllocation ha;
7138   ASSERT(args.length() == 2);
7139
7140   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7141   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7142   return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7143 }
7144
7145
7146 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7147   NoHandleAllocation ha;
7148   ASSERT(args.length() == 2);
7149
7150   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7151   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7152   return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7153 }
7154
7155
7156 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7157   NoHandleAllocation ha;
7158   ASSERT(args.length() == 2);
7159
7160   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7161   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7162   if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
7163   if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
7164   if (x == y) return Smi::FromInt(EQUAL);
7165   Object* result;
7166   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7167     result = Smi::FromInt(EQUAL);
7168   } else {
7169     result = Smi::FromInt(NOT_EQUAL);
7170   }
7171   return result;
7172 }
7173
7174
7175 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7176   NoHandleAllocation ha;
7177   ASSERT(args.length() == 2);
7178
7179   CONVERT_ARG_CHECKED(String, x, 0);
7180   CONVERT_ARG_CHECKED(String, y, 1);
7181
7182   bool not_equal = !x->Equals(y);
7183   // This is slightly convoluted because the value that signifies
7184   // equality is 0 and inequality is 1 so we have to negate the result
7185   // from String::Equals.
7186   ASSERT(not_equal == 0 || not_equal == 1);
7187   STATIC_CHECK(EQUAL == 0);
7188   STATIC_CHECK(NOT_EQUAL == 1);
7189   return Smi::FromInt(not_equal);
7190 }
7191
7192
7193 RUNTIME_FUNCTION(MaybeObject*, Runtime_UserObjectEquals) {
7194   NoHandleAllocation ha;
7195   ASSERT(args.length() == 2);
7196
7197   CONVERT_ARG_CHECKED(JSObject, lhs, 1);
7198   CONVERT_ARG_CHECKED(JSObject, rhs, 0);
7199
7200   bool result;
7201
7202   v8::UserObjectComparisonCallback callback = isolate->UserObjectComparisonCallback();
7203   if (callback) {
7204       HandleScope scope(isolate);
7205       Handle<JSObject> lhs_handle(lhs);
7206       Handle<JSObject> rhs_handle(rhs);
7207       result = callback(v8::Utils::ToLocal(lhs_handle), v8::Utils::ToLocal(rhs_handle));
7208   } else {
7209       result = (lhs == rhs);
7210   }
7211
7212   return Smi::FromInt(result?0:1);
7213 }
7214
7215
7216 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7217   NoHandleAllocation ha;
7218   ASSERT(args.length() == 3);
7219
7220   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7221   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7222   if (isnan(x) || isnan(y)) return args[2];
7223   if (x == y) return Smi::FromInt(EQUAL);
7224   if (isless(x, y)) return Smi::FromInt(LESS);
7225   return Smi::FromInt(GREATER);
7226 }
7227
7228
7229 // Compare two Smis as if they were converted to strings and then
7230 // compared lexicographically.
7231 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7232   NoHandleAllocation ha;
7233   ASSERT(args.length() == 2);
7234   CONVERT_SMI_ARG_CHECKED(x_value, 0);
7235   CONVERT_SMI_ARG_CHECKED(y_value, 1);
7236
7237   // If the integers are equal so are the string representations.
7238   if (x_value == y_value) return Smi::FromInt(EQUAL);
7239
7240   // If one of the integers is zero the normal integer order is the
7241   // same as the lexicographic order of the string representations.
7242   if (x_value == 0 || y_value == 0)
7243     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7244
7245   // If only one of the integers is negative the negative number is
7246   // smallest because the char code of '-' is less than the char code
7247   // of any digit.  Otherwise, we make both values positive.
7248
7249   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7250   // architectures using 32-bit Smis.
7251   uint32_t x_scaled = x_value;
7252   uint32_t y_scaled = y_value;
7253   if (x_value < 0 || y_value < 0) {
7254     if (y_value >= 0) return Smi::FromInt(LESS);
7255     if (x_value >= 0) return Smi::FromInt(GREATER);
7256     x_scaled = -x_value;
7257     y_scaled = -y_value;
7258   }
7259
7260   static const uint32_t kPowersOf10[] = {
7261     1, 10, 100, 1000, 10*1000, 100*1000,
7262     1000*1000, 10*1000*1000, 100*1000*1000,
7263     1000*1000*1000
7264   };
7265
7266   // If the integers have the same number of decimal digits they can be
7267   // compared directly as the numeric order is the same as the
7268   // lexicographic order.  If one integer has fewer digits, it is scaled
7269   // by some power of 10 to have the same number of digits as the longer
7270   // integer.  If the scaled integers are equal it means the shorter
7271   // integer comes first in the lexicographic order.
7272
7273   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7274   int x_log2 = IntegerLog2(x_scaled);
7275   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7276   x_log10 -= x_scaled < kPowersOf10[x_log10];
7277
7278   int y_log2 = IntegerLog2(y_scaled);
7279   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7280   y_log10 -= y_scaled < kPowersOf10[y_log10];
7281
7282   int tie = EQUAL;
7283
7284   if (x_log10 < y_log10) {
7285     // X has fewer digits.  We would like to simply scale up X but that
7286     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7287     // be scaled up to 9_000_000_000. So we scale up by the next
7288     // smallest power and scale down Y to drop one digit. It is OK to
7289     // drop one digit from the longer integer since the final digit is
7290     // past the length of the shorter integer.
7291     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7292     y_scaled /= 10;
7293     tie = LESS;
7294   } else if (y_log10 < x_log10) {
7295     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7296     x_scaled /= 10;
7297     tie = GREATER;
7298   }
7299
7300   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7301   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7302   return Smi::FromInt(tie);
7303 }
7304
7305
7306 static Object* StringInputBufferCompare(RuntimeState* state,
7307                                         String* x,
7308                                         String* y) {
7309   StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
7310   StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
7311   bufx.Reset(x);
7312   bufy.Reset(y);
7313   while (bufx.has_more() && bufy.has_more()) {
7314     int d = bufx.GetNext() - bufy.GetNext();
7315     if (d < 0) return Smi::FromInt(LESS);
7316     else if (d > 0) return Smi::FromInt(GREATER);
7317   }
7318
7319   // x is (non-trivial) prefix of y:
7320   if (bufy.has_more()) return Smi::FromInt(LESS);
7321   // y is prefix of x:
7322   return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
7323 }
7324
7325
7326 static Object* FlatStringCompare(String* x, String* y) {
7327   ASSERT(x->IsFlat());
7328   ASSERT(y->IsFlat());
7329   Object* equal_prefix_result = Smi::FromInt(EQUAL);
7330   int prefix_length = x->length();
7331   if (y->length() < prefix_length) {
7332     prefix_length = y->length();
7333     equal_prefix_result = Smi::FromInt(GREATER);
7334   } else if (y->length() > prefix_length) {
7335     equal_prefix_result = Smi::FromInt(LESS);
7336   }
7337   int r;
7338   String::FlatContent x_content = x->GetFlatContent();
7339   String::FlatContent y_content = y->GetFlatContent();
7340   if (x_content.IsAscii()) {
7341     Vector<const char> x_chars = x_content.ToAsciiVector();
7342     if (y_content.IsAscii()) {
7343       Vector<const char> y_chars = y_content.ToAsciiVector();
7344       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7345     } else {
7346       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7347       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7348     }
7349   } else {
7350     Vector<const uc16> x_chars = x_content.ToUC16Vector();
7351     if (y_content.IsAscii()) {
7352       Vector<const char> y_chars = y_content.ToAsciiVector();
7353       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7354     } else {
7355       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7356       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7357     }
7358   }
7359   Object* result;
7360   if (r == 0) {
7361     result = equal_prefix_result;
7362   } else {
7363     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7364   }
7365   ASSERT(result ==
7366       StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y));
7367   return result;
7368 }
7369
7370
7371 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7372   NoHandleAllocation ha;
7373   ASSERT(args.length() == 2);
7374
7375   CONVERT_ARG_CHECKED(String, x, 0);
7376   CONVERT_ARG_CHECKED(String, y, 1);
7377
7378   isolate->counters()->string_compare_runtime()->Increment();
7379
7380   // A few fast case tests before we flatten.
7381   if (x == y) return Smi::FromInt(EQUAL);
7382   if (y->length() == 0) {
7383     if (x->length() == 0) return Smi::FromInt(EQUAL);
7384     return Smi::FromInt(GREATER);
7385   } else if (x->length() == 0) {
7386     return Smi::FromInt(LESS);
7387   }
7388
7389   int d = x->Get(0) - y->Get(0);
7390   if (d < 0) return Smi::FromInt(LESS);
7391   else if (d > 0) return Smi::FromInt(GREATER);
7392
7393   Object* obj;
7394   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7395     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7396   }
7397   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7398     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7399   }
7400
7401   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7402       : StringInputBufferCompare(isolate->runtime_state(), x, y);
7403 }
7404
7405
7406 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7407   NoHandleAllocation ha;
7408   ASSERT(args.length() == 1);
7409   isolate->counters()->math_acos()->Increment();
7410
7411   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7412   return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7413 }
7414
7415
7416 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7417   NoHandleAllocation ha;
7418   ASSERT(args.length() == 1);
7419   isolate->counters()->math_asin()->Increment();
7420
7421   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7422   return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7423 }
7424
7425
7426 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7427   NoHandleAllocation ha;
7428   ASSERT(args.length() == 1);
7429   isolate->counters()->math_atan()->Increment();
7430
7431   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7432   return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7433 }
7434
7435
7436 static const double kPiDividedBy4 = 0.78539816339744830962;
7437
7438
7439 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7440   NoHandleAllocation ha;
7441   ASSERT(args.length() == 2);
7442   isolate->counters()->math_atan2()->Increment();
7443
7444   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7445   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7446   double result;
7447   if (isinf(x) && isinf(y)) {
7448     // Make sure that the result in case of two infinite arguments
7449     // is a multiple of Pi / 4. The sign of the result is determined
7450     // by the first argument (x) and the sign of the second argument
7451     // determines the multiplier: one or three.
7452     int multiplier = (x < 0) ? -1 : 1;
7453     if (y < 0) multiplier *= 3;
7454     result = multiplier * kPiDividedBy4;
7455   } else {
7456     result = atan2(x, y);
7457   }
7458   return isolate->heap()->AllocateHeapNumber(result);
7459 }
7460
7461
7462 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7463   NoHandleAllocation ha;
7464   ASSERT(args.length() == 1);
7465   isolate->counters()->math_ceil()->Increment();
7466
7467   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7468   return isolate->heap()->NumberFromDouble(ceiling(x));
7469 }
7470
7471
7472 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7473   NoHandleAllocation ha;
7474   ASSERT(args.length() == 1);
7475   isolate->counters()->math_cos()->Increment();
7476
7477   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7478   return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7479 }
7480
7481
7482 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7483   NoHandleAllocation ha;
7484   ASSERT(args.length() == 1);
7485   isolate->counters()->math_exp()->Increment();
7486
7487   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7488   return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x);
7489 }
7490
7491
7492 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7493   NoHandleAllocation ha;
7494   ASSERT(args.length() == 1);
7495   isolate->counters()->math_floor()->Increment();
7496
7497   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7498   return isolate->heap()->NumberFromDouble(floor(x));
7499 }
7500
7501
7502 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7503   NoHandleAllocation ha;
7504   ASSERT(args.length() == 1);
7505   isolate->counters()->math_log()->Increment();
7506
7507   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7508   return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7509 }
7510
7511 // Slow version of Math.pow.  We check for fast paths for special cases.
7512 // Used if SSE2/VFP3 is not available.
7513 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7514   NoHandleAllocation ha;
7515   ASSERT(args.length() == 2);
7516   isolate->counters()->math_pow()->Increment();
7517
7518   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7519
7520   // If the second argument is a smi, it is much faster to call the
7521   // custom powi() function than the generic pow().
7522   if (args[1]->IsSmi()) {
7523     int y = args.smi_at(1);
7524     return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7525   }
7526
7527   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7528   int y_int = static_cast<int>(y);
7529   double result;
7530   if (y == y_int) {
7531     result = power_double_int(x, y_int);  // Returns 1 if exponent is 0.
7532   } else  if (y == 0.5) {
7533     result = (isinf(x)) ? V8_INFINITY
7534                         : fast_sqrt(x + 0.0);  // Convert -0 to +0.
7535   } else if (y == -0.5) {
7536     result = (isinf(x)) ? 0
7537                         : 1.0 / fast_sqrt(x + 0.0);  // Convert -0 to +0.
7538   } else {
7539     result = power_double_double(x, y);
7540   }
7541   if (isnan(result)) return isolate->heap()->nan_value();
7542   return isolate->heap()->AllocateHeapNumber(result);
7543 }
7544
7545 // Fast version of Math.pow if we know that y is not an integer and y is not
7546 // -0.5 or 0.5.  Used as slow case from full codegen.
7547 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7548   NoHandleAllocation ha;
7549   ASSERT(args.length() == 2);
7550   isolate->counters()->math_pow()->Increment();
7551
7552   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7553   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7554   if (y == 0) {
7555     return Smi::FromInt(1);
7556   } else {
7557     double result = power_double_double(x, y);
7558     if (isnan(result)) return isolate->heap()->nan_value();
7559     return isolate->heap()->AllocateHeapNumber(result);
7560   }
7561 }
7562
7563
7564 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7565   NoHandleAllocation ha;
7566   ASSERT(args.length() == 1);
7567   isolate->counters()->math_round()->Increment();
7568
7569   if (!args[0]->IsHeapNumber()) {
7570     // Must be smi. Return the argument unchanged for all the other types
7571     // to make fuzz-natives test happy.
7572     return args[0];
7573   }
7574
7575   HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7576
7577   double value = number->value();
7578   int exponent = number->get_exponent();
7579   int sign = number->get_sign();
7580
7581   if (exponent < -1) {
7582     // Number in range ]-0.5..0.5[. These always round to +/-zero.
7583     if (sign) return isolate->heap()->minus_zero_value();
7584     return Smi::FromInt(0);
7585   }
7586
7587   // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7588   // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7589   // argument holds for 32-bit smis).
7590   if (!sign && exponent < kSmiValueSize - 2) {
7591     return Smi::FromInt(static_cast<int>(value + 0.5));
7592   }
7593
7594   // If the magnitude is big enough, there's no place for fraction part. If we
7595   // try to add 0.5 to this number, 1.0 will be added instead.
7596   if (exponent >= 52) {
7597     return number;
7598   }
7599
7600   if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7601
7602   // Do not call NumberFromDouble() to avoid extra checks.
7603   return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7604 }
7605
7606
7607 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7608   NoHandleAllocation ha;
7609   ASSERT(args.length() == 1);
7610   isolate->counters()->math_sin()->Increment();
7611
7612   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7613   return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7614 }
7615
7616
7617 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7618   NoHandleAllocation ha;
7619   ASSERT(args.length() == 1);
7620   isolate->counters()->math_sqrt()->Increment();
7621
7622   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7623   return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7624 }
7625
7626
7627 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7628   NoHandleAllocation ha;
7629   ASSERT(args.length() == 1);
7630   isolate->counters()->math_tan()->Increment();
7631
7632   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7633   return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7634 }
7635
7636
7637 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7638   NoHandleAllocation ha;
7639   ASSERT(args.length() == 2);
7640
7641   CONVERT_SMI_ARG_CHECKED(year, 0);
7642   CONVERT_SMI_ARG_CHECKED(month, 1);
7643
7644   return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7645 }
7646
7647
7648 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7649   HandleScope scope(isolate);
7650   ASSERT(args.length() == 3);
7651
7652   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7653   CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7654   CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7655
7656   DateCache* date_cache = isolate->date_cache();
7657
7658   Object* value = NULL;
7659   bool is_value_nan = false;
7660   if (isnan(time)) {
7661     value = isolate->heap()->nan_value();
7662     is_value_nan = true;
7663   } else if (!is_utc &&
7664              (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7665               time > DateCache::kMaxTimeBeforeUTCInMs)) {
7666     value = isolate->heap()->nan_value();
7667     is_value_nan = true;
7668   } else {
7669     time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7670     if (time < -DateCache::kMaxTimeInMs ||
7671         time > DateCache::kMaxTimeInMs) {
7672       value = isolate->heap()->nan_value();
7673       is_value_nan = true;
7674     } else  {
7675       MaybeObject* maybe_result =
7676           isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7677       if (!maybe_result->ToObject(&value)) return maybe_result;
7678     }
7679   }
7680   date->SetValue(value, is_value_nan);
7681   return value;
7682 }
7683
7684
7685 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7686   HandleScope scope(isolate);
7687   ASSERT(args.length() == 3);
7688
7689   Handle<JSFunction> callee = args.at<JSFunction>(0);
7690   Object** parameters = reinterpret_cast<Object**>(args[1]);
7691   const int argument_count = Smi::cast(args[2])->value();
7692
7693   Handle<JSObject> result =
7694       isolate->factory()->NewArgumentsObject(callee, argument_count);
7695   // Allocate the elements if needed.
7696   int parameter_count = callee->shared()->formal_parameter_count();
7697   if (argument_count > 0) {
7698     if (parameter_count > 0) {
7699       int mapped_count = Min(argument_count, parameter_count);
7700       Handle<FixedArray> parameter_map =
7701           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7702       parameter_map->set_map(
7703           isolate->heap()->non_strict_arguments_elements_map());
7704
7705       Handle<Map> old_map(result->map());
7706       Handle<Map> new_map =
7707           isolate->factory()->CopyMapDropTransitions(old_map);
7708       new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7709
7710       result->set_map(*new_map);
7711       result->set_elements(*parameter_map);
7712
7713       // Store the context and the arguments array at the beginning of the
7714       // parameter map.
7715       Handle<Context> context(isolate->context());
7716       Handle<FixedArray> arguments =
7717           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7718       parameter_map->set(0, *context);
7719       parameter_map->set(1, *arguments);
7720
7721       // Loop over the actual parameters backwards.
7722       int index = argument_count - 1;
7723       while (index >= mapped_count) {
7724         // These go directly in the arguments array and have no
7725         // corresponding slot in the parameter map.
7726         arguments->set(index, *(parameters - index - 1));
7727         --index;
7728       }
7729
7730       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7731       while (index >= 0) {
7732         // Detect duplicate names to the right in the parameter list.
7733         Handle<String> name(scope_info->ParameterName(index));
7734         int context_local_count = scope_info->ContextLocalCount();
7735         bool duplicate = false;
7736         for (int j = index + 1; j < parameter_count; ++j) {
7737           if (scope_info->ParameterName(j) == *name) {
7738             duplicate = true;
7739             break;
7740           }
7741         }
7742
7743         if (duplicate) {
7744           // This goes directly in the arguments array with a hole in the
7745           // parameter map.
7746           arguments->set(index, *(parameters - index - 1));
7747           parameter_map->set_the_hole(index + 2);
7748         } else {
7749           // The context index goes in the parameter map with a hole in the
7750           // arguments array.
7751           int context_index = -1;
7752           for (int j = 0; j < context_local_count; ++j) {
7753             if (scope_info->ContextLocalName(j) == *name) {
7754               context_index = j;
7755               break;
7756             }
7757           }
7758           ASSERT(context_index >= 0);
7759           arguments->set_the_hole(index);
7760           parameter_map->set(index + 2, Smi::FromInt(
7761               Context::MIN_CONTEXT_SLOTS + context_index));
7762         }
7763
7764         --index;
7765       }
7766     } else {
7767       // If there is no aliasing, the arguments object elements are not
7768       // special in any way.
7769       Handle<FixedArray> elements =
7770           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7771       result->set_elements(*elements);
7772       for (int i = 0; i < argument_count; ++i) {
7773         elements->set(i, *(parameters - i - 1));
7774       }
7775     }
7776   }
7777   return *result;
7778 }
7779
7780
7781 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7782   NoHandleAllocation ha;
7783   ASSERT(args.length() == 3);
7784
7785   JSFunction* callee = JSFunction::cast(args[0]);
7786   Object** parameters = reinterpret_cast<Object**>(args[1]);
7787   const int length = args.smi_at(2);
7788
7789   Object* result;
7790   { MaybeObject* maybe_result =
7791         isolate->heap()->AllocateArgumentsObject(callee, length);
7792     if (!maybe_result->ToObject(&result)) return maybe_result;
7793   }
7794   // Allocate the elements if needed.
7795   if (length > 0) {
7796     // Allocate the fixed array.
7797     Object* obj;
7798     { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7799       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7800     }
7801
7802     AssertNoAllocation no_gc;
7803     FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7804     array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
7805     array->set_length(length);
7806
7807     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7808     for (int i = 0; i < length; i++) {
7809       array->set(i, *--parameters, mode);
7810     }
7811     JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7812   }
7813   return result;
7814 }
7815
7816
7817 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7818   HandleScope scope(isolate);
7819   ASSERT(args.length() == 3);
7820   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
7821   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
7822   CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
7823
7824   // The caller ensures that we pretenure closures that are assigned
7825   // directly to properties.
7826   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7827   Handle<JSFunction> result =
7828       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7829                                                             context,
7830                                                             pretenure_flag);
7831   return *result;
7832 }
7833
7834
7835 // Find the arguments of the JavaScript function invocation that called
7836 // into C++ code. Collect these in a newly allocated array of handles (possibly
7837 // prefixed by a number of empty handles).
7838 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
7839     int prefix_argc,
7840     int* total_argc) {
7841   // Find frame containing arguments passed to the caller.
7842   JavaScriptFrameIterator it;
7843   JavaScriptFrame* frame = it.frame();
7844   List<JSFunction*> functions(2);
7845   frame->GetFunctions(&functions);
7846   if (functions.length() > 1) {
7847     int inlined_jsframe_index = functions.length() - 1;
7848     JSFunction* inlined_function = functions[inlined_jsframe_index];
7849     Vector<SlotRef> args_slots =
7850         SlotRef::ComputeSlotMappingForArguments(
7851             frame,
7852             inlined_jsframe_index,
7853             inlined_function->shared()->formal_parameter_count());
7854
7855     int args_count = args_slots.length();
7856
7857     *total_argc = prefix_argc + args_count;
7858     SmartArrayPointer<Handle<Object> > param_data(
7859         NewArray<Handle<Object> >(*total_argc));
7860     for (int i = 0; i < args_count; i++) {
7861       Handle<Object> val = args_slots[i].GetValue();
7862       param_data[prefix_argc + i] = val;
7863     }
7864
7865     args_slots.Dispose();
7866
7867     return param_data;
7868   } else {
7869     it.AdvanceToArgumentsFrame();
7870     frame = it.frame();
7871     int args_count = frame->ComputeParametersCount();
7872
7873     *total_argc = prefix_argc + args_count;
7874     SmartArrayPointer<Handle<Object> > param_data(
7875         NewArray<Handle<Object> >(*total_argc));
7876     for (int i = 0; i < args_count; i++) {
7877       Handle<Object> val = Handle<Object>(frame->GetParameter(i));
7878       param_data[prefix_argc + i] = val;
7879     }
7880     return param_data;
7881   }
7882 }
7883
7884
7885 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
7886   HandleScope scope(isolate);
7887   ASSERT(args.length() == 4);
7888   CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
7889   RUNTIME_ASSERT(args[3]->IsNumber());
7890   Handle<Object> bindee = args.at<Object>(1);
7891
7892   // TODO(lrn): Create bound function in C++ code from premade shared info.
7893   bound_function->shared()->set_bound(true);
7894   // Get all arguments of calling function (Function.prototype.bind).
7895   int argc = 0;
7896   SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(0, &argc);
7897   // Don't count the this-arg.
7898   if (argc > 0) {
7899     ASSERT(*arguments[0] == args[2]);
7900     argc--;
7901   } else {
7902     ASSERT(args[2]->IsUndefined());
7903   }
7904   // Initialize array of bindings (function, this, and any existing arguments
7905   // if the function was already bound).
7906   Handle<FixedArray> new_bindings;
7907   int i;
7908   if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
7909     Handle<FixedArray> old_bindings(
7910         JSFunction::cast(*bindee)->function_bindings());
7911     new_bindings =
7912         isolate->factory()->NewFixedArray(old_bindings->length() + argc);
7913     bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex));
7914     i = 0;
7915     for (int n = old_bindings->length(); i < n; i++) {
7916       new_bindings->set(i, old_bindings->get(i));
7917     }
7918   } else {
7919     int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
7920     new_bindings = isolate->factory()->NewFixedArray(array_size);
7921     new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
7922     new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
7923     i = 2;
7924   }
7925   // Copy arguments, skipping the first which is "this_arg".
7926   for (int j = 0; j < argc; j++, i++) {
7927     new_bindings->set(i, *arguments[j + 1]);
7928   }
7929   new_bindings->set_map_no_write_barrier(
7930       isolate->heap()->fixed_cow_array_map());
7931   bound_function->set_function_bindings(*new_bindings);
7932
7933   // Update length.
7934   Handle<String> length_symbol = isolate->factory()->length_symbol();
7935   Handle<Object> new_length(args.at<Object>(3));
7936   PropertyAttributes attr =
7937       static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
7938   ForceSetProperty(bound_function, length_symbol, new_length, attr);
7939   return *bound_function;
7940 }
7941
7942
7943 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
7944   HandleScope handles(isolate);
7945   ASSERT(args.length() == 1);
7946   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
7947   if (callable->IsJSFunction()) {
7948     Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
7949     if (function->shared()->bound()) {
7950       Handle<FixedArray> bindings(function->function_bindings());
7951       ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
7952       return *isolate->factory()->NewJSArrayWithElements(bindings);
7953     }
7954   }
7955   return isolate->heap()->undefined_value();
7956 }
7957
7958
7959 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
7960   HandleScope scope(isolate);
7961   ASSERT(args.length() == 1);
7962   // First argument is a function to use as a constructor.
7963   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
7964   RUNTIME_ASSERT(function->shared()->bound());
7965
7966   // The argument is a bound function. Extract its bound arguments
7967   // and callable.
7968   Handle<FixedArray> bound_args =
7969       Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
7970   int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
7971   Handle<Object> bound_function(
7972       JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)));
7973   ASSERT(!bound_function->IsJSFunction() ||
7974          !Handle<JSFunction>::cast(bound_function)->shared()->bound());
7975
7976   int total_argc = 0;
7977   SmartArrayPointer<Handle<Object> > param_data =
7978       GetCallerArguments(bound_argc, &total_argc);
7979   for (int i = 0; i < bound_argc; i++) {
7980     param_data[i] = Handle<Object>(bound_args->get(
7981         JSFunction::kBoundArgumentsStartIndex + i));
7982   }
7983
7984   if (!bound_function->IsJSFunction()) {
7985     bool exception_thrown;
7986     bound_function = Execution::TryGetConstructorDelegate(bound_function,
7987                                                           &exception_thrown);
7988     if (exception_thrown) return Failure::Exception();
7989   }
7990   ASSERT(bound_function->IsJSFunction());
7991
7992   bool exception = false;
7993   Handle<Object> result =
7994       Execution::New(Handle<JSFunction>::cast(bound_function),
7995                      total_argc, *param_data, &exception);
7996   if (exception) {
7997     return Failure::Exception();
7998   }
7999   ASSERT(!result.is_null());
8000   return *result;
8001 }
8002
8003
8004 static void TrySettingInlineConstructStub(Isolate* isolate,
8005                                           Handle<JSFunction> function) {
8006   Handle<Object> prototype = isolate->factory()->null_value();
8007   if (function->has_instance_prototype()) {
8008     prototype = Handle<Object>(function->instance_prototype(), isolate);
8009   }
8010   if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
8011     ConstructStubCompiler compiler(isolate);
8012     Handle<Code> code = compiler.CompileConstructStub(function);
8013     function->shared()->set_construct_stub(*code);
8014   }
8015 }
8016
8017
8018 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
8019   HandleScope scope(isolate);
8020   ASSERT(args.length() == 1);
8021
8022   Handle<Object> constructor = args.at<Object>(0);
8023
8024   // If the constructor isn't a proper function we throw a type error.
8025   if (!constructor->IsJSFunction()) {
8026     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8027     Handle<Object> type_error =
8028         isolate->factory()->NewTypeError("not_constructor", arguments);
8029     return isolate->Throw(*type_error);
8030   }
8031
8032   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8033
8034   // If function should not have prototype, construction is not allowed. In this
8035   // case generated code bailouts here, since function has no initial_map.
8036   if (!function->should_have_prototype() && !function->shared()->bound()) {
8037     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8038     Handle<Object> type_error =
8039         isolate->factory()->NewTypeError("not_constructor", arguments);
8040     return isolate->Throw(*type_error);
8041   }
8042
8043 #ifdef ENABLE_DEBUGGER_SUPPORT
8044   Debug* debug = isolate->debug();
8045   // Handle stepping into constructors if step into is active.
8046   if (debug->StepInActive()) {
8047     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8048   }
8049 #endif
8050
8051   if (function->has_initial_map()) {
8052     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8053       // The 'Function' function ignores the receiver object when
8054       // called using 'new' and creates a new JSFunction object that
8055       // is returned.  The receiver object is only used for error
8056       // reporting if an error occurs when constructing the new
8057       // JSFunction. FACTORY->NewJSObject() should not be used to
8058       // allocate JSFunctions since it does not properly initialize
8059       // the shared part of the function. Since the receiver is
8060       // ignored anyway, we use the global object as the receiver
8061       // instead of a new JSFunction object. This way, errors are
8062       // reported the same way whether or not 'Function' is called
8063       // using 'new'.
8064       return isolate->context()->global();
8065     }
8066   }
8067
8068   // The function should be compiled for the optimization hints to be
8069   // available. We cannot use EnsureCompiled because that forces a
8070   // compilation through the shared function info which makes it
8071   // impossible for us to optimize.
8072   if (!function->is_compiled()) {
8073     JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
8074   }
8075
8076   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8077   if (!function->has_initial_map() &&
8078       shared->IsInobjectSlackTrackingInProgress()) {
8079     // The tracking is already in progress for another function. We can only
8080     // track one initial_map at a time, so we force the completion before the
8081     // function is called as a constructor for the first time.
8082     shared->CompleteInobjectSlackTracking();
8083   }
8084
8085   bool first_allocation = !shared->live_objects_may_exist();
8086   Handle<JSObject> result = isolate->factory()->NewJSObject(function);
8087   RETURN_IF_EMPTY_HANDLE(isolate, result);
8088   // Delay setting the stub if inobject slack tracking is in progress.
8089   if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
8090     TrySettingInlineConstructStub(isolate, function);
8091   }
8092
8093   isolate->counters()->constructed_objects()->Increment();
8094   isolate->counters()->constructed_objects_runtime()->Increment();
8095
8096   return *result;
8097 }
8098
8099
8100 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8101   HandleScope scope(isolate);
8102   ASSERT(args.length() == 1);
8103
8104   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8105   function->shared()->CompleteInobjectSlackTracking();
8106   TrySettingInlineConstructStub(isolate, function);
8107
8108   return isolate->heap()->undefined_value();
8109 }
8110
8111
8112 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8113   HandleScope scope(isolate);
8114   ASSERT(args.length() == 1);
8115
8116   Handle<JSFunction> function = args.at<JSFunction>(0);
8117 #ifdef DEBUG
8118   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8119     PrintF("[lazy: ");
8120     function->PrintName();
8121     PrintF("]\n");
8122   }
8123 #endif
8124
8125   // Compile the target function.
8126   ASSERT(!function->is_compiled());
8127   if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8128     return Failure::Exception();
8129   }
8130
8131   // All done. Return the compiled code.
8132   ASSERT(function->is_compiled());
8133   return function->code();
8134 }
8135
8136
8137 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8138   HandleScope scope(isolate);
8139   ASSERT(args.length() == 1);
8140   Handle<JSFunction> function = args.at<JSFunction>(0);
8141
8142   // If the function is not compiled ignore the lazy
8143   // recompilation. This can happen if the debugger is activated and
8144   // the function is returned to the not compiled state.
8145   if (!function->shared()->is_compiled()) {
8146     function->ReplaceCode(function->shared()->code());
8147     return function->code();
8148   }
8149
8150   // If the function is not optimizable or debugger is active continue using the
8151   // code from the full compiler.
8152   if (!function->shared()->code()->optimizable() ||
8153       isolate->DebuggerHasBreakPoints()) {
8154     if (FLAG_trace_opt) {
8155       PrintF("[failed to optimize ");
8156       function->PrintName();
8157       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8158           function->shared()->code()->optimizable() ? "T" : "F",
8159           isolate->DebuggerHasBreakPoints() ? "T" : "F");
8160     }
8161     function->ReplaceCode(function->shared()->code());
8162     return function->code();
8163   }
8164   function->shared()->code()->set_profiler_ticks(0);
8165   if (JSFunction::CompileOptimized(function,
8166                                    AstNode::kNoNumber,
8167                                    CLEAR_EXCEPTION)) {
8168     return function->code();
8169   }
8170   if (FLAG_trace_opt) {
8171     PrintF("[failed to optimize ");
8172     function->PrintName();
8173     PrintF(": optimized compilation failed]\n");
8174   }
8175   function->ReplaceCode(function->shared()->code());
8176   return function->code();
8177 }
8178
8179
8180 class ActivationsFinder : public ThreadVisitor {
8181  public:
8182   explicit ActivationsFinder(JSFunction* function)
8183       : function_(function), has_activations_(false) {}
8184
8185   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8186     if (has_activations_) return;
8187
8188     for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
8189       JavaScriptFrame* frame = it.frame();
8190       if (frame->is_optimized() && frame->function() == function_) {
8191         has_activations_ = true;
8192         return;
8193       }
8194     }
8195   }
8196
8197   bool has_activations() { return has_activations_; }
8198
8199  private:
8200   JSFunction* function_;
8201   bool has_activations_;
8202 };
8203
8204
8205 static void MaterializeArgumentsObjectInFrame(Isolate* isolate,
8206                                               JavaScriptFrame* frame) {
8207   Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8208   Handle<Object> arguments;
8209   for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
8210     if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) {
8211       if (arguments.is_null()) {
8212         // FunctionGetArguments can't throw an exception, so cast away the
8213         // doubt with an assert.
8214         arguments = Handle<Object>(
8215             Accessors::FunctionGetArguments(*function,
8216                                             NULL)->ToObjectUnchecked());
8217         ASSERT(*arguments != isolate->heap()->null_value());
8218         ASSERT(*arguments != isolate->heap()->undefined_value());
8219       }
8220       frame->SetExpression(i, *arguments);
8221       if (FLAG_trace_deopt) {
8222         PrintF("Materializing arguments object for frame %p - %p: %p ",
8223                reinterpret_cast<void*>(frame->sp()),
8224                reinterpret_cast<void*>(frame->fp()),
8225                reinterpret_cast<void*>(*arguments));
8226         arguments->ShortPrint();
8227         PrintF("\n");
8228       }
8229     }
8230   }
8231 }
8232
8233
8234 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8235   HandleScope scope(isolate);
8236   ASSERT(args.length() == 1);
8237   RUNTIME_ASSERT(args[0]->IsSmi());
8238   Deoptimizer::BailoutType type =
8239       static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8240   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8241   ASSERT(isolate->heap()->IsAllocationAllowed());
8242   int jsframes = deoptimizer->jsframe_count();
8243
8244   deoptimizer->MaterializeHeapNumbers();
8245   delete deoptimizer;
8246
8247   JavaScriptFrameIterator it(isolate);
8248   for (int i = 0; i < jsframes - 1; i++) {
8249     MaterializeArgumentsObjectInFrame(isolate, it.frame());
8250     it.Advance();
8251   }
8252
8253   JavaScriptFrame* frame = it.frame();
8254   RUNTIME_ASSERT(frame->function()->IsJSFunction());
8255   Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8256   MaterializeArgumentsObjectInFrame(isolate, frame);
8257
8258   if (type == Deoptimizer::EAGER) {
8259     RUNTIME_ASSERT(function->IsOptimized());
8260   }
8261
8262   // Avoid doing too much work when running with --always-opt and keep
8263   // the optimized code around.
8264   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8265     return isolate->heap()->undefined_value();
8266   }
8267
8268   // Find other optimized activations of the function.
8269   bool has_other_activations = false;
8270   while (!it.done()) {
8271     JavaScriptFrame* frame = it.frame();
8272     if (frame->is_optimized() && frame->function() == *function) {
8273       has_other_activations = true;
8274       break;
8275     }
8276     it.Advance();
8277   }
8278
8279   if (!has_other_activations) {
8280     ActivationsFinder activations_finder(*function);
8281     isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8282     has_other_activations = activations_finder.has_activations();
8283   }
8284
8285   if (!has_other_activations) {
8286     if (FLAG_trace_deopt) {
8287       PrintF("[removing optimized code for: ");
8288       function->PrintName();
8289       PrintF("]\n");
8290     }
8291     function->ReplaceCode(function->shared()->code());
8292   } else {
8293     Deoptimizer::DeoptimizeFunction(*function);
8294   }
8295   return isolate->heap()->undefined_value();
8296 }
8297
8298
8299 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
8300   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8301   delete deoptimizer;
8302   return isolate->heap()->undefined_value();
8303 }
8304
8305
8306 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8307   HandleScope scope(isolate);
8308   ASSERT(args.length() == 1);
8309   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8310   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8311
8312   Deoptimizer::DeoptimizeFunction(*function);
8313
8314   return isolate->heap()->undefined_value();
8315 }
8316
8317
8318 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8319   HandleScope scope(isolate);
8320   ASSERT(args.length() == 1);
8321   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8322   Code* unoptimized = function->shared()->code();
8323   if (unoptimized->kind() == Code::FUNCTION) {
8324     unoptimized->ClearInlineCaches();
8325     unoptimized->ClearTypeFeedbackCells(isolate->heap());
8326   }
8327   return isolate->heap()->undefined_value();
8328 }
8329
8330
8331 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8332 #if defined(USE_SIMULATOR)
8333   return isolate->heap()->true_value();
8334 #else
8335   return isolate->heap()->false_value();
8336 #endif
8337 }
8338
8339
8340 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8341   HandleScope scope(isolate);
8342   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8343   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8344
8345   if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8346   function->MarkForLazyRecompilation();
8347
8348   Code* unoptimized = function->shared()->code();
8349   if (args.length() == 2 &&
8350       unoptimized->kind() == Code::FUNCTION) {
8351     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8352     CHECK(type->IsEqualTo(CStrVector("osr")));
8353     isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8354     unoptimized->set_allow_osr_at_loop_nesting_level(
8355         Code::kMaxLoopNestingMarker);
8356   }
8357
8358   return isolate->heap()->undefined_value();
8359 }
8360
8361
8362 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8363   HandleScope scope(isolate);
8364   ASSERT(args.length() == 1);
8365   // The least significant bit (after untagging) indicates whether the
8366   // function is currently optimized, regardless of reason.
8367   if (!V8::UseCrankshaft()) {
8368     return Smi::FromInt(4);  // 4 == "never".
8369   }
8370   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8371   if (FLAG_always_opt) {
8372     // We may have always opt, but that is more best-effort than a real
8373     // promise, so we still say "no" if it is not optimized.
8374     return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8375                                    : Smi::FromInt(2);  // 2 == "no".
8376   }
8377   return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8378                                  : Smi::FromInt(2);  // 2 == "no".
8379 }
8380
8381
8382 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8383   HandleScope scope(isolate);
8384   ASSERT(args.length() == 1);
8385   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8386   return Smi::FromInt(function->shared()->opt_count());
8387 }
8388
8389
8390 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8391   HandleScope scope(isolate);
8392   ASSERT(args.length() == 1);
8393   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8394
8395   // We're not prepared to handle a function with arguments object.
8396   ASSERT(!function->shared()->uses_arguments());
8397
8398   // We have hit a back edge in an unoptimized frame for a function that was
8399   // selected for on-stack replacement.  Find the unoptimized code object.
8400   Handle<Code> unoptimized(function->shared()->code(), isolate);
8401   // Keep track of whether we've succeeded in optimizing.
8402   bool succeeded = unoptimized->optimizable();
8403   if (succeeded) {
8404     // If we are trying to do OSR when there are already optimized
8405     // activations of the function, it means (a) the function is directly or
8406     // indirectly recursive and (b) an optimized invocation has been
8407     // deoptimized so that we are currently in an unoptimized activation.
8408     // Check for optimized activations of this function.
8409     JavaScriptFrameIterator it(isolate);
8410     while (succeeded && !it.done()) {
8411       JavaScriptFrame* frame = it.frame();
8412       succeeded = !frame->is_optimized() || frame->function() != *function;
8413       it.Advance();
8414     }
8415   }
8416
8417   int ast_id = AstNode::kNoNumber;
8418   if (succeeded) {
8419     // The top JS function is this one, the PC is somewhere in the
8420     // unoptimized code.
8421     JavaScriptFrameIterator it(isolate);
8422     JavaScriptFrame* frame = it.frame();
8423     ASSERT(frame->function() == *function);
8424     ASSERT(frame->LookupCode() == *unoptimized);
8425     ASSERT(unoptimized->contains(frame->pc()));
8426
8427     // Use linear search of the unoptimized code's stack check table to find
8428     // the AST id matching the PC.
8429     Address start = unoptimized->instruction_start();
8430     unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start);
8431     Address table_cursor = start + unoptimized->stack_check_table_offset();
8432     uint32_t table_length = Memory::uint32_at(table_cursor);
8433     table_cursor += kIntSize;
8434     for (unsigned i = 0; i < table_length; ++i) {
8435       // Table entries are (AST id, pc offset) pairs.
8436       uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize);
8437       if (pc_offset == target_pc_offset) {
8438         ast_id = static_cast<int>(Memory::uint32_at(table_cursor));
8439         break;
8440       }
8441       table_cursor += 2 * kIntSize;
8442     }
8443     ASSERT(ast_id != AstNode::kNoNumber);
8444     if (FLAG_trace_osr) {
8445       PrintF("[replacing on-stack at AST id %d in ", ast_id);
8446       function->PrintName();
8447       PrintF("]\n");
8448     }
8449
8450     // Try to compile the optimized code.  A true return value from
8451     // CompileOptimized means that compilation succeeded, not necessarily
8452     // that optimization succeeded.
8453     if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
8454         function->IsOptimized()) {
8455       DeoptimizationInputData* data = DeoptimizationInputData::cast(
8456           function->code()->deoptimization_data());
8457       if (data->OsrPcOffset()->value() >= 0) {
8458         if (FLAG_trace_osr) {
8459           PrintF("[on-stack replacement offset %d in optimized code]\n",
8460                data->OsrPcOffset()->value());
8461         }
8462         ASSERT(data->OsrAstId()->value() == ast_id);
8463       } else {
8464         // We may never generate the desired OSR entry if we emit an
8465         // early deoptimize.
8466         succeeded = false;
8467       }
8468     } else {
8469       succeeded = false;
8470     }
8471   }
8472
8473   // Revert to the original stack checks in the original unoptimized code.
8474   if (FLAG_trace_osr) {
8475     PrintF("[restoring original stack checks in ");
8476     function->PrintName();
8477     PrintF("]\n");
8478   }
8479   Handle<Code> check_code;
8480   if (FLAG_count_based_interrupts) {
8481     InterruptStub interrupt_stub;
8482     check_code = interrupt_stub.GetCode();
8483   } else  // NOLINT
8484   {  // NOLINT
8485     StackCheckStub check_stub;
8486     check_code = check_stub.GetCode();
8487   }
8488   Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
8489   Deoptimizer::RevertStackCheckCode(*unoptimized,
8490                                     *check_code,
8491                                     *replacement_code);
8492
8493   // Allow OSR only at nesting level zero again.
8494   unoptimized->set_allow_osr_at_loop_nesting_level(0);
8495
8496   // If the optimization attempt succeeded, return the AST id tagged as a
8497   // smi. This tells the builtin that we need to translate the unoptimized
8498   // frame to an optimized one.
8499   if (succeeded) {
8500     ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
8501     return Smi::FromInt(ast_id);
8502   } else {
8503     if (function->IsMarkedForLazyRecompilation()) {
8504       function->ReplaceCode(function->shared()->code());
8505     }
8506     return Smi::FromInt(-1);
8507   }
8508 }
8509
8510
8511 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8512   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8513   return isolate->heap()->undefined_value();
8514 }
8515
8516
8517 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8518   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8519   return isolate->heap()->nan_value();
8520 }
8521
8522
8523 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8524   HandleScope scope(isolate);
8525   ASSERT(args.length() >= 2);
8526   int argc = args.length() - 2;
8527   CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8528   Object* receiver = args[0];
8529
8530   // If there are too many arguments, allocate argv via malloc.
8531   const int argv_small_size = 10;
8532   Handle<Object> argv_small_buffer[argv_small_size];
8533   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8534   Handle<Object>* argv = argv_small_buffer;
8535   if (argc > argv_small_size) {
8536     argv = new Handle<Object>[argc];
8537     if (argv == NULL) return isolate->StackOverflow();
8538     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8539   }
8540
8541   for (int i = 0; i < argc; ++i) {
8542      MaybeObject* maybe = args[1 + i];
8543      Object* object;
8544      if (!maybe->To<Object>(&object)) return maybe;
8545      argv[i] = Handle<Object>(object);
8546   }
8547
8548   bool threw;
8549   Handle<JSReceiver> hfun(fun);
8550   Handle<Object> hreceiver(receiver);
8551   Handle<Object> result =
8552       Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
8553
8554   if (threw) return Failure::Exception();
8555   return *result;
8556 }
8557
8558
8559 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8560   HandleScope scope(isolate);
8561   ASSERT(args.length() == 5);
8562   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8563   Handle<Object> receiver = args.at<Object>(1);
8564   CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8565   CONVERT_SMI_ARG_CHECKED(offset, 3);
8566   CONVERT_SMI_ARG_CHECKED(argc, 4);
8567   ASSERT(offset >= 0);
8568   ASSERT(argc >= 0);
8569
8570   // If there are too many arguments, allocate argv via malloc.
8571   const int argv_small_size = 10;
8572   Handle<Object> argv_small_buffer[argv_small_size];
8573   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8574   Handle<Object>* argv = argv_small_buffer;
8575   if (argc > argv_small_size) {
8576     argv = new Handle<Object>[argc];
8577     if (argv == NULL) return isolate->StackOverflow();
8578     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8579   }
8580
8581   for (int i = 0; i < argc; ++i) {
8582     argv[i] = Object::GetElement(arguments, offset + i);
8583   }
8584
8585   bool threw;
8586   Handle<Object> result =
8587       Execution::Call(fun, receiver, argc, argv, &threw, true);
8588
8589   if (threw) return Failure::Exception();
8590   return *result;
8591 }
8592
8593
8594 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8595   HandleScope scope(isolate);
8596   ASSERT(args.length() == 1);
8597   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8598   return *Execution::GetFunctionDelegate(args.at<Object>(0));
8599 }
8600
8601
8602 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8603   HandleScope scope(isolate);
8604   ASSERT(args.length() == 1);
8605   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8606   return *Execution::GetConstructorDelegate(args.at<Object>(0));
8607 }
8608
8609
8610 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8611   NoHandleAllocation ha;
8612   ASSERT(args.length() == 1);
8613
8614   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8615   SharedFunctionInfo* shared = function->shared();
8616   // TODO: The QML mode should be checked in the ContextLength function.
8617   int length = shared->scope_info()->ContextLength(shared->qml_mode());
8618
8619   Object* result;
8620   { MaybeObject* maybe_result =
8621         isolate->heap()->AllocateFunctionContext(length, function);
8622     if (!maybe_result->ToObject(&result)) return maybe_result;
8623   }
8624
8625   isolate->set_context(Context::cast(result));
8626
8627   return result;  // non-failure
8628 }
8629
8630
8631 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8632   NoHandleAllocation ha;
8633   ASSERT(args.length() == 2);
8634   JSObject* extension_object;
8635   if (args[0]->IsJSObject()) {
8636     extension_object = JSObject::cast(args[0]);
8637   } else {
8638     // Convert the object to a proper JavaScript object.
8639     MaybeObject* maybe_js_object = args[0]->ToObject();
8640     if (!maybe_js_object->To(&extension_object)) {
8641       if (Failure::cast(maybe_js_object)->IsInternalError()) {
8642         HandleScope scope(isolate);
8643         Handle<Object> handle = args.at<Object>(0);
8644         Handle<Object> result =
8645             isolate->factory()->NewTypeError("with_expression",
8646                                              HandleVector(&handle, 1));
8647         return isolate->Throw(*result);
8648       } else {
8649         return maybe_js_object;
8650       }
8651     }
8652   }
8653
8654   JSFunction* function;
8655   if (args[1]->IsSmi()) {
8656     // A smi sentinel indicates a context nested inside global code rather
8657     // than some function.  There is a canonical empty function that can be
8658     // gotten from the global context.
8659     function = isolate->context()->global_context()->closure();
8660   } else {
8661     function = JSFunction::cast(args[1]);
8662   }
8663
8664   Context* context;
8665   MaybeObject* maybe_context =
8666       isolate->heap()->AllocateWithContext(function,
8667                                            isolate->context(),
8668                                            extension_object);
8669   if (!maybe_context->To(&context)) return maybe_context;
8670   isolate->set_context(context);
8671   return context;
8672 }
8673
8674
8675 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8676   NoHandleAllocation ha;
8677   ASSERT(args.length() == 3);
8678   String* name = String::cast(args[0]);
8679   Object* thrown_object = args[1];
8680   JSFunction* function;
8681   if (args[2]->IsSmi()) {
8682     // A smi sentinel indicates a context nested inside global code rather
8683     // than some function.  There is a canonical empty function that can be
8684     // gotten from the global context.
8685     function = isolate->context()->global_context()->closure();
8686   } else {
8687     function = JSFunction::cast(args[2]);
8688   }
8689   Context* context;
8690   MaybeObject* maybe_context =
8691       isolate->heap()->AllocateCatchContext(function,
8692                                             isolate->context(),
8693                                             name,
8694                                             thrown_object);
8695   if (!maybe_context->To(&context)) return maybe_context;
8696   isolate->set_context(context);
8697   return context;
8698 }
8699
8700
8701 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8702   NoHandleAllocation ha;
8703   ASSERT(args.length() == 2);
8704   ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8705   JSFunction* function;
8706   if (args[1]->IsSmi()) {
8707     // A smi sentinel indicates a context nested inside global code rather
8708     // than some function.  There is a canonical empty function that can be
8709     // gotten from the global context.
8710     function = isolate->context()->global_context()->closure();
8711   } else {
8712     function = JSFunction::cast(args[1]);
8713   }
8714   Context* context;
8715   MaybeObject* maybe_context =
8716       isolate->heap()->AllocateBlockContext(function,
8717                                             isolate->context(),
8718                                             scope_info);
8719   if (!maybe_context->To(&context)) return maybe_context;
8720   isolate->set_context(context);
8721   return context;
8722 }
8723
8724
8725 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
8726   NoHandleAllocation ha;
8727   ASSERT(args.length() == 2);
8728   CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 0);
8729   CONVERT_ARG_HANDLE_CHECKED(JSModule, instance, 1);
8730
8731   Context* context;
8732   MaybeObject* maybe_context =
8733       isolate->heap()->AllocateModuleContext(isolate->context(),
8734                                              scope_info);
8735   if (!maybe_context->To(&context)) return maybe_context;
8736   // Also initialize the context slot of the instance object.
8737   instance->set_context(context);
8738   isolate->set_context(context);
8739
8740   return context;
8741 }
8742
8743
8744 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8745   HandleScope scope(isolate);
8746   ASSERT(args.length() == 2);
8747
8748   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8749   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
8750
8751   int index;
8752   PropertyAttributes attributes;
8753   ContextLookupFlags flags = FOLLOW_CHAINS;
8754   BindingFlags binding_flags;
8755   Handle<Object> holder = context->Lookup(name,
8756                                           flags,
8757                                           &index,
8758                                           &attributes,
8759                                           &binding_flags);
8760
8761   // If the slot was not found the result is true.
8762   if (holder.is_null()) {
8763     return isolate->heap()->true_value();
8764   }
8765
8766   // If the slot was found in a context, it should be DONT_DELETE.
8767   if (holder->IsContext()) {
8768     return isolate->heap()->false_value();
8769   }
8770
8771   // The slot was found in a JSObject, either a context extension object,
8772   // the global object, or the subject of a with.  Try to delete it
8773   // (respecting DONT_DELETE).
8774   Handle<JSObject> object = Handle<JSObject>::cast(holder);
8775   return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
8776 }
8777
8778
8779 // A mechanism to return a pair of Object pointers in registers (if possible).
8780 // How this is achieved is calling convention-dependent.
8781 // All currently supported x86 compiles uses calling conventions that are cdecl
8782 // variants where a 64-bit value is returned in two 32-bit registers
8783 // (edx:eax on ia32, r1:r0 on ARM).
8784 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
8785 // In Win64 calling convention, a struct of two pointers is returned in memory,
8786 // allocated by the caller, and passed as a pointer in a hidden first parameter.
8787 #ifdef V8_HOST_ARCH_64_BIT
8788 struct ObjectPair {
8789   MaybeObject* x;
8790   MaybeObject* y;
8791 };
8792
8793 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8794   ObjectPair result = {x, y};
8795   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
8796   // In Win64 they are assigned to a hidden first argument.
8797   return result;
8798 }
8799 #else
8800 typedef uint64_t ObjectPair;
8801 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8802   return reinterpret_cast<uint32_t>(x) |
8803       (reinterpret_cast<ObjectPair>(y) << 32);
8804 }
8805 #endif
8806
8807
8808 static inline MaybeObject* Unhole(Heap* heap,
8809                                   MaybeObject* x,
8810                                   PropertyAttributes attributes) {
8811   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
8812   USE(attributes);
8813   return x->IsTheHole() ? heap->undefined_value() : x;
8814 }
8815
8816
8817 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
8818                                            JSObject* holder) {
8819   ASSERT(!holder->IsGlobalObject());
8820   Context* top = isolate->context();
8821   // Get the context extension function.
8822   JSFunction* context_extension_function =
8823       top->global_context()->context_extension_function();
8824   // If the holder isn't a context extension object, we just return it
8825   // as the receiver. This allows arguments objects to be used as
8826   // receivers, but only if they are put in the context scope chain
8827   // explicitly via a with-statement.
8828   Object* constructor = holder->map()->constructor();
8829   if (constructor != context_extension_function) return holder;
8830   // Fall back to using the global object as the implicit receiver if
8831   // the property turns out to be a local variable allocated in a
8832   // context extension object - introduced via eval. Implicit global
8833   // receivers are indicated with the hole value.
8834   return isolate->heap()->the_hole_value();
8835 }
8836
8837
8838 static ObjectPair LoadContextSlotHelper(Arguments args,
8839                                         Isolate* isolate,
8840                                         bool throw_error) {
8841   HandleScope scope(isolate);
8842   ASSERT_EQ(2, args.length());
8843
8844   if (!args[0]->IsContext() || !args[1]->IsString()) {
8845     return MakePair(isolate->ThrowIllegalOperation(), NULL);
8846   }
8847   Handle<Context> context = args.at<Context>(0);
8848   Handle<String> name = args.at<String>(1);
8849
8850   int index;
8851   PropertyAttributes attributes;
8852   ContextLookupFlags flags = FOLLOW_CHAINS;
8853   BindingFlags binding_flags;
8854   Handle<Object> holder = context->Lookup(name,
8855                                           flags,
8856                                           &index,
8857                                           &attributes,
8858                                           &binding_flags);
8859
8860   // If the index is non-negative, the slot has been found in a context.
8861   if (index >= 0) {
8862     ASSERT(holder->IsContext());
8863     // If the "property" we were looking for is a local variable, the
8864     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
8865     //
8866     // Use the hole as the receiver to signal that the receiver is implicit
8867     // and that the global receiver should be used (as distinguished from an
8868     // explicit receiver that happens to be a global object).
8869     Handle<Object> receiver = isolate->factory()->the_hole_value();
8870     Object* value = Context::cast(*holder)->get(index);
8871     // Check for uninitialized bindings.
8872     switch (binding_flags) {
8873       case MUTABLE_CHECK_INITIALIZED:
8874       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
8875         if (value->IsTheHole()) {
8876           Handle<Object> reference_error =
8877               isolate->factory()->NewReferenceError("not_defined",
8878                                                     HandleVector(&name, 1));
8879           return MakePair(isolate->Throw(*reference_error), NULL);
8880         }
8881         // FALLTHROUGH
8882       case MUTABLE_IS_INITIALIZED:
8883       case IMMUTABLE_IS_INITIALIZED:
8884       case IMMUTABLE_IS_INITIALIZED_HARMONY:
8885         ASSERT(!value->IsTheHole());
8886         return MakePair(value, *receiver);
8887       case IMMUTABLE_CHECK_INITIALIZED:
8888         return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
8889       case MISSING_BINDING:
8890         UNREACHABLE();
8891         return MakePair(NULL, NULL);
8892     }
8893   }
8894
8895   // Otherwise, if the slot was found the holder is a context extension
8896   // object, subject of a with, or a global object.  We read the named
8897   // property from it.
8898   if (!holder.is_null()) {
8899     Handle<JSObject> object = Handle<JSObject>::cast(holder);
8900     ASSERT(object->HasProperty(*name));
8901     // GetProperty below can cause GC.
8902     Handle<Object> receiver_handle(object->IsGlobalObject()
8903         ? GlobalObject::cast(*object)->global_receiver()
8904         : ComputeReceiverForNonGlobal(isolate, *object));
8905
8906     // No need to unhole the value here.  This is taken care of by the
8907     // GetProperty function.
8908     MaybeObject* value = object->GetProperty(*name);
8909     return MakePair(value, *receiver_handle);
8910   }
8911
8912   if (throw_error) {
8913     // The property doesn't exist - throw exception.
8914     Handle<Object> reference_error =
8915         isolate->factory()->NewReferenceError("not_defined",
8916                                               HandleVector(&name, 1));
8917     return MakePair(isolate->Throw(*reference_error), NULL);
8918   } else {
8919     // The property doesn't exist - return undefined.
8920     return MakePair(isolate->heap()->undefined_value(),
8921                     isolate->heap()->undefined_value());
8922   }
8923 }
8924
8925
8926 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
8927   return LoadContextSlotHelper(args, isolate, true);
8928 }
8929
8930
8931 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
8932   return LoadContextSlotHelper(args, isolate, false);
8933 }
8934
8935
8936 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
8937   HandleScope scope(isolate);
8938   ASSERT(args.length() == 4);
8939
8940   Handle<Object> value(args[0], isolate);
8941   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
8942   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
8943   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
8944   StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
8945       ? kNonStrictMode : kStrictMode;
8946
8947   int index;
8948   PropertyAttributes attributes;
8949   ContextLookupFlags flags = FOLLOW_CHAINS;
8950   BindingFlags binding_flags;
8951   Handle<Object> holder = context->Lookup(name,
8952                                           flags,
8953                                           &index,
8954                                           &attributes,
8955                                           &binding_flags);
8956
8957   if (index >= 0) {
8958     // The property was found in a context slot.
8959     Handle<Context> context = Handle<Context>::cast(holder);
8960     if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
8961         context->get(index)->IsTheHole()) {
8962       Handle<Object> error =
8963           isolate->factory()->NewReferenceError("not_defined",
8964                                                 HandleVector(&name, 1));
8965       return isolate->Throw(*error);
8966     }
8967     // Ignore if read_only variable.
8968     if ((attributes & READ_ONLY) == 0) {
8969       // Context is a fixed array and set cannot fail.
8970       context->set(index, *value);
8971     } else if (strict_mode == kStrictMode) {
8972       // Setting read only property in strict mode.
8973       Handle<Object> error =
8974           isolate->factory()->NewTypeError("strict_cannot_assign",
8975                                            HandleVector(&name, 1));
8976       return isolate->Throw(*error);
8977     }
8978     return *value;
8979   }
8980
8981   // Slow case: The property is not in a context slot.  It is either in a
8982   // context extension object, a property of the subject of a with, or a
8983   // property of the global object.
8984   Handle<JSObject> object;
8985
8986   if (!holder.is_null()) {
8987     // The property exists on the holder.
8988     object = Handle<JSObject>::cast(holder);
8989   } else {
8990     // The property was not found.
8991     ASSERT(attributes == ABSENT);
8992
8993     if (strict_mode == kStrictMode) {
8994       // Throw in strict mode (assignment to undefined variable).
8995       Handle<Object> error =
8996           isolate->factory()->NewReferenceError(
8997               "not_defined", HandleVector(&name, 1));
8998       return isolate->Throw(*error);
8999     }
9000     // In non-strict mode, the property is added to the global object.
9001     attributes = NONE;
9002     object = Handle<JSObject>(isolate->context()->global());
9003   }
9004
9005   // Set the property if it's not read only or doesn't yet exist.
9006   if ((attributes & READ_ONLY) == 0 ||
9007       (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
9008     RETURN_IF_EMPTY_HANDLE(
9009         isolate,
9010         JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9011   } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
9012     // Setting read only property in strict mode.
9013     Handle<Object> error =
9014       isolate->factory()->NewTypeError(
9015           "strict_cannot_assign", HandleVector(&name, 1));
9016     return isolate->Throw(*error);
9017   }
9018   return *value;
9019 }
9020
9021
9022 RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
9023   HandleScope scope(isolate);
9024   ASSERT(args.length() == 1);
9025
9026   return isolate->Throw(args[0]);
9027 }
9028
9029
9030 RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
9031   HandleScope scope(isolate);
9032   ASSERT(args.length() == 1);
9033
9034   return isolate->ReThrow(args[0]);
9035 }
9036
9037
9038 RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
9039   ASSERT_EQ(0, args.length());
9040   return isolate->PromoteScheduledException();
9041 }
9042
9043
9044 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
9045   HandleScope scope(isolate);
9046   ASSERT(args.length() == 1);
9047
9048   Handle<Object> name(args[0], isolate);
9049   Handle<Object> reference_error =
9050     isolate->factory()->NewReferenceError("not_defined",
9051                                           HandleVector(&name, 1));
9052   return isolate->Throw(*reference_error);
9053 }
9054
9055
9056 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9057   ASSERT(args.length() == 0);
9058
9059   // First check if this is a real stack overflow.
9060   if (isolate->stack_guard()->IsStackOverflow()) {
9061     NoHandleAllocation na;
9062     return isolate->StackOverflow();
9063   }
9064
9065   return Execution::HandleStackGuardInterrupt(isolate);
9066 }
9067
9068
9069 RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
9070   ASSERT(args.length() == 0);
9071   return Execution::HandleStackGuardInterrupt(isolate);
9072 }
9073
9074
9075 static int StackSize() {
9076   int n = 0;
9077   for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
9078   return n;
9079 }
9080
9081
9082 static void PrintTransition(Object* result) {
9083   // indentation
9084   { const int nmax = 80;
9085     int n = StackSize();
9086     if (n <= nmax)
9087       PrintF("%4d:%*s", n, n, "");
9088     else
9089       PrintF("%4d:%*s", n, nmax, "...");
9090   }
9091
9092   if (result == NULL) {
9093     JavaScriptFrame::PrintTop(stdout, true, false);
9094     PrintF(" {\n");
9095   } else {
9096     // function result
9097     PrintF("} -> ");
9098     result->ShortPrint();
9099     PrintF("\n");
9100   }
9101 }
9102
9103
9104 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9105   ASSERT(args.length() == 0);
9106   NoHandleAllocation ha;
9107   PrintTransition(NULL);
9108   return isolate->heap()->undefined_value();
9109 }
9110
9111
9112 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9113   NoHandleAllocation ha;
9114   PrintTransition(args[0]);
9115   return args[0];  // return TOS
9116 }
9117
9118
9119 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9120   NoHandleAllocation ha;
9121   ASSERT(args.length() == 1);
9122
9123 #ifdef DEBUG
9124   if (args[0]->IsString()) {
9125     // If we have a string, assume it's a code "marker"
9126     // and print some interesting cpu debugging info.
9127     JavaScriptFrameIterator it(isolate);
9128     JavaScriptFrame* frame = it.frame();
9129     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9130            frame->fp(), frame->sp(), frame->caller_sp());
9131   } else {
9132     PrintF("DebugPrint: ");
9133   }
9134   args[0]->Print();
9135   if (args[0]->IsHeapObject()) {
9136     PrintF("\n");
9137     HeapObject::cast(args[0])->map()->Print();
9138   }
9139 #else
9140   // ShortPrint is available in release mode. Print is not.
9141   args[0]->ShortPrint();
9142 #endif
9143   PrintF("\n");
9144   Flush();
9145
9146   return args[0];  // return TOS
9147 }
9148
9149
9150 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9151   ASSERT(args.length() == 0);
9152   NoHandleAllocation ha;
9153   isolate->PrintStack();
9154   return isolate->heap()->undefined_value();
9155 }
9156
9157
9158 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9159   NoHandleAllocation ha;
9160   ASSERT(args.length() == 0);
9161
9162   // According to ECMA-262, section 15.9.1, page 117, the precision of
9163   // the number in a Date object representing a particular instant in
9164   // time is milliseconds. Therefore, we floor the result of getting
9165   // the OS time.
9166   double millis = floor(OS::TimeCurrentMillis());
9167   return isolate->heap()->NumberFromDouble(millis);
9168 }
9169
9170
9171 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9172   HandleScope scope(isolate);
9173   ASSERT(args.length() == 2);
9174
9175   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9176   FlattenString(str);
9177
9178   CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9179
9180   MaybeObject* maybe_result_array =
9181       output->EnsureCanContainHeapObjectElements();
9182   if (maybe_result_array->IsFailure()) return maybe_result_array;
9183   RUNTIME_ASSERT(output->HasFastElements());
9184
9185   AssertNoAllocation no_allocation;
9186
9187   FixedArray* output_array = FixedArray::cast(output->elements());
9188   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9189   bool result;
9190   String::FlatContent str_content = str->GetFlatContent();
9191   if (str_content.IsAscii()) {
9192     result = DateParser::Parse(str_content.ToAsciiVector(),
9193                                output_array,
9194                                isolate->unicode_cache());
9195   } else {
9196     ASSERT(str_content.IsTwoByte());
9197     result = DateParser::Parse(str_content.ToUC16Vector(),
9198                                output_array,
9199                                isolate->unicode_cache());
9200   }
9201
9202   if (result) {
9203     return *output;
9204   } else {
9205     return isolate->heap()->null_value();
9206   }
9207 }
9208
9209
9210 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9211   NoHandleAllocation ha;
9212   ASSERT(args.length() == 1);
9213
9214   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9215   int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9216   const char* zone = OS::LocalTimezone(static_cast<double>(time));
9217   return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9218 }
9219
9220
9221 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9222   NoHandleAllocation ha;
9223   ASSERT(args.length() == 1);
9224
9225   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9226   int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9227
9228   return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9229 }
9230
9231
9232 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9233   ASSERT(args.length() == 1);
9234   Object* global = args[0];
9235   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9236   return JSGlobalObject::cast(global)->global_receiver();
9237 }
9238
9239
9240 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9241   HandleScope scope(isolate);
9242   ASSERT_EQ(1, args.length());
9243   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9244
9245   source = Handle<String>(source->TryFlattenGetString());
9246   // Optimized fast case where we only have ASCII characters.
9247   Handle<Object> result;
9248   if (source->IsSeqAsciiString()) {
9249     result = JsonParser<true>::Parse(source);
9250   } else {
9251     result = JsonParser<false>::Parse(source);
9252   }
9253   if (result.is_null()) {
9254     // Syntax error or stack overflow in scanner.
9255     ASSERT(isolate->has_pending_exception());
9256     return Failure::Exception();
9257   }
9258   return *result;
9259 }
9260
9261
9262 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9263                                       Handle<Context> context) {
9264   ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9265   // Check with callback if set.
9266   AllowCodeGenerationFromStringsCallback callback =
9267       isolate->allow_code_gen_callback();
9268   if (callback == NULL) {
9269     // No callback set and code generation disallowed.
9270     return false;
9271   } else {
9272     // Callback set. Let it decide if code generation is allowed.
9273     VMState state(isolate, EXTERNAL);
9274     return callback(v8::Utils::ToLocal(context));
9275   }
9276 }
9277
9278
9279 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9280   HandleScope scope(isolate);
9281   ASSERT_EQ(1, args.length());
9282   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9283
9284   // Extract global context.
9285   Handle<Context> context(isolate->context()->global_context());
9286
9287   // Check if global context allows code generation from
9288   // strings. Throw an exception if it doesn't.
9289   if (context->allow_code_gen_from_strings()->IsFalse() &&
9290       !CodeGenerationFromStringsAllowed(isolate, context)) {
9291     return isolate->Throw(*isolate->factory()->NewError(
9292         "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9293   }
9294
9295   // Compile source string in the global context.
9296   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9297       source, context, true, CLASSIC_MODE, RelocInfo::kNoPosition, false);
9298   if (shared.is_null()) return Failure::Exception();
9299   Handle<JSFunction> fun =
9300       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9301                                                             context,
9302                                                             NOT_TENURED);
9303   return *fun;
9304 }
9305
9306
9307 static ObjectPair CompileGlobalEval(Isolate* isolate,
9308                                     Handle<String> source,
9309                                     Handle<Object> receiver,
9310                                     LanguageMode language_mode,
9311                                     int scope_position,
9312                                     bool qml_mode) {
9313   Handle<Context> context = Handle<Context>(isolate->context());
9314   Handle<Context> global_context = Handle<Context>(context->global_context());
9315
9316   // Check if global context allows code generation from
9317   // strings. Throw an exception if it doesn't.
9318   if (global_context->allow_code_gen_from_strings()->IsFalse() &&
9319       !CodeGenerationFromStringsAllowed(isolate, global_context)) {
9320     isolate->Throw(*isolate->factory()->NewError(
9321         "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9322     return MakePair(Failure::Exception(), NULL);
9323   }
9324
9325   // Deal with a normal eval call with a string argument. Compile it
9326   // and return the compiled function bound in the local context.
9327   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9328       source,
9329       Handle<Context>(isolate->context()),
9330       context->IsGlobalContext(),
9331       language_mode,
9332       scope_position,
9333       qml_mode);
9334   if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
9335   Handle<JSFunction> compiled =
9336       isolate->factory()->NewFunctionFromSharedFunctionInfo(
9337           shared, context, NOT_TENURED);
9338   return MakePair(*compiled, *receiver);
9339 }
9340
9341
9342 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9343   ASSERT(args.length() == 6);
9344
9345   HandleScope scope(isolate);
9346   Handle<Object> callee = args.at<Object>(0);
9347
9348   // If "eval" didn't refer to the original GlobalEval, it's not a
9349   // direct call to eval.
9350   // (And even if it is, but the first argument isn't a string, just let
9351   // execution default to an indirect call to eval, which will also return
9352   // the first argument without doing anything).
9353   if (*callee != isolate->global_context()->global_eval_fun() ||
9354       !args[1]->IsString()) {
9355     return MakePair(*callee, isolate->heap()->the_hole_value());
9356   }
9357
9358   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9359   ASSERT(args[4]->IsSmi());
9360   return CompileGlobalEval(isolate,
9361                            args.at<String>(1),
9362                            args.at<Object>(2),
9363                            language_mode,
9364                            args.smi_at(4),
9365                            Smi::cast(args[5])->value());
9366 }
9367
9368
9369 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) {
9370   // This utility adjusts the property attributes for newly created Function
9371   // object ("new Function(...)") by changing the map.
9372   // All it does is changing the prototype property to enumerable
9373   // as specified in ECMA262, 15.3.5.2.
9374   HandleScope scope(isolate);
9375   ASSERT(args.length() == 1);
9376   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
9377
9378   Handle<Map> map = func->shared()->is_classic_mode()
9379       ? isolate->function_instance_map()
9380       : isolate->strict_mode_function_instance_map();
9381
9382   ASSERT(func->map()->instance_type() == map->instance_type());
9383   ASSERT(func->map()->instance_size() == map->instance_size());
9384   func->set_map(*map);
9385   return *func;
9386 }
9387
9388
9389 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9390   // Allocate a block of memory in NewSpace (filled with a filler).
9391   // Use as fallback for allocation in generated code when NewSpace
9392   // is full.
9393   ASSERT(args.length() == 1);
9394   CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9395   int size = size_smi->value();
9396   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9397   RUNTIME_ASSERT(size > 0);
9398   Heap* heap = isolate->heap();
9399   const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
9400   RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
9401   Object* allocation;
9402   { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
9403     if (maybe_allocation->ToObject(&allocation)) {
9404       heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9405     }
9406     return maybe_allocation;
9407   }
9408 }
9409
9410
9411 // Push an object unto an array of objects if it is not already in the
9412 // array.  Returns true if the element was pushed on the stack and
9413 // false otherwise.
9414 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9415   ASSERT(args.length() == 2);
9416   CONVERT_ARG_CHECKED(JSArray, array, 0);
9417   CONVERT_ARG_CHECKED(JSObject, element, 1);
9418   RUNTIME_ASSERT(array->HasFastElements() || array->HasFastSmiOnlyElements());
9419   int length = Smi::cast(array->length())->value();
9420   FixedArray* elements = FixedArray::cast(array->elements());
9421   for (int i = 0; i < length; i++) {
9422     if (elements->get(i) == element) return isolate->heap()->false_value();
9423   }
9424   Object* obj;
9425   // Strict not needed. Used for cycle detection in Array join implementation.
9426   { MaybeObject* maybe_obj =
9427         array->SetFastElement(length, element, kNonStrictMode, true);
9428     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9429   }
9430   return isolate->heap()->true_value();
9431 }
9432
9433
9434 /**
9435  * A simple visitor visits every element of Array's.
9436  * The backend storage can be a fixed array for fast elements case,
9437  * or a dictionary for sparse array. Since Dictionary is a subtype
9438  * of FixedArray, the class can be used by both fast and slow cases.
9439  * The second parameter of the constructor, fast_elements, specifies
9440  * whether the storage is a FixedArray or Dictionary.
9441  *
9442  * An index limit is used to deal with the situation that a result array
9443  * length overflows 32-bit non-negative integer.
9444  */
9445 class ArrayConcatVisitor {
9446  public:
9447   ArrayConcatVisitor(Isolate* isolate,
9448                      Handle<FixedArray> storage,
9449                      bool fast_elements) :
9450       isolate_(isolate),
9451       storage_(Handle<FixedArray>::cast(
9452           isolate->global_handles()->Create(*storage))),
9453       index_offset_(0u),
9454       fast_elements_(fast_elements) { }
9455
9456   ~ArrayConcatVisitor() {
9457     clear_storage();
9458   }
9459
9460   void visit(uint32_t i, Handle<Object> elm) {
9461     if (i >= JSObject::kMaxElementCount - index_offset_) return;
9462     uint32_t index = index_offset_ + i;
9463
9464     if (fast_elements_) {
9465       if (index < static_cast<uint32_t>(storage_->length())) {
9466         storage_->set(index, *elm);
9467         return;
9468       }
9469       // Our initial estimate of length was foiled, possibly by
9470       // getters on the arrays increasing the length of later arrays
9471       // during iteration.
9472       // This shouldn't happen in anything but pathological cases.
9473       SetDictionaryMode(index);
9474       // Fall-through to dictionary mode.
9475     }
9476     ASSERT(!fast_elements_);
9477     Handle<SeededNumberDictionary> dict(
9478         SeededNumberDictionary::cast(*storage_));
9479     Handle<SeededNumberDictionary> result =
9480         isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9481     if (!result.is_identical_to(dict)) {
9482       // Dictionary needed to grow.
9483       clear_storage();
9484       set_storage(*result);
9485     }
9486 }
9487
9488   void increase_index_offset(uint32_t delta) {
9489     if (JSObject::kMaxElementCount - index_offset_ < delta) {
9490       index_offset_ = JSObject::kMaxElementCount;
9491     } else {
9492       index_offset_ += delta;
9493     }
9494   }
9495
9496   Handle<JSArray> ToArray() {
9497     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9498     Handle<Object> length =
9499         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9500     Handle<Map> map;
9501     if (fast_elements_) {
9502       map = isolate_->factory()->GetElementsTransitionMap(array,
9503                                                           FAST_ELEMENTS);
9504     } else {
9505       map = isolate_->factory()->GetElementsTransitionMap(array,
9506                                                           DICTIONARY_ELEMENTS);
9507     }
9508     array->set_map(*map);
9509     array->set_length(*length);
9510     array->set_elements(*storage_);
9511     return array;
9512   }
9513
9514  private:
9515   // Convert storage to dictionary mode.
9516   void SetDictionaryMode(uint32_t index) {
9517     ASSERT(fast_elements_);
9518     Handle<FixedArray> current_storage(*storage_);
9519     Handle<SeededNumberDictionary> slow_storage(
9520         isolate_->factory()->NewSeededNumberDictionary(
9521             current_storage->length()));
9522     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9523     for (uint32_t i = 0; i < current_length; i++) {
9524       HandleScope loop_scope;
9525       Handle<Object> element(current_storage->get(i));
9526       if (!element->IsTheHole()) {
9527         Handle<SeededNumberDictionary> new_storage =
9528           isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9529         if (!new_storage.is_identical_to(slow_storage)) {
9530           slow_storage = loop_scope.CloseAndEscape(new_storage);
9531         }
9532       }
9533     }
9534     clear_storage();
9535     set_storage(*slow_storage);
9536     fast_elements_ = false;
9537   }
9538
9539   inline void clear_storage() {
9540     isolate_->global_handles()->Destroy(
9541         Handle<Object>::cast(storage_).location());
9542   }
9543
9544   inline void set_storage(FixedArray* storage) {
9545     storage_ = Handle<FixedArray>::cast(
9546         isolate_->global_handles()->Create(storage));
9547   }
9548
9549   Isolate* isolate_;
9550   Handle<FixedArray> storage_;  // Always a global handle.
9551   // Index after last seen index. Always less than or equal to
9552   // JSObject::kMaxElementCount.
9553   uint32_t index_offset_;
9554   bool fast_elements_;
9555 };
9556
9557
9558 static uint32_t EstimateElementCount(Handle<JSArray> array) {
9559   uint32_t length = static_cast<uint32_t>(array->length()->Number());
9560   int element_count = 0;
9561   switch (array->GetElementsKind()) {
9562     case FAST_SMI_ONLY_ELEMENTS:
9563     case FAST_ELEMENTS: {
9564       // Fast elements can't have lengths that are not representable by
9565       // a 32-bit signed integer.
9566       ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9567       int fast_length = static_cast<int>(length);
9568       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9569       for (int i = 0; i < fast_length; i++) {
9570         if (!elements->get(i)->IsTheHole()) element_count++;
9571       }
9572       break;
9573     }
9574     case FAST_DOUBLE_ELEMENTS:
9575       // TODO(1810): Decide if it's worthwhile to implement this.
9576       UNREACHABLE();
9577       break;
9578     case DICTIONARY_ELEMENTS: {
9579       Handle<SeededNumberDictionary> dictionary(
9580           SeededNumberDictionary::cast(array->elements()));
9581       int capacity = dictionary->Capacity();
9582       for (int i = 0; i < capacity; i++) {
9583         Handle<Object> key(dictionary->KeyAt(i));
9584         if (dictionary->IsKey(*key)) {
9585           element_count++;
9586         }
9587       }
9588       break;
9589     }
9590     case NON_STRICT_ARGUMENTS_ELEMENTS:
9591     case EXTERNAL_BYTE_ELEMENTS:
9592     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9593     case EXTERNAL_SHORT_ELEMENTS:
9594     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9595     case EXTERNAL_INT_ELEMENTS:
9596     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9597     case EXTERNAL_FLOAT_ELEMENTS:
9598     case EXTERNAL_DOUBLE_ELEMENTS:
9599     case EXTERNAL_PIXEL_ELEMENTS:
9600       // External arrays are always dense.
9601       return length;
9602   }
9603   // As an estimate, we assume that the prototype doesn't contain any
9604   // inherited elements.
9605   return element_count;
9606 }
9607
9608
9609
9610 template<class ExternalArrayClass, class ElementType>
9611 static void IterateExternalArrayElements(Isolate* isolate,
9612                                          Handle<JSObject> receiver,
9613                                          bool elements_are_ints,
9614                                          bool elements_are_guaranteed_smis,
9615                                          ArrayConcatVisitor* visitor) {
9616   Handle<ExternalArrayClass> array(
9617       ExternalArrayClass::cast(receiver->elements()));
9618   uint32_t len = static_cast<uint32_t>(array->length());
9619
9620   ASSERT(visitor != NULL);
9621   if (elements_are_ints) {
9622     if (elements_are_guaranteed_smis) {
9623       for (uint32_t j = 0; j < len; j++) {
9624         HandleScope loop_scope;
9625         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))));
9626         visitor->visit(j, e);
9627       }
9628     } else {
9629       for (uint32_t j = 0; j < len; j++) {
9630         HandleScope loop_scope;
9631         int64_t val = static_cast<int64_t>(array->get_scalar(j));
9632         if (Smi::IsValid(static_cast<intptr_t>(val))) {
9633           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
9634           visitor->visit(j, e);
9635         } else {
9636           Handle<Object> e =
9637               isolate->factory()->NewNumber(static_cast<ElementType>(val));
9638           visitor->visit(j, e);
9639         }
9640       }
9641     }
9642   } else {
9643     for (uint32_t j = 0; j < len; j++) {
9644       HandleScope loop_scope(isolate);
9645       Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
9646       visitor->visit(j, e);
9647     }
9648   }
9649 }
9650
9651
9652 // Used for sorting indices in a List<uint32_t>.
9653 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
9654   uint32_t a = *ap;
9655   uint32_t b = *bp;
9656   return (a == b) ? 0 : (a < b) ? -1 : 1;
9657 }
9658
9659
9660 static void CollectElementIndices(Handle<JSObject> object,
9661                                   uint32_t range,
9662                                   List<uint32_t>* indices) {
9663   ElementsKind kind = object->GetElementsKind();
9664   switch (kind) {
9665     case FAST_SMI_ONLY_ELEMENTS:
9666     case FAST_ELEMENTS: {
9667       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
9668       uint32_t length = static_cast<uint32_t>(elements->length());
9669       if (range < length) length = range;
9670       for (uint32_t i = 0; i < length; i++) {
9671         if (!elements->get(i)->IsTheHole()) {
9672           indices->Add(i);
9673         }
9674       }
9675       break;
9676     }
9677     case FAST_DOUBLE_ELEMENTS: {
9678       // TODO(1810): Decide if it's worthwhile to implement this.
9679       UNREACHABLE();
9680       break;
9681     }
9682     case DICTIONARY_ELEMENTS: {
9683       Handle<SeededNumberDictionary> dict(
9684           SeededNumberDictionary::cast(object->elements()));
9685       uint32_t capacity = dict->Capacity();
9686       for (uint32_t j = 0; j < capacity; j++) {
9687         HandleScope loop_scope;
9688         Handle<Object> k(dict->KeyAt(j));
9689         if (dict->IsKey(*k)) {
9690           ASSERT(k->IsNumber());
9691           uint32_t index = static_cast<uint32_t>(k->Number());
9692           if (index < range) {
9693             indices->Add(index);
9694           }
9695         }
9696       }
9697       break;
9698     }
9699     default: {
9700       int dense_elements_length;
9701       switch (kind) {
9702         case EXTERNAL_PIXEL_ELEMENTS: {
9703           dense_elements_length =
9704               ExternalPixelArray::cast(object->elements())->length();
9705           break;
9706         }
9707         case EXTERNAL_BYTE_ELEMENTS: {
9708           dense_elements_length =
9709               ExternalByteArray::cast(object->elements())->length();
9710           break;
9711         }
9712         case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9713           dense_elements_length =
9714               ExternalUnsignedByteArray::cast(object->elements())->length();
9715           break;
9716         }
9717         case EXTERNAL_SHORT_ELEMENTS: {
9718           dense_elements_length =
9719               ExternalShortArray::cast(object->elements())->length();
9720           break;
9721         }
9722         case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9723           dense_elements_length =
9724               ExternalUnsignedShortArray::cast(object->elements())->length();
9725           break;
9726         }
9727         case EXTERNAL_INT_ELEMENTS: {
9728           dense_elements_length =
9729               ExternalIntArray::cast(object->elements())->length();
9730           break;
9731         }
9732         case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9733           dense_elements_length =
9734               ExternalUnsignedIntArray::cast(object->elements())->length();
9735           break;
9736         }
9737         case EXTERNAL_FLOAT_ELEMENTS: {
9738           dense_elements_length =
9739               ExternalFloatArray::cast(object->elements())->length();
9740           break;
9741         }
9742         case EXTERNAL_DOUBLE_ELEMENTS: {
9743           dense_elements_length =
9744               ExternalDoubleArray::cast(object->elements())->length();
9745           break;
9746         }
9747         default:
9748           UNREACHABLE();
9749           dense_elements_length = 0;
9750           break;
9751       }
9752       uint32_t length = static_cast<uint32_t>(dense_elements_length);
9753       if (range <= length) {
9754         length = range;
9755         // We will add all indices, so we might as well clear it first
9756         // and avoid duplicates.
9757         indices->Clear();
9758       }
9759       for (uint32_t i = 0; i < length; i++) {
9760         indices->Add(i);
9761       }
9762       if (length == range) return;  // All indices accounted for already.
9763       break;
9764     }
9765   }
9766
9767   Handle<Object> prototype(object->GetPrototype());
9768   if (prototype->IsJSObject()) {
9769     // The prototype will usually have no inherited element indices,
9770     // but we have to check.
9771     CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
9772   }
9773 }
9774
9775
9776 /**
9777  * A helper function that visits elements of a JSArray in numerical
9778  * order.
9779  *
9780  * The visitor argument called for each existing element in the array
9781  * with the element index and the element's value.
9782  * Afterwards it increments the base-index of the visitor by the array
9783  * length.
9784  * Returns false if any access threw an exception, otherwise true.
9785  */
9786 static bool IterateElements(Isolate* isolate,
9787                             Handle<JSArray> receiver,
9788                             ArrayConcatVisitor* visitor) {
9789   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
9790   switch (receiver->GetElementsKind()) {
9791     case FAST_SMI_ONLY_ELEMENTS:
9792     case FAST_ELEMENTS: {
9793       // Run through the elements FixedArray and use HasElement and GetElement
9794       // to check the prototype for missing elements.
9795       Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
9796       int fast_length = static_cast<int>(length);
9797       ASSERT(fast_length <= elements->length());
9798       for (int j = 0; j < fast_length; j++) {
9799         HandleScope loop_scope(isolate);
9800         Handle<Object> element_value(elements->get(j), isolate);
9801         if (!element_value->IsTheHole()) {
9802           visitor->visit(j, element_value);
9803         } else if (receiver->HasElement(j)) {
9804           // Call GetElement on receiver, not its prototype, or getters won't
9805           // have the correct receiver.
9806           element_value = Object::GetElement(receiver, j);
9807           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
9808           visitor->visit(j, element_value);
9809         }
9810       }
9811       break;
9812     }
9813     case FAST_DOUBLE_ELEMENTS: {
9814       // TODO(1810): Decide if it's worthwhile to implement this.
9815       UNREACHABLE();
9816       break;
9817     }
9818     case DICTIONARY_ELEMENTS: {
9819       Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
9820       List<uint32_t> indices(dict->Capacity() / 2);
9821       // Collect all indices in the object and the prototypes less
9822       // than length. This might introduce duplicates in the indices list.
9823       CollectElementIndices(receiver, length, &indices);
9824       indices.Sort(&compareUInt32);
9825       int j = 0;
9826       int n = indices.length();
9827       while (j < n) {
9828         HandleScope loop_scope;
9829         uint32_t index = indices[j];
9830         Handle<Object> element = Object::GetElement(receiver, index);
9831         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
9832         visitor->visit(index, element);
9833         // Skip to next different index (i.e., omit duplicates).
9834         do {
9835           j++;
9836         } while (j < n && indices[j] == index);
9837       }
9838       break;
9839     }
9840     case EXTERNAL_PIXEL_ELEMENTS: {
9841       Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
9842           receiver->elements()));
9843       for (uint32_t j = 0; j < length; j++) {
9844         Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)));
9845         visitor->visit(j, e);
9846       }
9847       break;
9848     }
9849     case EXTERNAL_BYTE_ELEMENTS: {
9850       IterateExternalArrayElements<ExternalByteArray, int8_t>(
9851           isolate, receiver, true, true, visitor);
9852       break;
9853     }
9854     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9855       IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
9856           isolate, receiver, true, true, visitor);
9857       break;
9858     }
9859     case EXTERNAL_SHORT_ELEMENTS: {
9860       IterateExternalArrayElements<ExternalShortArray, int16_t>(
9861           isolate, receiver, true, true, visitor);
9862       break;
9863     }
9864     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9865       IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
9866           isolate, receiver, true, true, visitor);
9867       break;
9868     }
9869     case EXTERNAL_INT_ELEMENTS: {
9870       IterateExternalArrayElements<ExternalIntArray, int32_t>(
9871           isolate, receiver, true, false, visitor);
9872       break;
9873     }
9874     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9875       IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
9876           isolate, receiver, true, false, visitor);
9877       break;
9878     }
9879     case EXTERNAL_FLOAT_ELEMENTS: {
9880       IterateExternalArrayElements<ExternalFloatArray, float>(
9881           isolate, receiver, false, false, visitor);
9882       break;
9883     }
9884     case EXTERNAL_DOUBLE_ELEMENTS: {
9885       IterateExternalArrayElements<ExternalDoubleArray, double>(
9886           isolate, receiver, false, false, visitor);
9887       break;
9888     }
9889     default:
9890       UNREACHABLE();
9891       break;
9892   }
9893   visitor->increase_index_offset(length);
9894   return true;
9895 }
9896
9897
9898 /**
9899  * Array::concat implementation.
9900  * See ECMAScript 262, 15.4.4.4.
9901  * TODO(581): Fix non-compliance for very large concatenations and update to
9902  * following the ECMAScript 5 specification.
9903  */
9904 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
9905   ASSERT(args.length() == 1);
9906   HandleScope handle_scope(isolate);
9907
9908   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
9909   int argument_count = static_cast<int>(arguments->length()->Number());
9910   RUNTIME_ASSERT(arguments->HasFastElements());
9911   Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
9912
9913   // Pass 1: estimate the length and number of elements of the result.
9914   // The actual length can be larger if any of the arguments have getters
9915   // that mutate other arguments (but will otherwise be precise).
9916   // The number of elements is precise if there are no inherited elements.
9917
9918   uint32_t estimate_result_length = 0;
9919   uint32_t estimate_nof_elements = 0;
9920   {
9921     for (int i = 0; i < argument_count; i++) {
9922       HandleScope loop_scope;
9923       Handle<Object> obj(elements->get(i));
9924       uint32_t length_estimate;
9925       uint32_t element_estimate;
9926       if (obj->IsJSArray()) {
9927         Handle<JSArray> array(Handle<JSArray>::cast(obj));
9928         // TODO(1810): Find out if it's worthwhile to properly support
9929         // arbitrary ElementsKinds. For now, pessimistically transition to
9930         // FAST_ELEMENTS.
9931         if (array->HasFastDoubleElements()) {
9932           array = Handle<JSArray>::cast(
9933               JSObject::TransitionElementsKind(array, FAST_ELEMENTS));
9934         }
9935         length_estimate =
9936             static_cast<uint32_t>(array->length()->Number());
9937         element_estimate =
9938             EstimateElementCount(array);
9939       } else {
9940         length_estimate = 1;
9941         element_estimate = 1;
9942       }
9943       // Avoid overflows by capping at kMaxElementCount.
9944       if (JSObject::kMaxElementCount - estimate_result_length <
9945           length_estimate) {
9946         estimate_result_length = JSObject::kMaxElementCount;
9947       } else {
9948         estimate_result_length += length_estimate;
9949       }
9950       if (JSObject::kMaxElementCount - estimate_nof_elements <
9951           element_estimate) {
9952         estimate_nof_elements = JSObject::kMaxElementCount;
9953       } else {
9954         estimate_nof_elements += element_estimate;
9955       }
9956     }
9957   }
9958
9959   // If estimated number of elements is more than half of length, a
9960   // fixed array (fast case) is more time and space-efficient than a
9961   // dictionary.
9962   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
9963
9964   Handle<FixedArray> storage;
9965   if (fast_case) {
9966     // The backing storage array must have non-existing elements to
9967     // preserve holes across concat operations.
9968     storage = isolate->factory()->NewFixedArrayWithHoles(
9969         estimate_result_length);
9970   } else {
9971     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
9972     uint32_t at_least_space_for = estimate_nof_elements +
9973                                   (estimate_nof_elements >> 2);
9974     storage = Handle<FixedArray>::cast(
9975         isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
9976   }
9977
9978   ArrayConcatVisitor visitor(isolate, storage, fast_case);
9979
9980   for (int i = 0; i < argument_count; i++) {
9981     Handle<Object> obj(elements->get(i));
9982     if (obj->IsJSArray()) {
9983       Handle<JSArray> array = Handle<JSArray>::cast(obj);
9984       if (!IterateElements(isolate, array, &visitor)) {
9985         return Failure::Exception();
9986       }
9987     } else {
9988       visitor.visit(0, obj);
9989       visitor.increase_index_offset(1);
9990     }
9991   }
9992
9993   return *visitor.ToArray();
9994 }
9995
9996
9997 // This will not allocate (flatten the string), but it may run
9998 // very slowly for very deeply nested ConsStrings.  For debugging use only.
9999 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10000   NoHandleAllocation ha;
10001   ASSERT(args.length() == 1);
10002
10003   CONVERT_ARG_CHECKED(String, string, 0);
10004   StringInputBuffer buffer(string);
10005   while (buffer.has_more()) {
10006     uint16_t character = buffer.GetNext();
10007     PrintF("%c", character);
10008   }
10009   return string;
10010 }
10011
10012 // Moves all own elements of an object, that are below a limit, to positions
10013 // starting at zero. All undefined values are placed after non-undefined values,
10014 // and are followed by non-existing element. Does not change the length
10015 // property.
10016 // Returns the number of non-undefined elements collected.
10017 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10018   ASSERT(args.length() == 2);
10019   CONVERT_ARG_CHECKED(JSObject, object, 0);
10020   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10021   return object->PrepareElementsForSort(limit);
10022 }
10023
10024
10025 // Move contents of argument 0 (an array) to argument 1 (an array)
10026 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10027   ASSERT(args.length() == 2);
10028   CONVERT_ARG_CHECKED(JSArray, from, 0);
10029   CONVERT_ARG_CHECKED(JSArray, to, 1);
10030   FixedArrayBase* new_elements = from->elements();
10031   MaybeObject* maybe_new_map;
10032   ElementsKind elements_kind;
10033   if (new_elements->map() == isolate->heap()->fixed_array_map() ||
10034       new_elements->map() == isolate->heap()->fixed_cow_array_map()) {
10035     elements_kind = FAST_ELEMENTS;
10036   } else if (new_elements->map() ==
10037              isolate->heap()->fixed_double_array_map()) {
10038     elements_kind = FAST_DOUBLE_ELEMENTS;
10039   } else {
10040     elements_kind = DICTIONARY_ELEMENTS;
10041   }
10042   maybe_new_map = to->GetElementsTransitionMap(isolate, elements_kind);
10043   Object* new_map;
10044   if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10045   to->set_map(Map::cast(new_map));
10046   to->set_elements(new_elements);
10047   to->set_length(from->length());
10048   Object* obj;
10049   { MaybeObject* maybe_obj = from->ResetElements();
10050     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10051   }
10052   from->set_length(Smi::FromInt(0));
10053   return to;
10054 }
10055
10056
10057 // How many elements does this object/array have?
10058 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10059   ASSERT(args.length() == 1);
10060   CONVERT_ARG_CHECKED(JSObject, object, 0);
10061   HeapObject* elements = object->elements();
10062   if (elements->IsDictionary()) {
10063     int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10064     return Smi::FromInt(result);
10065   } else if (object->IsJSArray()) {
10066     return JSArray::cast(object)->length();
10067   } else {
10068     return Smi::FromInt(FixedArray::cast(elements)->length());
10069   }
10070 }
10071
10072
10073 // Returns an array that tells you where in the [0, length) interval an array
10074 // might have elements.  Can either return keys (positive integers) or
10075 // intervals (pair of a negative integer (-start-1) followed by a
10076 // positive (length)) or undefined values.
10077 // Intervals can span over some keys that are not in the object.
10078 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10079   ASSERT(args.length() == 2);
10080   HandleScope scope(isolate);
10081   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10082   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10083   if (array->elements()->IsDictionary()) {
10084     // Create an array and get all the keys into it, then remove all the
10085     // keys that are not integers in the range 0 to length-1.
10086     bool threw = false;
10087     Handle<FixedArray> keys =
10088         GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw);
10089     if (threw) return Failure::Exception();
10090
10091     int keys_length = keys->length();
10092     for (int i = 0; i < keys_length; i++) {
10093       Object* key = keys->get(i);
10094       uint32_t index = 0;
10095       if (!key->ToArrayIndex(&index) || index >= length) {
10096         // Zap invalid keys.
10097         keys->set_undefined(i);
10098       }
10099     }
10100     return *isolate->factory()->NewJSArrayWithElements(keys);
10101   } else {
10102     ASSERT(array->HasFastElements() ||
10103            array->HasFastSmiOnlyElements() ||
10104            array->HasFastDoubleElements());
10105     Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
10106     // -1 means start of array.
10107     single_interval->set(0, Smi::FromInt(-1));
10108     FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
10109     uint32_t actual_length =
10110         static_cast<uint32_t>(elements->length());
10111     uint32_t min_length = actual_length < length ? actual_length : length;
10112     Handle<Object> length_object =
10113         isolate->factory()->NewNumber(static_cast<double>(min_length));
10114     single_interval->set(1, *length_object);
10115     return *isolate->factory()->NewJSArrayWithElements(single_interval);
10116   }
10117 }
10118
10119
10120 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10121   ASSERT(args.length() == 3);
10122   CONVERT_ARG_CHECKED(JSObject, obj, 0);
10123   CONVERT_ARG_CHECKED(String, name, 1);
10124   CONVERT_SMI_ARG_CHECKED(flag, 2);
10125   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10126   return obj->LookupAccessor(name, component);
10127 }
10128
10129
10130 #ifdef ENABLE_DEBUGGER_SUPPORT
10131 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10132   ASSERT(args.length() == 0);
10133   return Execution::DebugBreakHelper();
10134 }
10135
10136
10137 // Helper functions for wrapping and unwrapping stack frame ids.
10138 static Smi* WrapFrameId(StackFrame::Id id) {
10139   ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10140   return Smi::FromInt(id >> 2);
10141 }
10142
10143
10144 static StackFrame::Id UnwrapFrameId(int wrapped) {
10145   return static_cast<StackFrame::Id>(wrapped << 2);
10146 }
10147
10148
10149 // Adds a JavaScript function as a debug event listener.
10150 // args[0]: debug event listener function to set or null or undefined for
10151 //          clearing the event listener function
10152 // args[1]: object supplied during callback
10153 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10154   ASSERT(args.length() == 2);
10155   RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10156                  args[0]->IsUndefined() ||
10157                  args[0]->IsNull());
10158   Handle<Object> callback = args.at<Object>(0);
10159   Handle<Object> data = args.at<Object>(1);
10160   isolate->debugger()->SetEventListener(callback, data);
10161
10162   return isolate->heap()->undefined_value();
10163 }
10164
10165
10166 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10167   ASSERT(args.length() == 0);
10168   isolate->stack_guard()->DebugBreak();
10169   return isolate->heap()->undefined_value();
10170 }
10171
10172
10173 static MaybeObject* DebugLookupResultValue(Heap* heap,
10174                                            Object* receiver,
10175                                            String* name,
10176                                            LookupResult* result,
10177                                            bool* caught_exception) {
10178   Object* value;
10179   switch (result->type()) {
10180     case NORMAL:
10181       value = result->holder()->GetNormalizedProperty(result);
10182       if (value->IsTheHole()) {
10183         return heap->undefined_value();
10184       }
10185       return value;
10186     case FIELD:
10187       value =
10188           JSObject::cast(
10189               result->holder())->FastPropertyAt(result->GetFieldIndex());
10190       if (value->IsTheHole()) {
10191         return heap->undefined_value();
10192       }
10193       return value;
10194     case CONSTANT_FUNCTION:
10195       return result->GetConstantFunction();
10196     case CALLBACKS: {
10197       Object* structure = result->GetCallbackObject();
10198       if (structure->IsForeign() || structure->IsAccessorInfo()) {
10199         MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
10200             receiver, structure, name);
10201         if (!maybe_value->ToObject(&value)) {
10202           if (maybe_value->IsRetryAfterGC()) return maybe_value;
10203           ASSERT(maybe_value->IsException());
10204           maybe_value = heap->isolate()->pending_exception();
10205           heap->isolate()->clear_pending_exception();
10206           if (caught_exception != NULL) {
10207             *caught_exception = true;
10208           }
10209           return maybe_value;
10210         }
10211         return value;
10212       } else {
10213         return heap->undefined_value();
10214       }
10215     }
10216     case INTERCEPTOR:
10217     case MAP_TRANSITION:
10218     case ELEMENTS_TRANSITION:
10219     case CONSTANT_TRANSITION:
10220     case NULL_DESCRIPTOR:
10221       return heap->undefined_value();
10222     case HANDLER:
10223       UNREACHABLE();
10224       return heap->undefined_value();
10225   }
10226   UNREACHABLE();  // keep the compiler happy
10227   return heap->undefined_value();
10228 }
10229
10230
10231 // Get debugger related details for an object property.
10232 // args[0]: object holding property
10233 // args[1]: name of the property
10234 //
10235 // The array returned contains the following information:
10236 // 0: Property value
10237 // 1: Property details
10238 // 2: Property value is exception
10239 // 3: Getter function if defined
10240 // 4: Setter function if defined
10241 // Items 2-4 are only filled if the property has either a getter or a setter
10242 // defined through __defineGetter__ and/or __defineSetter__.
10243 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10244   HandleScope scope(isolate);
10245
10246   ASSERT(args.length() == 2);
10247
10248   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10249   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10250
10251   // Make sure to set the current context to the context before the debugger was
10252   // entered (if the debugger is entered). The reason for switching context here
10253   // is that for some property lookups (accessors and interceptors) callbacks
10254   // into the embedding application can occour, and the embedding application
10255   // could have the assumption that its own global context is the current
10256   // context and not some internal debugger context.
10257   SaveContext save(isolate);
10258   if (isolate->debug()->InDebugger()) {
10259     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10260   }
10261
10262   // Skip the global proxy as it has no properties and always delegates to the
10263   // real global object.
10264   if (obj->IsJSGlobalProxy()) {
10265     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10266   }
10267
10268
10269   // Check if the name is trivially convertible to an index and get the element
10270   // if so.
10271   uint32_t index;
10272   if (name->AsArrayIndex(&index)) {
10273     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10274     Object* element_or_char;
10275     { MaybeObject* maybe_element_or_char =
10276           Runtime::GetElementOrCharAt(isolate, obj, index);
10277       if (!maybe_element_or_char->ToObject(&element_or_char)) {
10278         return maybe_element_or_char;
10279       }
10280     }
10281     details->set(0, element_or_char);
10282     details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
10283     return *isolate->factory()->NewJSArrayWithElements(details);
10284   }
10285
10286   // Find the number of objects making up this.
10287   int length = LocalPrototypeChainLength(*obj);
10288
10289   // Try local lookup on each of the objects.
10290   Handle<JSObject> jsproto = obj;
10291   for (int i = 0; i < length; i++) {
10292     LookupResult result(isolate);
10293     jsproto->LocalLookup(*name, &result);
10294     if (result.IsProperty()) {
10295       // LookupResult is not GC safe as it holds raw object pointers.
10296       // GC can happen later in this code so put the required fields into
10297       // local variables using handles when required for later use.
10298       PropertyType result_type = result.type();
10299       Handle<Object> result_callback_obj;
10300       if (result_type == CALLBACKS) {
10301         result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10302                                              isolate);
10303       }
10304       Smi* property_details = result.GetPropertyDetails().AsSmi();
10305       // DebugLookupResultValue can cause GC so details from LookupResult needs
10306       // to be copied to handles before this.
10307       bool caught_exception = false;
10308       Object* raw_value;
10309       { MaybeObject* maybe_raw_value =
10310             DebugLookupResultValue(isolate->heap(), *obj, *name,
10311                                    &result, &caught_exception);
10312         if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10313       }
10314       Handle<Object> value(raw_value, isolate);
10315
10316       // If the callback object is a fixed array then it contains JavaScript
10317       // getter and/or setter.
10318       bool hasJavaScriptAccessors = result_type == CALLBACKS &&
10319                                     result_callback_obj->IsAccessorPair();
10320       Handle<FixedArray> details =
10321           isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10322       details->set(0, *value);
10323       details->set(1, property_details);
10324       if (hasJavaScriptAccessors) {
10325         AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10326         details->set(2, isolate->heap()->ToBoolean(caught_exception));
10327         details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10328         details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10329       }
10330
10331       return *isolate->factory()->NewJSArrayWithElements(details);
10332     }
10333     if (i < length - 1) {
10334       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10335     }
10336   }
10337
10338   return isolate->heap()->undefined_value();
10339 }
10340
10341
10342 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10343   HandleScope scope(isolate);
10344
10345   ASSERT(args.length() == 2);
10346
10347   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10348   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10349
10350   LookupResult result(isolate);
10351   obj->Lookup(*name, &result);
10352   if (result.IsProperty()) {
10353     return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10354   }
10355   return isolate->heap()->undefined_value();
10356 }
10357
10358
10359 // Return the property type calculated from the property details.
10360 // args[0]: smi with property details.
10361 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10362   ASSERT(args.length() == 1);
10363   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10364   return Smi::FromInt(static_cast<int>(details.type()));
10365 }
10366
10367
10368 // Return the property attribute calculated from the property details.
10369 // args[0]: smi with property details.
10370 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10371   ASSERT(args.length() == 1);
10372   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10373   return Smi::FromInt(static_cast<int>(details.attributes()));
10374 }
10375
10376
10377 // Return the property insertion index calculated from the property details.
10378 // args[0]: smi with property details.
10379 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10380   ASSERT(args.length() == 1);
10381   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10382   return Smi::FromInt(details.index());
10383 }
10384
10385
10386 // Return property value from named interceptor.
10387 // args[0]: object
10388 // args[1]: property name
10389 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10390   HandleScope scope(isolate);
10391   ASSERT(args.length() == 2);
10392   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10393   RUNTIME_ASSERT(obj->HasNamedInterceptor());
10394   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10395
10396   PropertyAttributes attributes;
10397   return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
10398 }
10399
10400
10401 // Return element value from indexed interceptor.
10402 // args[0]: object
10403 // args[1]: index
10404 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10405   HandleScope scope(isolate);
10406   ASSERT(args.length() == 2);
10407   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10408   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10409   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10410
10411   return obj->GetElementWithInterceptor(*obj, index);
10412 }
10413
10414
10415 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10416   ASSERT(args.length() >= 1);
10417   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10418   // Check that the break id is valid.
10419   if (isolate->debug()->break_id() == 0 ||
10420       break_id != isolate->debug()->break_id()) {
10421     return isolate->Throw(
10422         isolate->heap()->illegal_execution_state_symbol());
10423   }
10424
10425   return isolate->heap()->true_value();
10426 }
10427
10428
10429 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10430   HandleScope scope(isolate);
10431   ASSERT(args.length() == 1);
10432
10433   // Check arguments.
10434   Object* result;
10435   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10436       RUNTIME_ARGUMENTS(isolate, args));
10437     if (!maybe_result->ToObject(&result)) return maybe_result;
10438   }
10439
10440   // Count all frames which are relevant to debugging stack trace.
10441   int n = 0;
10442   StackFrame::Id id = isolate->debug()->break_frame_id();
10443   if (id == StackFrame::NO_ID) {
10444     // If there is no JavaScript stack frame count is 0.
10445     return Smi::FromInt(0);
10446   }
10447
10448   for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10449     n += it.frame()->GetInlineCount();
10450   }
10451   return Smi::FromInt(n);
10452 }
10453
10454
10455 class FrameInspector {
10456  public:
10457   FrameInspector(JavaScriptFrame* frame,
10458                  int inlined_jsframe_index,
10459                  Isolate* isolate)
10460       : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
10461     // Calculate the deoptimized frame.
10462     if (frame->is_optimized()) {
10463       deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
10464           frame, inlined_jsframe_index, isolate);
10465     }
10466     has_adapted_arguments_ = frame_->has_adapted_arguments();
10467     is_bottommost_ = inlined_jsframe_index == 0;
10468     is_optimized_ = frame_->is_optimized();
10469   }
10470
10471   ~FrameInspector() {
10472     // Get rid of the calculated deoptimized frame if any.
10473     if (deoptimized_frame_ != NULL) {
10474       Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
10475                                                   isolate_);
10476     }
10477   }
10478
10479   int GetParametersCount() {
10480     return is_optimized_
10481         ? deoptimized_frame_->parameters_count()
10482         : frame_->ComputeParametersCount();
10483   }
10484   int expression_count() { return deoptimized_frame_->expression_count(); }
10485   Object* GetFunction() {
10486     return is_optimized_
10487         ? deoptimized_frame_->GetFunction()
10488         : frame_->function();
10489   }
10490   Object* GetParameter(int index) {
10491     return is_optimized_
10492         ? deoptimized_frame_->GetParameter(index)
10493         : frame_->GetParameter(index);
10494   }
10495   Object* GetExpression(int index) {
10496     return is_optimized_
10497         ? deoptimized_frame_->GetExpression(index)
10498         : frame_->GetExpression(index);
10499   }
10500   int GetSourcePosition() {
10501     return is_optimized_
10502         ? deoptimized_frame_->GetSourcePosition()
10503         : frame_->LookupCode()->SourcePosition(frame_->pc());
10504   }
10505   bool IsConstructor() {
10506     return is_optimized_ && !is_bottommost_
10507         ? deoptimized_frame_->HasConstructStub()
10508         : frame_->IsConstructor();
10509   }
10510
10511   // To inspect all the provided arguments the frame might need to be
10512   // replaced with the arguments frame.
10513   void SetArgumentsFrame(JavaScriptFrame* frame) {
10514     ASSERT(has_adapted_arguments_);
10515     frame_ = frame;
10516     is_optimized_ = frame_->is_optimized();
10517     ASSERT(!is_optimized_);
10518   }
10519
10520  private:
10521   JavaScriptFrame* frame_;
10522   DeoptimizedFrameInfo* deoptimized_frame_;
10523   Isolate* isolate_;
10524   bool is_optimized_;
10525   bool is_bottommost_;
10526   bool has_adapted_arguments_;
10527
10528   DISALLOW_COPY_AND_ASSIGN(FrameInspector);
10529 };
10530
10531
10532 static const int kFrameDetailsFrameIdIndex = 0;
10533 static const int kFrameDetailsReceiverIndex = 1;
10534 static const int kFrameDetailsFunctionIndex = 2;
10535 static const int kFrameDetailsArgumentCountIndex = 3;
10536 static const int kFrameDetailsLocalCountIndex = 4;
10537 static const int kFrameDetailsSourcePositionIndex = 5;
10538 static const int kFrameDetailsConstructCallIndex = 6;
10539 static const int kFrameDetailsAtReturnIndex = 7;
10540 static const int kFrameDetailsFlagsIndex = 8;
10541 static const int kFrameDetailsFirstDynamicIndex = 9;
10542
10543
10544 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
10545                                              JavaScriptFrame* frame) {
10546   SaveContext* save = isolate->save_context();
10547   while (save != NULL && !save->IsBelowFrame(frame)) {
10548     save = save->prev();
10549   }
10550   ASSERT(save != NULL);
10551   return save;
10552 }
10553
10554
10555 // Return an array with frame details
10556 // args[0]: number: break id
10557 // args[1]: number: frame index
10558 //
10559 // The array returned contains the following information:
10560 // 0: Frame id
10561 // 1: Receiver
10562 // 2: Function
10563 // 3: Argument count
10564 // 4: Local count
10565 // 5: Source position
10566 // 6: Constructor call
10567 // 7: Is at return
10568 // 8: Flags
10569 // Arguments name, value
10570 // Locals name, value
10571 // Return value if any
10572 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
10573   HandleScope scope(isolate);
10574   ASSERT(args.length() == 2);
10575
10576   // Check arguments.
10577   Object* check;
10578   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10579       RUNTIME_ARGUMENTS(isolate, args));
10580     if (!maybe_check->ToObject(&check)) return maybe_check;
10581   }
10582   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10583   Heap* heap = isolate->heap();
10584
10585   // Find the relevant frame with the requested index.
10586   StackFrame::Id id = isolate->debug()->break_frame_id();
10587   if (id == StackFrame::NO_ID) {
10588     // If there are no JavaScript stack frames return undefined.
10589     return heap->undefined_value();
10590   }
10591
10592   int count = 0;
10593   JavaScriptFrameIterator it(isolate, id);
10594   for (; !it.done(); it.Advance()) {
10595     if (index < count + it.frame()->GetInlineCount()) break;
10596     count += it.frame()->GetInlineCount();
10597   }
10598   if (it.done()) return heap->undefined_value();
10599
10600   bool is_optimized = it.frame()->is_optimized();
10601
10602   int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
10603   if (is_optimized) {
10604     inlined_jsframe_index =
10605         it.frame()->GetInlineCount() - (index - count) - 1;
10606   }
10607   FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
10608
10609   // Traverse the saved contexts chain to find the active context for the
10610   // selected frame.
10611   SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
10612
10613   // Get the frame id.
10614   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
10615
10616   // Find source position in unoptimized code.
10617   int position = frame_inspector.GetSourcePosition();
10618
10619   // Check for constructor frame.
10620   bool constructor = frame_inspector.IsConstructor();
10621
10622   // Get scope info and read from it for local variable information.
10623   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
10624   Handle<SharedFunctionInfo> shared(function->shared());
10625   Handle<ScopeInfo> scope_info(shared->scope_info());
10626   ASSERT(*scope_info != ScopeInfo::Empty());
10627
10628   // Get the locals names and values into a temporary array.
10629   //
10630   // TODO(1240907): Hide compiler-introduced stack variables
10631   // (e.g. .result)?  For users of the debugger, they will probably be
10632   // confusing.
10633   Handle<FixedArray> locals =
10634       isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
10635
10636   // Fill in the values of the locals.
10637   int i = 0;
10638   for (; i < scope_info->StackLocalCount(); ++i) {
10639     // Use the value from the stack.
10640     locals->set(i * 2, scope_info->LocalName(i));
10641     locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
10642   }
10643   if (i < scope_info->LocalCount()) {
10644     // Get the context containing declarations.
10645     Handle<Context> context(
10646         Context::cast(it.frame()->context())->declaration_context());
10647     for (; i < scope_info->LocalCount(); ++i) {
10648       Handle<String> name(scope_info->LocalName(i));
10649       VariableMode mode;
10650       InitializationFlag init_flag;
10651       locals->set(i * 2, *name);
10652       locals->set(i * 2 + 1, context->get(
10653           scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
10654     }
10655   }
10656
10657   // Check whether this frame is positioned at return. If not top
10658   // frame or if the frame is optimized it cannot be at a return.
10659   bool at_return = false;
10660   if (!is_optimized && index == 0) {
10661     at_return = isolate->debug()->IsBreakAtReturn(it.frame());
10662   }
10663
10664   // If positioned just before return find the value to be returned and add it
10665   // to the frame information.
10666   Handle<Object> return_value = isolate->factory()->undefined_value();
10667   if (at_return) {
10668     StackFrameIterator it2(isolate);
10669     Address internal_frame_sp = NULL;
10670     while (!it2.done()) {
10671       if (it2.frame()->is_internal()) {
10672         internal_frame_sp = it2.frame()->sp();
10673       } else {
10674         if (it2.frame()->is_java_script()) {
10675           if (it2.frame()->id() == it.frame()->id()) {
10676             // The internal frame just before the JavaScript frame contains the
10677             // value to return on top. A debug break at return will create an
10678             // internal frame to store the return value (eax/rax/r0) before
10679             // entering the debug break exit frame.
10680             if (internal_frame_sp != NULL) {
10681               return_value =
10682                   Handle<Object>(Memory::Object_at(internal_frame_sp),
10683                                  isolate);
10684               break;
10685             }
10686           }
10687         }
10688
10689         // Indicate that the previous frame was not an internal frame.
10690         internal_frame_sp = NULL;
10691       }
10692       it2.Advance();
10693     }
10694   }
10695
10696   // Now advance to the arguments adapter frame (if any). It contains all
10697   // the provided parameters whereas the function frame always have the number
10698   // of arguments matching the functions parameters. The rest of the
10699   // information (except for what is collected above) is the same.
10700   if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
10701     it.AdvanceToArgumentsFrame();
10702     frame_inspector.SetArgumentsFrame(it.frame());
10703   }
10704
10705   // Find the number of arguments to fill. At least fill the number of
10706   // parameters for the function and fill more if more parameters are provided.
10707   int argument_count = scope_info->ParameterCount();
10708   if (argument_count < frame_inspector.GetParametersCount()) {
10709     argument_count = frame_inspector.GetParametersCount();
10710   }
10711
10712   // Calculate the size of the result.
10713   int details_size = kFrameDetailsFirstDynamicIndex +
10714                      2 * (argument_count + scope_info->LocalCount()) +
10715                      (at_return ? 1 : 0);
10716   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
10717
10718   // Add the frame id.
10719   details->set(kFrameDetailsFrameIdIndex, *frame_id);
10720
10721   // Add the function (same as in function frame).
10722   details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
10723
10724   // Add the arguments count.
10725   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
10726
10727   // Add the locals count
10728   details->set(kFrameDetailsLocalCountIndex,
10729                Smi::FromInt(scope_info->LocalCount()));
10730
10731   // Add the source position.
10732   if (position != RelocInfo::kNoPosition) {
10733     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
10734   } else {
10735     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
10736   }
10737
10738   // Add the constructor information.
10739   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
10740
10741   // Add the at return information.
10742   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
10743
10744   // Add flags to indicate information on whether this frame is
10745   //   bit 0: invoked in the debugger context.
10746   //   bit 1: optimized frame.
10747   //   bit 2: inlined in optimized frame
10748   int flags = 0;
10749   if (*save->context() == *isolate->debug()->debug_context()) {
10750     flags |= 1 << 0;
10751   }
10752   if (is_optimized) {
10753     flags |= 1 << 1;
10754     flags |= inlined_jsframe_index << 2;
10755   }
10756   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
10757
10758   // Fill the dynamic part.
10759   int details_index = kFrameDetailsFirstDynamicIndex;
10760
10761   // Add arguments name and value.
10762   for (int i = 0; i < argument_count; i++) {
10763     // Name of the argument.
10764     if (i < scope_info->ParameterCount()) {
10765       details->set(details_index++, scope_info->ParameterName(i));
10766     } else {
10767       details->set(details_index++, heap->undefined_value());
10768     }
10769
10770     // Parameter value.
10771     if (i < frame_inspector.GetParametersCount()) {
10772       // Get the value from the stack.
10773       details->set(details_index++, frame_inspector.GetParameter(i));
10774     } else {
10775       details->set(details_index++, heap->undefined_value());
10776     }
10777   }
10778
10779   // Add locals name and value from the temporary copy from the function frame.
10780   for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
10781     details->set(details_index++, locals->get(i));
10782   }
10783
10784   // Add the value being returned.
10785   if (at_return) {
10786     details->set(details_index++, *return_value);
10787   }
10788
10789   // Add the receiver (same as in function frame).
10790   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
10791   // THE FRAME ITERATOR TO WRAP THE RECEIVER.
10792   Handle<Object> receiver(it.frame()->receiver(), isolate);
10793   if (!receiver->IsJSObject() &&
10794       shared->is_classic_mode() &&
10795       !shared->native()) {
10796     // If the receiver is not a JSObject and the function is not a
10797     // builtin or strict-mode we have hit an optimization where a
10798     // value object is not converted into a wrapped JS objects. To
10799     // hide this optimization from the debugger, we wrap the receiver
10800     // by creating correct wrapper object based on the calling frame's
10801     // global context.
10802     it.Advance();
10803     Handle<Context> calling_frames_global_context(
10804         Context::cast(Context::cast(it.frame()->context())->global_context()));
10805     receiver =
10806         isolate->factory()->ToObject(receiver, calling_frames_global_context);
10807   }
10808   details->set(kFrameDetailsReceiverIndex, *receiver);
10809
10810   ASSERT_EQ(details_size, details_index);
10811   return *isolate->factory()->NewJSArrayWithElements(details);
10812 }
10813
10814
10815 // Copy all the context locals into an object used to materialize a scope.
10816 static bool CopyContextLocalsToScopeObject(
10817     Isolate* isolate,
10818     Handle<ScopeInfo> scope_info,
10819     Handle<Context> context,
10820     Handle<JSObject> scope_object) {
10821   // Fill all context locals to the context extension.
10822   for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
10823     VariableMode mode;
10824     InitializationFlag init_flag;
10825     int context_index = scope_info->ContextSlotIndex(
10826         scope_info->ContextLocalName(i), &mode, &init_flag);
10827
10828     RETURN_IF_EMPTY_HANDLE_VALUE(
10829         isolate,
10830         SetProperty(scope_object,
10831                     Handle<String>(scope_info->ContextLocalName(i)),
10832                     Handle<Object>(context->get(context_index), isolate),
10833                     NONE,
10834                     kNonStrictMode),
10835         false);
10836   }
10837
10838   return true;
10839 }
10840
10841
10842 // Create a plain JSObject which materializes the local scope for the specified
10843 // frame.
10844 static Handle<JSObject> MaterializeLocalScopeWithFrameInspector(
10845     Isolate* isolate,
10846     JavaScriptFrame* frame,
10847     FrameInspector* frame_inspector) {
10848   Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
10849   Handle<SharedFunctionInfo> shared(function->shared());
10850   Handle<ScopeInfo> scope_info(shared->scope_info());
10851
10852   // Allocate and initialize a JSObject with all the arguments, stack locals
10853   // heap locals and extension properties of the debugged function.
10854   Handle<JSObject> local_scope =
10855       isolate->factory()->NewJSObject(isolate->object_function());
10856
10857   // First fill all parameters.
10858   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
10859     Handle<Object> value(
10860         i < frame_inspector->GetParametersCount() ?
10861         frame_inspector->GetParameter(i) : isolate->heap()->undefined_value());
10862
10863     RETURN_IF_EMPTY_HANDLE_VALUE(
10864         isolate,
10865         SetProperty(local_scope,
10866                     Handle<String>(scope_info->ParameterName(i)),
10867                     value,
10868                     NONE,
10869                     kNonStrictMode),
10870         Handle<JSObject>());
10871   }
10872
10873   // Second fill all stack locals.
10874   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
10875     RETURN_IF_EMPTY_HANDLE_VALUE(
10876         isolate,
10877         SetProperty(local_scope,
10878                     Handle<String>(scope_info->StackLocalName(i)),
10879                     Handle<Object>(frame_inspector->GetExpression(i)),
10880                     NONE,
10881                     kNonStrictMode),
10882         Handle<JSObject>());
10883   }
10884
10885   if (scope_info->HasContext()) {
10886     // Third fill all context locals.
10887     Handle<Context> frame_context(Context::cast(frame->context()));
10888     Handle<Context> function_context(frame_context->declaration_context());
10889     if (!CopyContextLocalsToScopeObject(
10890             isolate, scope_info, function_context, local_scope)) {
10891       return Handle<JSObject>();
10892     }
10893
10894     // Finally copy any properties from the function context extension.
10895     // These will be variables introduced by eval.
10896     if (function_context->closure() == *function) {
10897       if (function_context->has_extension() &&
10898           !function_context->IsGlobalContext()) {
10899         Handle<JSObject> ext(JSObject::cast(function_context->extension()));
10900         bool threw = false;
10901         Handle<FixedArray> keys =
10902             GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10903         if (threw) return Handle<JSObject>();
10904
10905         for (int i = 0; i < keys->length(); i++) {
10906           // Names of variables introduced by eval are strings.
10907           ASSERT(keys->get(i)->IsString());
10908           Handle<String> key(String::cast(keys->get(i)));
10909           RETURN_IF_EMPTY_HANDLE_VALUE(
10910               isolate,
10911               SetProperty(local_scope,
10912                           key,
10913                           GetProperty(ext, key),
10914                           NONE,
10915                           kNonStrictMode),
10916               Handle<JSObject>());
10917         }
10918       }
10919     }
10920   }
10921
10922   return local_scope;
10923 }
10924
10925
10926 static Handle<JSObject> MaterializeLocalScope(
10927     Isolate* isolate,
10928     JavaScriptFrame* frame,
10929     int inlined_jsframe_index) {
10930   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
10931   return MaterializeLocalScopeWithFrameInspector(isolate,
10932                                                  frame,
10933                                                  &frame_inspector);
10934 }
10935
10936
10937 // Create a plain JSObject which materializes the closure content for the
10938 // context.
10939 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
10940                                            Handle<Context> context) {
10941   ASSERT(context->IsFunctionContext());
10942
10943   Handle<SharedFunctionInfo> shared(context->closure()->shared());
10944   Handle<ScopeInfo> scope_info(shared->scope_info());
10945
10946   // Allocate and initialize a JSObject with all the content of this function
10947   // closure.
10948   Handle<JSObject> closure_scope =
10949       isolate->factory()->NewJSObject(isolate->object_function());
10950
10951   // Fill all context locals to the context extension.
10952   if (!CopyContextLocalsToScopeObject(
10953           isolate, scope_info, context, closure_scope)) {
10954     return Handle<JSObject>();
10955   }
10956
10957   // Finally copy any properties from the function context extension. This will
10958   // be variables introduced by eval.
10959   if (context->has_extension()) {
10960     Handle<JSObject> ext(JSObject::cast(context->extension()));
10961     bool threw = false;
10962     Handle<FixedArray> keys =
10963         GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10964     if (threw) return Handle<JSObject>();
10965
10966     for (int i = 0; i < keys->length(); i++) {
10967       // Names of variables introduced by eval are strings.
10968       ASSERT(keys->get(i)->IsString());
10969       Handle<String> key(String::cast(keys->get(i)));
10970        RETURN_IF_EMPTY_HANDLE_VALUE(
10971           isolate,
10972           SetProperty(closure_scope,
10973                       key,
10974                       GetProperty(ext, key),
10975                       NONE,
10976                       kNonStrictMode),
10977           Handle<JSObject>());
10978     }
10979   }
10980
10981   return closure_scope;
10982 }
10983
10984
10985 // Create a plain JSObject which materializes the scope for the specified
10986 // catch context.
10987 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
10988                                               Handle<Context> context) {
10989   ASSERT(context->IsCatchContext());
10990   Handle<String> name(String::cast(context->extension()));
10991   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX));
10992   Handle<JSObject> catch_scope =
10993       isolate->factory()->NewJSObject(isolate->object_function());
10994   RETURN_IF_EMPTY_HANDLE_VALUE(
10995       isolate,
10996       SetProperty(catch_scope, name, thrown_object, NONE, kNonStrictMode),
10997       Handle<JSObject>());
10998   return catch_scope;
10999 }
11000
11001
11002 // Create a plain JSObject which materializes the block scope for the specified
11003 // block context.
11004 static Handle<JSObject> MaterializeBlockScope(
11005     Isolate* isolate,
11006     Handle<Context> context) {
11007   ASSERT(context->IsBlockContext());
11008   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11009
11010   // Allocate and initialize a JSObject with all the arguments, stack locals
11011   // heap locals and extension properties of the debugged function.
11012   Handle<JSObject> block_scope =
11013       isolate->factory()->NewJSObject(isolate->object_function());
11014
11015   // Fill all context locals.
11016   if (!CopyContextLocalsToScopeObject(
11017           isolate, scope_info, context, block_scope)) {
11018     return Handle<JSObject>();
11019   }
11020
11021   return block_scope;
11022 }
11023
11024
11025 // Create a plain JSObject which materializes the module scope for the specified
11026 // module context.
11027 static Handle<JSObject> MaterializeModuleScope(
11028     Isolate* isolate,
11029     Handle<Context> context) {
11030   ASSERT(context->IsModuleContext());
11031   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11032
11033   // Allocate and initialize a JSObject with all the members of the debugged
11034   // module.
11035   Handle<JSObject> module_scope =
11036       isolate->factory()->NewJSObject(isolate->object_function());
11037
11038   // Fill all context locals.
11039   if (!CopyContextLocalsToScopeObject(
11040           isolate, scope_info, context, module_scope)) {
11041     return Handle<JSObject>();
11042   }
11043
11044   return module_scope;
11045 }
11046
11047
11048 // Iterate over the actual scopes visible from a stack frame or from a closure.
11049 // The iteration proceeds from the innermost visible nested scope outwards.
11050 // All scopes are backed by an actual context except the local scope,
11051 // which is inserted "artificially" in the context chain.
11052 class ScopeIterator {
11053  public:
11054   enum ScopeType {
11055     ScopeTypeGlobal = 0,
11056     ScopeTypeLocal,
11057     ScopeTypeWith,
11058     ScopeTypeClosure,
11059     ScopeTypeCatch,
11060     ScopeTypeBlock,
11061     ScopeTypeModule
11062   };
11063
11064   ScopeIterator(Isolate* isolate,
11065                 JavaScriptFrame* frame,
11066                 int inlined_jsframe_index)
11067     : isolate_(isolate),
11068       frame_(frame),
11069       inlined_jsframe_index_(inlined_jsframe_index),
11070       function_(JSFunction::cast(frame->function())),
11071       context_(Context::cast(frame->context())),
11072       nested_scope_chain_(4) {
11073
11074     // Catch the case when the debugger stops in an internal function.
11075     Handle<SharedFunctionInfo> shared_info(function_->shared());
11076     Handle<ScopeInfo> scope_info(shared_info->scope_info());
11077     if (shared_info->script() == isolate->heap()->undefined_value()) {
11078       while (context_->closure() == *function_) {
11079         context_ = Handle<Context>(context_->previous(), isolate_);
11080       }
11081       return;
11082     }
11083
11084     // Get the debug info (create it if it does not exist).
11085     if (!isolate->debug()->EnsureDebugInfo(shared_info)) {
11086       // Return if ensuring debug info failed.
11087       return;
11088     }
11089     Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11090
11091     // Find the break point where execution has stopped.
11092     BreakLocationIterator break_location_iterator(debug_info,
11093                                                   ALL_BREAK_LOCATIONS);
11094     break_location_iterator.FindBreakLocationFromAddress(frame->pc());
11095     if (break_location_iterator.IsExit()) {
11096       // We are within the return sequence. At the momemt it is not possible to
11097       // get a source position which is consistent with the current scope chain.
11098       // Thus all nested with, catch and block contexts are skipped and we only
11099       // provide the function scope.
11100       if (scope_info->HasContext()) {
11101         context_ = Handle<Context>(context_->declaration_context(), isolate_);
11102       } else {
11103         while (context_->closure() == *function_) {
11104           context_ = Handle<Context>(context_->previous(), isolate_);
11105         }
11106       }
11107       if (scope_info->Type() != EVAL_SCOPE) nested_scope_chain_.Add(scope_info);
11108     } else {
11109       // Reparse the code and analyze the scopes.
11110       ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
11111       Handle<Script> script(Script::cast(shared_info->script()));
11112       Scope* scope = NULL;
11113
11114       // Check whether we are in global, eval or function code.
11115       Handle<ScopeInfo> scope_info(shared_info->scope_info());
11116       if (scope_info->Type() != FUNCTION_SCOPE) {
11117         // Global or eval code.
11118         CompilationInfo info(script);
11119         if (scope_info->Type() == GLOBAL_SCOPE) {
11120           info.MarkAsGlobal();
11121         } else {
11122           ASSERT(scope_info->Type() == EVAL_SCOPE);
11123           info.MarkAsEval();
11124           info.SetCallingContext(Handle<Context>(function_->context()));
11125         }
11126         if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
11127           scope = info.function()->scope();
11128         }
11129       } else {
11130         // Function code
11131         CompilationInfo info(shared_info);
11132         if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
11133           scope = info.function()->scope();
11134         }
11135       }
11136
11137       // Retrieve the scope chain for the current position.
11138       if (scope != NULL) {
11139         int source_position = shared_info->code()->SourcePosition(frame_->pc());
11140         scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
11141       } else {
11142         // A failed reparse indicates that the preparser has diverged from the
11143         // parser or that the preparse data given to the initial parse has been
11144         // faulty. We fail in debug mode but in release mode we only provide the
11145         // information we get from the context chain but nothing about
11146         // completely stack allocated scopes or stack allocated locals.
11147         UNREACHABLE();
11148       }
11149     }
11150   }
11151
11152   ScopeIterator(Isolate* isolate,
11153                 Handle<JSFunction> function)
11154     : isolate_(isolate),
11155       frame_(NULL),
11156       inlined_jsframe_index_(0),
11157       function_(function),
11158       context_(function->context()) {
11159     if (function->IsBuiltin()) {
11160       context_ = Handle<Context>();
11161     }
11162   }
11163
11164   // More scopes?
11165   bool Done() { return context_.is_null(); }
11166
11167   // Move to the next scope.
11168   void Next() {
11169     ScopeType scope_type = Type();
11170     if (scope_type == ScopeTypeGlobal) {
11171       // The global scope is always the last in the chain.
11172       ASSERT(context_->IsGlobalContext());
11173       context_ = Handle<Context>();
11174       return;
11175     }
11176     if (nested_scope_chain_.is_empty()) {
11177       context_ = Handle<Context>(context_->previous(), isolate_);
11178     } else {
11179       if (nested_scope_chain_.last()->HasContext()) {
11180         ASSERT(context_->previous() != NULL);
11181         context_ = Handle<Context>(context_->previous(), isolate_);
11182       }
11183       nested_scope_chain_.RemoveLast();
11184     }
11185   }
11186
11187   // Return the type of the current scope.
11188   ScopeType Type() {
11189     if (!nested_scope_chain_.is_empty()) {
11190       Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11191       switch (scope_info->Type()) {
11192         case FUNCTION_SCOPE:
11193           ASSERT(context_->IsFunctionContext() ||
11194                  !scope_info->HasContext());
11195           return ScopeTypeLocal;
11196         case MODULE_SCOPE:
11197           ASSERT(context_->IsModuleContext());
11198           return ScopeTypeModule;
11199         case GLOBAL_SCOPE:
11200           ASSERT(context_->IsGlobalContext());
11201           return ScopeTypeGlobal;
11202         case WITH_SCOPE:
11203           ASSERT(context_->IsWithContext());
11204           return ScopeTypeWith;
11205         case CATCH_SCOPE:
11206           ASSERT(context_->IsCatchContext());
11207           return ScopeTypeCatch;
11208         case BLOCK_SCOPE:
11209           ASSERT(!scope_info->HasContext() ||
11210                  context_->IsBlockContext());
11211           return ScopeTypeBlock;
11212         case EVAL_SCOPE:
11213           UNREACHABLE();
11214       }
11215     }
11216     if (context_->IsGlobalContext()) {
11217       ASSERT(context_->global()->IsGlobalObject());
11218       return ScopeTypeGlobal;
11219     }
11220     if (context_->IsFunctionContext()) {
11221       return ScopeTypeClosure;
11222     }
11223     if (context_->IsCatchContext()) {
11224       return ScopeTypeCatch;
11225     }
11226     if (context_->IsBlockContext()) {
11227       return ScopeTypeBlock;
11228     }
11229     if (context_->IsModuleContext()) {
11230       return ScopeTypeModule;
11231     }
11232     ASSERT(context_->IsWithContext());
11233     return ScopeTypeWith;
11234   }
11235
11236   // Return the JavaScript object with the content of the current scope.
11237   Handle<JSObject> ScopeObject() {
11238     switch (Type()) {
11239       case ScopeIterator::ScopeTypeGlobal:
11240         return Handle<JSObject>(CurrentContext()->global());
11241       case ScopeIterator::ScopeTypeLocal:
11242         // Materialize the content of the local scope into a JSObject.
11243         ASSERT(nested_scope_chain_.length() == 1);
11244         return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11245       case ScopeIterator::ScopeTypeWith:
11246         // Return the with object.
11247         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11248       case ScopeIterator::ScopeTypeCatch:
11249         return MaterializeCatchScope(isolate_, CurrentContext());
11250       case ScopeIterator::ScopeTypeClosure:
11251         // Materialize the content of the closure scope into a JSObject.
11252         return MaterializeClosure(isolate_, CurrentContext());
11253       case ScopeIterator::ScopeTypeBlock:
11254         return MaterializeBlockScope(isolate_, CurrentContext());
11255       case ScopeIterator::ScopeTypeModule:
11256         return MaterializeModuleScope(isolate_, CurrentContext());
11257     }
11258     UNREACHABLE();
11259     return Handle<JSObject>();
11260   }
11261
11262   Handle<ScopeInfo> CurrentScopeInfo() {
11263     if (!nested_scope_chain_.is_empty()) {
11264       return nested_scope_chain_.last();
11265     } else if (context_->IsBlockContext()) {
11266       return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
11267     } else if (context_->IsFunctionContext()) {
11268       return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
11269     }
11270     return Handle<ScopeInfo>::null();
11271   }
11272
11273   // Return the context for this scope. For the local context there might not
11274   // be an actual context.
11275   Handle<Context> CurrentContext() {
11276     if (Type() == ScopeTypeGlobal ||
11277         nested_scope_chain_.is_empty()) {
11278       return context_;
11279     } else if (nested_scope_chain_.last()->HasContext()) {
11280       return context_;
11281     } else {
11282       return Handle<Context>();
11283     }
11284   }
11285
11286 #ifdef DEBUG
11287   // Debug print of the content of the current scope.
11288   void DebugPrint() {
11289     switch (Type()) {
11290       case ScopeIterator::ScopeTypeGlobal:
11291         PrintF("Global:\n");
11292         CurrentContext()->Print();
11293         break;
11294
11295       case ScopeIterator::ScopeTypeLocal: {
11296         PrintF("Local:\n");
11297         function_->shared()->scope_info()->Print();
11298         if (!CurrentContext().is_null()) {
11299           CurrentContext()->Print();
11300           if (CurrentContext()->has_extension()) {
11301             Handle<Object> extension(CurrentContext()->extension());
11302             if (extension->IsJSContextExtensionObject()) {
11303               extension->Print();
11304             }
11305           }
11306         }
11307         break;
11308       }
11309
11310       case ScopeIterator::ScopeTypeWith:
11311         PrintF("With:\n");
11312         CurrentContext()->extension()->Print();
11313         break;
11314
11315       case ScopeIterator::ScopeTypeCatch:
11316         PrintF("Catch:\n");
11317         CurrentContext()->extension()->Print();
11318         CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
11319         break;
11320
11321       case ScopeIterator::ScopeTypeClosure:
11322         PrintF("Closure:\n");
11323         CurrentContext()->Print();
11324         if (CurrentContext()->has_extension()) {
11325           Handle<Object> extension(CurrentContext()->extension());
11326           if (extension->IsJSContextExtensionObject()) {
11327             extension->Print();
11328           }
11329         }
11330         break;
11331
11332       default:
11333         UNREACHABLE();
11334     }
11335     PrintF("\n");
11336   }
11337 #endif
11338
11339  private:
11340   Isolate* isolate_;
11341   JavaScriptFrame* frame_;
11342   int inlined_jsframe_index_;
11343   Handle<JSFunction> function_;
11344   Handle<Context> context_;
11345   List<Handle<ScopeInfo> > nested_scope_chain_;
11346
11347   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11348 };
11349
11350
11351 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11352   HandleScope scope(isolate);
11353   ASSERT(args.length() == 2);
11354
11355   // Check arguments.
11356   Object* check;
11357   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11358       RUNTIME_ARGUMENTS(isolate, args));
11359     if (!maybe_check->ToObject(&check)) return maybe_check;
11360   }
11361   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11362
11363   // Get the frame where the debugging is performed.
11364   StackFrame::Id id = UnwrapFrameId(wrapped_id);
11365   JavaScriptFrameIterator it(isolate, id);
11366   JavaScriptFrame* frame = it.frame();
11367
11368   // Count the visible scopes.
11369   int n = 0;
11370   for (ScopeIterator it(isolate, frame, 0);
11371        !it.Done();
11372        it.Next()) {
11373     n++;
11374   }
11375
11376   return Smi::FromInt(n);
11377 }
11378
11379
11380 static const int kScopeDetailsTypeIndex = 0;
11381 static const int kScopeDetailsObjectIndex = 1;
11382 static const int kScopeDetailsSize = 2;
11383
11384
11385 static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
11386     ScopeIterator* it) {
11387   // Calculate the size of the result.
11388   int details_size = kScopeDetailsSize;
11389   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11390
11391   // Fill in scope details.
11392   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
11393   Handle<JSObject> scope_object = it->ScopeObject();
11394   RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
11395   details->set(kScopeDetailsObjectIndex, *scope_object);
11396
11397   return *isolate->factory()->NewJSArrayWithElements(details);
11398 }
11399
11400 // Return an array with scope details
11401 // args[0]: number: break id
11402 // args[1]: number: frame index
11403 // args[2]: number: inlined frame index
11404 // args[3]: number: scope index
11405 //
11406 // The array returned contains the following information:
11407 // 0: Scope type
11408 // 1: Scope object
11409 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
11410   HandleScope scope(isolate);
11411   ASSERT(args.length() == 4);
11412
11413   // Check arguments.
11414   Object* check;
11415   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11416       RUNTIME_ARGUMENTS(isolate, args));
11417     if (!maybe_check->ToObject(&check)) return maybe_check;
11418   }
11419   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11420   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11421   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
11422
11423   // Get the frame where the debugging is performed.
11424   StackFrame::Id id = UnwrapFrameId(wrapped_id);
11425   JavaScriptFrameIterator frame_it(isolate, id);
11426   JavaScriptFrame* frame = frame_it.frame();
11427
11428   // Find the requested scope.
11429   int n = 0;
11430   ScopeIterator it(isolate, frame, inlined_jsframe_index);
11431   for (; !it.Done() && n < index; it.Next()) {
11432     n++;
11433   }
11434   if (it.Done()) {
11435     return isolate->heap()->undefined_value();
11436   }
11437   return MaterializeScopeDetails(isolate, &it);
11438 }
11439
11440
11441 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
11442   HandleScope scope(isolate);
11443   ASSERT(args.length() == 1);
11444
11445   // Check arguments.
11446   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11447
11448   // Count the visible scopes.
11449   int n = 0;
11450   for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
11451     n++;
11452   }
11453
11454   return Smi::FromInt(n);
11455 }
11456
11457
11458 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
11459   HandleScope scope(isolate);
11460   ASSERT(args.length() == 2);
11461
11462   // Check arguments.
11463   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11464   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11465
11466   // Find the requested scope.
11467   int n = 0;
11468   ScopeIterator it(isolate, fun);
11469   for (; !it.Done() && n < index; it.Next()) {
11470     n++;
11471   }
11472   if (it.Done()) {
11473     return isolate->heap()->undefined_value();
11474   }
11475
11476   return MaterializeScopeDetails(isolate, &it);
11477 }
11478
11479
11480 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
11481   HandleScope scope(isolate);
11482   ASSERT(args.length() == 0);
11483
11484 #ifdef DEBUG
11485   // Print the scopes for the top frame.
11486   StackFrameLocator locator;
11487   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
11488   for (ScopeIterator it(isolate, frame, 0);
11489        !it.Done();
11490        it.Next()) {
11491     it.DebugPrint();
11492   }
11493 #endif
11494   return isolate->heap()->undefined_value();
11495 }
11496
11497
11498 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
11499   HandleScope scope(isolate);
11500   ASSERT(args.length() == 1);
11501
11502   // Check arguments.
11503   Object* result;
11504   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11505       RUNTIME_ARGUMENTS(isolate, args));
11506     if (!maybe_result->ToObject(&result)) return maybe_result;
11507   }
11508
11509   // Count all archived V8 threads.
11510   int n = 0;
11511   for (ThreadState* thread =
11512           isolate->thread_manager()->FirstThreadStateInUse();
11513        thread != NULL;
11514        thread = thread->Next()) {
11515     n++;
11516   }
11517
11518   // Total number of threads is current thread and archived threads.
11519   return Smi::FromInt(n + 1);
11520 }
11521
11522
11523 static const int kThreadDetailsCurrentThreadIndex = 0;
11524 static const int kThreadDetailsThreadIdIndex = 1;
11525 static const int kThreadDetailsSize = 2;
11526
11527 // Return an array with thread details
11528 // args[0]: number: break id
11529 // args[1]: number: thread index
11530 //
11531 // The array returned contains the following information:
11532 // 0: Is current thread?
11533 // 1: Thread id
11534 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
11535   HandleScope scope(isolate);
11536   ASSERT(args.length() == 2);
11537
11538   // Check arguments.
11539   Object* check;
11540   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11541       RUNTIME_ARGUMENTS(isolate, args));
11542     if (!maybe_check->ToObject(&check)) return maybe_check;
11543   }
11544   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11545
11546   // Allocate array for result.
11547   Handle<FixedArray> details =
11548       isolate->factory()->NewFixedArray(kThreadDetailsSize);
11549
11550   // Thread index 0 is current thread.
11551   if (index == 0) {
11552     // Fill the details.
11553     details->set(kThreadDetailsCurrentThreadIndex,
11554                  isolate->heap()->true_value());
11555     details->set(kThreadDetailsThreadIdIndex,
11556                  Smi::FromInt(ThreadId::Current().ToInteger()));
11557   } else {
11558     // Find the thread with the requested index.
11559     int n = 1;
11560     ThreadState* thread =
11561         isolate->thread_manager()->FirstThreadStateInUse();
11562     while (index != n && thread != NULL) {
11563       thread = thread->Next();
11564       n++;
11565     }
11566     if (thread == NULL) {
11567       return isolate->heap()->undefined_value();
11568     }
11569
11570     // Fill the details.
11571     details->set(kThreadDetailsCurrentThreadIndex,
11572                  isolate->heap()->false_value());
11573     details->set(kThreadDetailsThreadIdIndex,
11574                  Smi::FromInt(thread->id().ToInteger()));
11575   }
11576
11577   // Convert to JS array and return.
11578   return *isolate->factory()->NewJSArrayWithElements(details);
11579 }
11580
11581
11582 // Sets the disable break state
11583 // args[0]: disable break state
11584 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
11585   HandleScope scope(isolate);
11586   ASSERT(args.length() == 1);
11587   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
11588   isolate->debug()->set_disable_break(disable_break);
11589   return  isolate->heap()->undefined_value();
11590 }
11591
11592
11593 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
11594   HandleScope scope(isolate);
11595   ASSERT(args.length() == 1);
11596
11597   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11598   Handle<SharedFunctionInfo> shared(fun->shared());
11599   // Find the number of break points
11600   Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
11601   if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
11602   // Return array as JS array
11603   return *isolate->factory()->NewJSArrayWithElements(
11604       Handle<FixedArray>::cast(break_locations));
11605 }
11606
11607
11608 // Return the value of breakpoint_relocation flag
11609 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllowBreakPointRelocation) {
11610   return Smi::FromInt(FLAG_breakpoint_relocation);
11611 }
11612
11613
11614 // Set a break point in a function
11615 // args[0]: function
11616 // args[1]: number: break source position (within the function source)
11617 // args[2]: number: break point object
11618 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
11619   HandleScope scope(isolate);
11620   ASSERT(args.length() == 3);
11621   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11622   Handle<SharedFunctionInfo> shared(fun->shared());
11623   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11624   RUNTIME_ASSERT(source_position >= 0);
11625   Handle<Object> break_point_object_arg = args.at<Object>(2);
11626
11627   // Set break point.
11628   isolate->debug()->SetBreakPoint(shared, break_point_object_arg,
11629                                   &source_position);
11630
11631   return Smi::FromInt(source_position);
11632 }
11633
11634
11635 Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
11636                                                 Handle<Script> script,
11637                                                 int position) {
11638   // Iterate the heap looking for SharedFunctionInfo generated from the
11639   // script. The inner most SharedFunctionInfo containing the source position
11640   // for the requested break point is found.
11641   // NOTE: This might require several heap iterations. If the SharedFunctionInfo
11642   // which is found is not compiled it is compiled and the heap is iterated
11643   // again as the compilation might create inner functions from the newly
11644   // compiled function and the actual requested break point might be in one of
11645   // these functions.
11646   bool done = false;
11647   // The current candidate for the source position:
11648   int target_start_position = RelocInfo::kNoPosition;
11649   Handle<SharedFunctionInfo> target;
11650   while (!done) {
11651     { // Extra scope for iterator and no-allocation.
11652       isolate->heap()->EnsureHeapIsIterable();
11653       AssertNoAllocation no_alloc_during_heap_iteration;
11654       HeapIterator iterator;
11655       for (HeapObject* obj = iterator.next();
11656            obj != NULL; obj = iterator.next()) {
11657         if (obj->IsSharedFunctionInfo()) {
11658           Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
11659           if (shared->script() == *script) {
11660             // If the SharedFunctionInfo found has the requested script data and
11661             // contains the source position it is a candidate.
11662             int start_position = shared->function_token_position();
11663             if (start_position == RelocInfo::kNoPosition) {
11664               start_position = shared->start_position();
11665             }
11666             if (start_position <= position &&
11667                 position <= shared->end_position()) {
11668               // If there is no candidate or this function is within the current
11669               // candidate this is the new candidate.
11670               if (target.is_null()) {
11671                 target_start_position = start_position;
11672                 target = shared;
11673               } else {
11674                 if (target_start_position == start_position &&
11675                     shared->end_position() == target->end_position()) {
11676                     // If a top-level function contain only one function
11677                     // declartion the source for the top-level and the
11678                     // function is the same. In that case prefer the non
11679                     // top-level function.
11680                   if (!shared->is_toplevel()) {
11681                     target_start_position = start_position;
11682                     target = shared;
11683                   }
11684                 } else if (target_start_position <= start_position &&
11685                            shared->end_position() <= target->end_position()) {
11686                   // This containment check includes equality as a function
11687                   // inside a top-level function can share either start or end
11688                   // position with the top-level function.
11689                   target_start_position = start_position;
11690                   target = shared;
11691                 }
11692               }
11693             }
11694           }
11695         }
11696       }  // End for loop.
11697     }  // End No allocation scope.
11698
11699     if (target.is_null()) {
11700       return isolate->heap()->undefined_value();
11701     }
11702
11703     // If the candidate found is compiled we are done. NOTE: when lazy
11704     // compilation of inner functions is introduced some additional checking
11705     // needs to be done here to compile inner functions.
11706     done = target->is_compiled();
11707     if (!done) {
11708       // If the candidate is not compiled compile it to reveal any inner
11709       // functions which might contain the requested source position.
11710       SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION);
11711     }
11712   }  // End while loop.
11713
11714   return *target;
11715 }
11716
11717
11718 // Changes the state of a break point in a script and returns source position
11719 // where break point was set. NOTE: Regarding performance see the NOTE for
11720 // GetScriptFromScriptData.
11721 // args[0]: script to set break point in
11722 // args[1]: number: break source position (within the script source)
11723 // args[2]: number: break point object
11724 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
11725   HandleScope scope(isolate);
11726   ASSERT(args.length() == 3);
11727   CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
11728   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11729   RUNTIME_ASSERT(source_position >= 0);
11730   Handle<Object> break_point_object_arg = args.at<Object>(2);
11731
11732   // Get the script from the script wrapper.
11733   RUNTIME_ASSERT(wrapper->value()->IsScript());
11734   Handle<Script> script(Script::cast(wrapper->value()));
11735
11736   Object* result = Runtime::FindSharedFunctionInfoInScript(
11737       isolate, script, source_position);
11738   if (!result->IsUndefined()) {
11739     Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
11740     // Find position within function. The script position might be before the
11741     // source position of the first function.
11742     int position;
11743     if (shared->start_position() > source_position) {
11744       position = 0;
11745     } else {
11746       position = source_position - shared->start_position();
11747     }
11748     isolate->debug()->SetBreakPoint(shared, break_point_object_arg, &position);
11749     position += shared->start_position();
11750     return Smi::FromInt(position);
11751   }
11752   return  isolate->heap()->undefined_value();
11753 }
11754
11755
11756 // Clear a break point
11757 // args[0]: number: break point object
11758 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
11759   HandleScope scope(isolate);
11760   ASSERT(args.length() == 1);
11761   Handle<Object> break_point_object_arg = args.at<Object>(0);
11762
11763   // Clear break point.
11764   isolate->debug()->ClearBreakPoint(break_point_object_arg);
11765
11766   return isolate->heap()->undefined_value();
11767 }
11768
11769
11770 // Change the state of break on exceptions.
11771 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
11772 // args[1]: Boolean indicating on/off.
11773 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
11774   HandleScope scope(isolate);
11775   ASSERT(args.length() == 2);
11776   RUNTIME_ASSERT(args[0]->IsNumber());
11777   CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
11778
11779   // If the number doesn't match an enum value, the ChangeBreakOnException
11780   // function will default to affecting caught exceptions.
11781   ExceptionBreakType type =
11782       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11783   // Update break point state.
11784   isolate->debug()->ChangeBreakOnException(type, enable);
11785   return isolate->heap()->undefined_value();
11786 }
11787
11788
11789 // Returns the state of break on exceptions
11790 // args[0]: boolean indicating uncaught exceptions
11791 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
11792   HandleScope scope(isolate);
11793   ASSERT(args.length() == 1);
11794   RUNTIME_ASSERT(args[0]->IsNumber());
11795
11796   ExceptionBreakType type =
11797       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11798   bool result = isolate->debug()->IsBreakOnException(type);
11799   return Smi::FromInt(result);
11800 }
11801
11802
11803 // Prepare for stepping
11804 // args[0]: break id for checking execution state
11805 // args[1]: step action from the enumeration StepAction
11806 // args[2]: number of times to perform the step, for step out it is the number
11807 //          of frames to step down.
11808 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
11809   HandleScope scope(isolate);
11810   ASSERT(args.length() == 3);
11811   // Check arguments.
11812   Object* check;
11813   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11814       RUNTIME_ARGUMENTS(isolate, args));
11815     if (!maybe_check->ToObject(&check)) return maybe_check;
11816   }
11817   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
11818     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11819   }
11820
11821   // Get the step action and check validity.
11822   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
11823   if (step_action != StepIn &&
11824       step_action != StepNext &&
11825       step_action != StepOut &&
11826       step_action != StepInMin &&
11827       step_action != StepMin) {
11828     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11829   }
11830
11831   // Get the number of steps.
11832   int step_count = NumberToInt32(args[2]);
11833   if (step_count < 1) {
11834     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11835   }
11836
11837   // Clear all current stepping setup.
11838   isolate->debug()->ClearStepping();
11839
11840   // Prepare step.
11841   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
11842                                 step_count);
11843   return isolate->heap()->undefined_value();
11844 }
11845
11846
11847 // Clear all stepping set by PrepareStep.
11848 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
11849   HandleScope scope(isolate);
11850   ASSERT(args.length() == 0);
11851   isolate->debug()->ClearStepping();
11852   return isolate->heap()->undefined_value();
11853 }
11854
11855
11856 // Creates a copy of the with context chain. The copy of the context chain is
11857 // is linked to the function context supplied.
11858 static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
11859                                                    Handle<JSFunction> function,
11860                                                    Handle<Context> base,
11861                                                    JavaScriptFrame* frame,
11862                                                    int inlined_jsframe_index) {
11863   HandleScope scope(isolate);
11864   List<Handle<ScopeInfo> > scope_chain;
11865   List<Handle<Context> > context_chain;
11866
11867   ScopeIterator it(isolate, frame, inlined_jsframe_index);
11868   for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
11869          it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
11870     ASSERT(!it.Done());
11871     scope_chain.Add(it.CurrentScopeInfo());
11872     context_chain.Add(it.CurrentContext());
11873   }
11874
11875   // At the end of the chain. Return the base context to link to.
11876   Handle<Context> context = base;
11877
11878   // Iteratively copy and or materialize the nested contexts.
11879   while (!scope_chain.is_empty()) {
11880     Handle<ScopeInfo> scope_info = scope_chain.RemoveLast();
11881     Handle<Context> current = context_chain.RemoveLast();
11882     ASSERT(!(scope_info->HasContext() & current.is_null()));
11883
11884     if (scope_info->Type() == CATCH_SCOPE) {
11885       Handle<String> name(String::cast(current->extension()));
11886       Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX));
11887       context =
11888           isolate->factory()->NewCatchContext(function,
11889                                               context,
11890                                               name,
11891                                               thrown_object);
11892     } else if (scope_info->Type() == BLOCK_SCOPE) {
11893       // Materialize the contents of the block scope into a JSObject.
11894       Handle<JSObject> block_scope_object =
11895           MaterializeBlockScope(isolate, current);
11896       if (block_scope_object.is_null()) {
11897         return Handle<Context>::null();
11898       }
11899       // Allocate a new function context for the debug evaluation and set the
11900       // extension object.
11901       Handle<Context> new_context =
11902           isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11903                                                  function);
11904       new_context->set_extension(*block_scope_object);
11905       new_context->set_previous(*context);
11906       context = new_context;
11907     } else {
11908       ASSERT(scope_info->Type() == WITH_SCOPE);
11909       ASSERT(current->IsWithContext());
11910       Handle<JSObject> extension(JSObject::cast(current->extension()));
11911       context =
11912           isolate->factory()->NewWithContext(function, context, extension);
11913     }
11914   }
11915
11916   return scope.CloseAndEscape(context);
11917 }
11918
11919
11920 // Helper function to find or create the arguments object for
11921 // Runtime_DebugEvaluate.
11922 static Handle<Object> GetArgumentsObject(Isolate* isolate,
11923                                          JavaScriptFrame* frame,
11924                                          FrameInspector* frame_inspector,
11925                                          Handle<ScopeInfo> scope_info,
11926                                          Handle<Context> function_context) {
11927   // Try to find the value of 'arguments' to pass as parameter. If it is not
11928   // found (that is the debugged function does not reference 'arguments' and
11929   // does not support eval) then create an 'arguments' object.
11930   int index;
11931   if (scope_info->StackLocalCount() > 0) {
11932     index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
11933     if (index != -1) {
11934       return Handle<Object>(frame->GetExpression(index), isolate);
11935     }
11936   }
11937
11938   if (scope_info->HasHeapAllocatedLocals()) {
11939     VariableMode mode;
11940     InitializationFlag init_flag;
11941     index = scope_info->ContextSlotIndex(
11942         isolate->heap()->arguments_symbol(), &mode, &init_flag);
11943     if (index != -1) {
11944       return Handle<Object>(function_context->get(index), isolate);
11945     }
11946   }
11947
11948   Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
11949   int length = frame_inspector->GetParametersCount();
11950   Handle<JSObject> arguments =
11951       isolate->factory()->NewArgumentsObject(function, length);
11952   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
11953
11954   AssertNoAllocation no_gc;
11955   WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
11956   for (int i = 0; i < length; i++) {
11957     array->set(i, frame_inspector->GetParameter(i), mode);
11958   }
11959   arguments->set_elements(*array);
11960   return arguments;
11961 }
11962
11963
11964 static const char kSourceStr[] =
11965     "(function(arguments,__source__){return eval(__source__);})";
11966
11967
11968 // Evaluate a piece of JavaScript in the context of a stack frame for
11969 // debugging. This is accomplished by creating a new context which in its
11970 // extension part has all the parameters and locals of the function on the
11971 // stack frame. A function which calls eval with the code to evaluate is then
11972 // compiled in this context and called in this context. As this context
11973 // replaces the context of the function on the stack frame a new (empty)
11974 // function is created as well to be used as the closure for the context.
11975 // This function and the context acts as replacements for the function on the
11976 // stack frame presenting the same view of the values of parameters and
11977 // local variables as if the piece of JavaScript was evaluated at the point
11978 // where the function on the stack frame is currently stopped.
11979 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
11980   HandleScope scope(isolate);
11981
11982   // Check the execution state and decode arguments frame and source to be
11983   // evaluated.
11984   ASSERT(args.length() == 6);
11985   Object* check_result;
11986   { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
11987       RUNTIME_ARGUMENTS(isolate, args));
11988     if (!maybe_check_result->ToObject(&check_result)) {
11989       return maybe_check_result;
11990     }
11991   }
11992   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11993   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11994   CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
11995   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
11996   Handle<Object> additional_context(args[5]);
11997
11998   // Handle the processing of break.
11999   DisableBreak disable_break_save(disable_break);
12000
12001   // Get the frame where the debugging is performed.
12002   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12003   JavaScriptFrameIterator it(isolate, id);
12004   JavaScriptFrame* frame = it.frame();
12005   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12006   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12007   Handle<ScopeInfo> scope_info(function->shared()->scope_info());
12008   bool qml_mode = function->shared()->qml_mode();
12009
12010   // Traverse the saved contexts chain to find the active context for the
12011   // selected frame.
12012   SaveContext* save = FindSavedContextForFrame(isolate, frame);
12013
12014   SaveContext savex(isolate);
12015   isolate->set_context(*(save->context()));
12016
12017   // Create the (empty) function replacing the function on the stack frame for
12018   // the purpose of evaluating in the context created below. It is important
12019   // that this function does not describe any parameters and local variables
12020   // in the context. If it does then this will cause problems with the lookup
12021   // in Context::Lookup, where context slots for parameters and local variables
12022   // are looked at before the extension object.
12023   Handle<JSFunction> go_between =
12024       isolate->factory()->NewFunction(isolate->factory()->empty_string(),
12025                                       isolate->factory()->undefined_value());
12026   go_between->set_context(function->context());
12027 #ifdef DEBUG
12028   Handle<ScopeInfo> go_between_scope_info(go_between->shared()->scope_info());
12029   ASSERT(go_between_scope_info->ParameterCount() == 0);
12030   ASSERT(go_between_scope_info->ContextLocalCount() == 0);
12031 #endif
12032
12033   // Materialize the content of the local scope into a JSObject.
12034   Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector(
12035       isolate, frame, &frame_inspector);
12036   RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
12037
12038   // Allocate a new context for the debug evaluation and set the extension
12039   // object build.
12040   Handle<Context> context =
12041       isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
12042                                              go_between);
12043   context->set_extension(*local_scope);
12044   // Copy any with contexts present and chain them in front of this context.
12045   Handle<Context> frame_context(Context::cast(frame->context()));
12046   Handle<Context> function_context;
12047   // Get the function's context if it has one.
12048   if (scope_info->HasContext()) {
12049     function_context = Handle<Context>(frame_context->declaration_context());
12050   }
12051   context = CopyNestedScopeContextChain(isolate,
12052                                         go_between,
12053                                         context,
12054                                         frame,
12055                                         inlined_jsframe_index);
12056
12057   if (additional_context->IsJSObject()) {
12058     Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
12059     context =
12060         isolate->factory()->NewWithContext(go_between, context, extension);
12061   }
12062
12063   // Wrap the evaluation statement in a new function compiled in the newly
12064   // created context. The function has one parameter which has to be called
12065   // 'arguments'. This it to have access to what would have been 'arguments' in
12066   // the function being debugged.
12067   // function(arguments,__source__) {return eval(__source__);}
12068
12069   Handle<String> function_source =
12070       isolate->factory()->NewStringFromAscii(
12071           Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
12072
12073   // Currently, the eval code will be executed in non-strict mode,
12074   // even in the strict code context.
12075   Handle<SharedFunctionInfo> shared =
12076       Compiler::CompileEval(function_source,
12077                             context,
12078                             context->IsGlobalContext(),
12079                             CLASSIC_MODE,
12080                             RelocInfo::kNoPosition,
12081                             qml_mode);
12082   if (shared.is_null()) return Failure::Exception();
12083   Handle<JSFunction> compiled_function =
12084       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
12085
12086   // Invoke the result of the compilation to get the evaluation function.
12087   bool has_pending_exception;
12088   Handle<Object> receiver(frame->receiver(), isolate);
12089   Handle<Object> evaluation_function =
12090       Execution::Call(compiled_function, receiver, 0, NULL,
12091                       &has_pending_exception, false,
12092                       Handle<Object>(function->context()->qml_global()));
12093   if (has_pending_exception) return Failure::Exception();
12094
12095   Handle<Object> arguments = GetArgumentsObject(isolate,
12096                                                 frame,
12097                                                 &frame_inspector,
12098                                                 scope_info,
12099                                                 function_context);
12100
12101   // Invoke the evaluation function and return the result.
12102   Handle<Object> argv[] = { arguments, source };
12103   Handle<Object> result =
12104       Execution::Call(Handle<JSFunction>::cast(evaluation_function),
12105                       receiver,
12106                       ARRAY_SIZE(argv),
12107                       argv,
12108                       &has_pending_exception);
12109   if (has_pending_exception) return Failure::Exception();
12110
12111   // Skip the global proxy as it has no properties and always delegates to the
12112   // real global object.
12113   if (result->IsJSGlobalProxy()) {
12114     result = Handle<JSObject>(JSObject::cast(result->GetPrototype()));
12115   }
12116
12117   return *result;
12118 }
12119
12120
12121 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
12122   HandleScope scope(isolate);
12123
12124   // Check the execution state and decode arguments frame and source to be
12125   // evaluated.
12126   ASSERT(args.length() == 4);
12127   Object* check_result;
12128   { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
12129       RUNTIME_ARGUMENTS(isolate, args));
12130     if (!maybe_check_result->ToObject(&check_result)) {
12131       return maybe_check_result;
12132     }
12133   }
12134   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12135   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
12136   Handle<Object> additional_context(args[3]);
12137
12138   // Handle the processing of break.
12139   DisableBreak disable_break_save(disable_break);
12140
12141   // Enter the top context from before the debugger was invoked.
12142   SaveContext save(isolate);
12143   SaveContext* top = &save;
12144   while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
12145     top = top->prev();
12146   }
12147   if (top != NULL) {
12148     isolate->set_context(*top->context());
12149   }
12150
12151   // Get the global context now set to the top context from before the
12152   // debugger was invoked.
12153   Handle<Context> context = isolate->global_context();
12154
12155   bool is_global = true;
12156
12157   if (additional_context->IsJSObject()) {
12158     // Create a new with context with the additional context information between
12159     // the context of the debugged function and the eval code to be executed.
12160     context = isolate->factory()->NewWithContext(
12161         Handle<JSFunction>(context->closure()),
12162         context,
12163         Handle<JSObject>::cast(additional_context));
12164     is_global = false;
12165   }
12166
12167   // Compile the source to be evaluated.
12168   // Currently, the eval code will be executed in non-strict mode,
12169   // even in the strict code context.
12170   Handle<SharedFunctionInfo> shared =
12171       Compiler::CompileEval(source,
12172                             context,
12173                             is_global,
12174                             CLASSIC_MODE,
12175                             RelocInfo::kNoPosition,
12176                             false);
12177   if (shared.is_null()) return Failure::Exception();
12178   Handle<JSFunction> compiled_function =
12179       Handle<JSFunction>(
12180           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
12181                                                                 context));
12182
12183   // Invoke the result of the compilation to get the evaluation function.
12184   bool has_pending_exception;
12185   Handle<Object> receiver = isolate->global();
12186   Handle<Object> result =
12187     Execution::Call(compiled_function, receiver, 0, NULL,
12188                     &has_pending_exception);
12189   // Clear the oneshot breakpoints so that the debugger does not step further.
12190   isolate->debug()->ClearStepping();
12191   if (has_pending_exception) return Failure::Exception();
12192   return *result;
12193 }
12194
12195
12196 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
12197   HandleScope scope(isolate);
12198   ASSERT(args.length() == 0);
12199
12200   // Fill the script objects.
12201   Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
12202
12203   // Convert the script objects to proper JS objects.
12204   for (int i = 0; i < instances->length(); i++) {
12205     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
12206     // Get the script wrapper in a local handle before calling GetScriptWrapper,
12207     // because using
12208     //   instances->set(i, *GetScriptWrapper(script))
12209     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12210     // already have dereferenced the instances handle.
12211     Handle<JSValue> wrapper = GetScriptWrapper(script);
12212     instances->set(i, *wrapper);
12213   }
12214
12215   // Return result as a JS array.
12216   Handle<JSObject> result =
12217       isolate->factory()->NewJSObject(isolate->array_function());
12218   isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12219   return *result;
12220 }
12221
12222
12223 // Helper function used by Runtime_DebugReferencedBy below.
12224 static int DebugReferencedBy(HeapIterator* iterator,
12225                              JSObject* target,
12226                              Object* instance_filter, int max_references,
12227                              FixedArray* instances, int instances_size,
12228                              JSFunction* arguments_function) {
12229   NoHandleAllocation ha;
12230   AssertNoAllocation no_alloc;
12231
12232   // Iterate the heap.
12233   int count = 0;
12234   JSObject* last = NULL;
12235   HeapObject* heap_obj = NULL;
12236   while (((heap_obj = iterator->next()) != NULL) &&
12237          (max_references == 0 || count < max_references)) {
12238     // Only look at all JSObjects.
12239     if (heap_obj->IsJSObject()) {
12240       // Skip context extension objects and argument arrays as these are
12241       // checked in the context of functions using them.
12242       JSObject* obj = JSObject::cast(heap_obj);
12243       if (obj->IsJSContextExtensionObject() ||
12244           obj->map()->constructor() == arguments_function) {
12245         continue;
12246       }
12247
12248       // Check if the JS object has a reference to the object looked for.
12249       if (obj->ReferencesObject(target)) {
12250         // Check instance filter if supplied. This is normally used to avoid
12251         // references from mirror objects (see Runtime_IsInPrototypeChain).
12252         if (!instance_filter->IsUndefined()) {
12253           Object* V = obj;
12254           while (true) {
12255             Object* prototype = V->GetPrototype();
12256             if (prototype->IsNull()) {
12257               break;
12258             }
12259             if (instance_filter == prototype) {
12260               obj = NULL;  // Don't add this object.
12261               break;
12262             }
12263             V = prototype;
12264           }
12265         }
12266
12267         if (obj != NULL) {
12268           // Valid reference found add to instance array if supplied an update
12269           // count.
12270           if (instances != NULL && count < instances_size) {
12271             instances->set(count, obj);
12272           }
12273           last = obj;
12274           count++;
12275         }
12276       }
12277     }
12278   }
12279
12280   // Check for circular reference only. This can happen when the object is only
12281   // referenced from mirrors and has a circular reference in which case the
12282   // object is not really alive and would have been garbage collected if not
12283   // referenced from the mirror.
12284   if (count == 1 && last == target) {
12285     count = 0;
12286   }
12287
12288   // Return the number of referencing objects found.
12289   return count;
12290 }
12291
12292
12293 // Scan the heap for objects with direct references to an object
12294 // args[0]: the object to find references to
12295 // args[1]: constructor function for instances to exclude (Mirror)
12296 // args[2]: the the maximum number of objects to return
12297 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12298   ASSERT(args.length() == 3);
12299
12300   // First perform a full GC in order to avoid references from dead objects.
12301   isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12302                                      "%DebugReferencedBy");
12303   // The heap iterator reserves the right to do a GC to make the heap iterable.
12304   // Due to the GC above we know it won't need to do that, but it seems cleaner
12305   // to get the heap iterator constructed before we start having unprotected
12306   // Object* locals that are not protected by handles.
12307
12308   // Check parameters.
12309   CONVERT_ARG_CHECKED(JSObject, target, 0);
12310   Object* instance_filter = args[1];
12311   RUNTIME_ASSERT(instance_filter->IsUndefined() ||
12312                  instance_filter->IsJSObject());
12313   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
12314   RUNTIME_ASSERT(max_references >= 0);
12315
12316
12317   // Get the constructor function for context extension and arguments array.
12318   JSObject* arguments_boilerplate =
12319       isolate->context()->global_context()->arguments_boilerplate();
12320   JSFunction* arguments_function =
12321       JSFunction::cast(arguments_boilerplate->map()->constructor());
12322
12323   // Get the number of referencing objects.
12324   int count;
12325   HeapIterator heap_iterator;
12326   count = DebugReferencedBy(&heap_iterator,
12327                             target, instance_filter, max_references,
12328                             NULL, 0, arguments_function);
12329
12330   // Allocate an array to hold the result.
12331   Object* object;
12332   { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12333     if (!maybe_object->ToObject(&object)) return maybe_object;
12334   }
12335   FixedArray* instances = FixedArray::cast(object);
12336
12337   // Fill the referencing objects.
12338   // AllocateFixedArray above does not make the heap non-iterable.
12339   ASSERT(HEAP->IsHeapIterable());
12340   HeapIterator heap_iterator2;
12341   count = DebugReferencedBy(&heap_iterator2,
12342                             target, instance_filter, max_references,
12343                             instances, count, arguments_function);
12344
12345   // Return result as JS array.
12346   Object* result;
12347   MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12348       isolate->context()->global_context()->array_function());
12349   if (!maybe_result->ToObject(&result)) return maybe_result;
12350   return JSArray::cast(result)->SetContent(instances);
12351 }
12352
12353
12354 // Helper function used by Runtime_DebugConstructedBy below.
12355 static int DebugConstructedBy(HeapIterator* iterator,
12356                               JSFunction* constructor,
12357                               int max_references,
12358                               FixedArray* instances,
12359                               int instances_size) {
12360   AssertNoAllocation no_alloc;
12361
12362   // Iterate the heap.
12363   int count = 0;
12364   HeapObject* heap_obj = NULL;
12365   while (((heap_obj = iterator->next()) != NULL) &&
12366          (max_references == 0 || count < max_references)) {
12367     // Only look at all JSObjects.
12368     if (heap_obj->IsJSObject()) {
12369       JSObject* obj = JSObject::cast(heap_obj);
12370       if (obj->map()->constructor() == constructor) {
12371         // Valid reference found add to instance array if supplied an update
12372         // count.
12373         if (instances != NULL && count < instances_size) {
12374           instances->set(count, obj);
12375         }
12376         count++;
12377       }
12378     }
12379   }
12380
12381   // Return the number of referencing objects found.
12382   return count;
12383 }
12384
12385
12386 // Scan the heap for objects constructed by a specific function.
12387 // args[0]: the constructor to find instances of
12388 // args[1]: the the maximum number of objects to return
12389 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
12390   ASSERT(args.length() == 2);
12391
12392   // First perform a full GC in order to avoid dead objects.
12393   isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12394                                      "%DebugConstructedBy");
12395
12396   // Check parameters.
12397   CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
12398   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
12399   RUNTIME_ASSERT(max_references >= 0);
12400
12401   // Get the number of referencing objects.
12402   int count;
12403   HeapIterator heap_iterator;
12404   count = DebugConstructedBy(&heap_iterator,
12405                              constructor,
12406                              max_references,
12407                              NULL,
12408                              0);
12409
12410   // Allocate an array to hold the result.
12411   Object* object;
12412   { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12413     if (!maybe_object->ToObject(&object)) return maybe_object;
12414   }
12415   FixedArray* instances = FixedArray::cast(object);
12416
12417   ASSERT(HEAP->IsHeapIterable());
12418   // Fill the referencing objects.
12419   HeapIterator heap_iterator2;
12420   count = DebugConstructedBy(&heap_iterator2,
12421                              constructor,
12422                              max_references,
12423                              instances,
12424                              count);
12425
12426   // Return result as JS array.
12427   Object* result;
12428   { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12429           isolate->context()->global_context()->array_function());
12430     if (!maybe_result->ToObject(&result)) return maybe_result;
12431   }
12432   return JSArray::cast(result)->SetContent(instances);
12433 }
12434
12435
12436 // Find the effective prototype object as returned by __proto__.
12437 // args[0]: the object to find the prototype for.
12438 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
12439   ASSERT(args.length() == 1);
12440
12441   CONVERT_ARG_CHECKED(JSObject, obj, 0);
12442
12443   // Use the __proto__ accessor.
12444   return Accessors::ObjectPrototype.getter(obj, NULL);
12445 }
12446
12447
12448 // Patches script source (should be called upon BeforeCompile event).
12449 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
12450   HandleScope scope(isolate);
12451   ASSERT(args.length() == 2);
12452
12453   CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
12454   Handle<String> source(String::cast(args[1]));
12455
12456   RUNTIME_ASSERT(script_wrapper->value()->IsScript());
12457   Handle<Script> script(Script::cast(script_wrapper->value()));
12458
12459   int compilation_state = Smi::cast(script->compilation_state())->value();
12460   RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
12461   script->set_source(*source);
12462
12463   return isolate->heap()->undefined_value();
12464 }
12465
12466
12467 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
12468   ASSERT(args.length() == 0);
12469   CPU::DebugBreak();
12470   return isolate->heap()->undefined_value();
12471 }
12472
12473
12474 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
12475 #ifdef DEBUG
12476   HandleScope scope(isolate);
12477   ASSERT(args.length() == 1);
12478   // Get the function and make sure it is compiled.
12479   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12480   Handle<SharedFunctionInfo> shared(func->shared());
12481   if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
12482     return Failure::Exception();
12483   }
12484   func->code()->PrintLn();
12485 #endif  // DEBUG
12486   return isolate->heap()->undefined_value();
12487 }
12488
12489
12490 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
12491 #ifdef DEBUG
12492   HandleScope scope(isolate);
12493   ASSERT(args.length() == 1);
12494   // Get the function and make sure it is compiled.
12495   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12496   Handle<SharedFunctionInfo> shared(func->shared());
12497   if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
12498     return Failure::Exception();
12499   }
12500   shared->construct_stub()->PrintLn();
12501 #endif  // DEBUG
12502   return isolate->heap()->undefined_value();
12503 }
12504
12505
12506 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
12507   NoHandleAllocation ha;
12508   ASSERT(args.length() == 1);
12509
12510   CONVERT_ARG_CHECKED(JSFunction, f, 0);
12511   return f->shared()->inferred_name();
12512 }
12513
12514
12515 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
12516                                             Script* script,
12517                                             FixedArray* buffer) {
12518   AssertNoAllocation no_allocations;
12519   int counter = 0;
12520   int buffer_size = buffer->length();
12521   for (HeapObject* obj = iterator->next();
12522        obj != NULL;
12523        obj = iterator->next()) {
12524     ASSERT(obj != NULL);
12525     if (!obj->IsSharedFunctionInfo()) {
12526       continue;
12527     }
12528     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
12529     if (shared->script() != script) {
12530       continue;
12531     }
12532     if (counter < buffer_size) {
12533       buffer->set(counter, shared);
12534     }
12535     counter++;
12536   }
12537   return counter;
12538 }
12539
12540 // For a script finds all SharedFunctionInfo's in the heap that points
12541 // to this script. Returns JSArray of SharedFunctionInfo wrapped
12542 // in OpaqueReferences.
12543 RUNTIME_FUNCTION(MaybeObject*,
12544                  Runtime_LiveEditFindSharedFunctionInfosForScript) {
12545   ASSERT(args.length() == 1);
12546   HandleScope scope(isolate);
12547   CONVERT_ARG_CHECKED(JSValue, script_value, 0);
12548
12549
12550   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
12551
12552   const int kBufferSize = 32;
12553
12554   Handle<FixedArray> array;
12555   array = isolate->factory()->NewFixedArray(kBufferSize);
12556   int number;
12557   {
12558     isolate->heap()->EnsureHeapIsIterable();
12559     AssertNoAllocation no_allocations;
12560     HeapIterator heap_iterator;
12561     Script* scr = *script;
12562     FixedArray* arr = *array;
12563     number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12564   }
12565   if (number > kBufferSize) {
12566     array = isolate->factory()->NewFixedArray(number);
12567     isolate->heap()->EnsureHeapIsIterable();
12568     AssertNoAllocation no_allocations;
12569     HeapIterator heap_iterator;
12570     Script* scr = *script;
12571     FixedArray* arr = *array;
12572     FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12573   }
12574
12575   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
12576   result->set_length(Smi::FromInt(number));
12577
12578   LiveEdit::WrapSharedFunctionInfos(result);
12579
12580   return *result;
12581 }
12582
12583 // For a script calculates compilation information about all its functions.
12584 // The script source is explicitly specified by the second argument.
12585 // The source of the actual script is not used, however it is important that
12586 // all generated code keeps references to this particular instance of script.
12587 // Returns a JSArray of compilation infos. The array is ordered so that
12588 // each function with all its descendant is always stored in a continues range
12589 // with the function itself going first. The root function is a script function.
12590 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
12591   ASSERT(args.length() == 2);
12592   HandleScope scope(isolate);
12593   CONVERT_ARG_CHECKED(JSValue, script, 0);
12594   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12595   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
12596
12597   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
12598
12599   if (isolate->has_pending_exception()) {
12600     return Failure::Exception();
12601   }
12602
12603   return result;
12604 }
12605
12606 // Changes the source of the script to a new_source.
12607 // If old_script_name is provided (i.e. is a String), also creates a copy of
12608 // the script with its original source and sends notification to debugger.
12609 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
12610   ASSERT(args.length() == 3);
12611   HandleScope scope(isolate);
12612   CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
12613   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
12614   Handle<Object> old_script_name(args[2], isolate);
12615
12616   RUNTIME_ASSERT(original_script_value->value()->IsScript());
12617   Handle<Script> original_script(Script::cast(original_script_value->value()));
12618
12619   Object* old_script = LiveEdit::ChangeScriptSource(original_script,
12620                                                     new_source,
12621                                                     old_script_name);
12622
12623   if (old_script->IsScript()) {
12624     Handle<Script> script_handle(Script::cast(old_script));
12625     return *(GetScriptWrapper(script_handle));
12626   } else {
12627     return isolate->heap()->null_value();
12628   }
12629 }
12630
12631
12632 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
12633   ASSERT(args.length() == 1);
12634   HandleScope scope(isolate);
12635   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
12636   return LiveEdit::FunctionSourceUpdated(shared_info);
12637 }
12638
12639
12640 // Replaces code of SharedFunctionInfo with a new one.
12641 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
12642   ASSERT(args.length() == 2);
12643   HandleScope scope(isolate);
12644   CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
12645   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
12646
12647   return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
12648 }
12649
12650 // Connects SharedFunctionInfo to another script.
12651 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
12652   ASSERT(args.length() == 2);
12653   HandleScope scope(isolate);
12654   Handle<Object> function_object(args[0], isolate);
12655   Handle<Object> script_object(args[1], isolate);
12656
12657   if (function_object->IsJSValue()) {
12658     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
12659     if (script_object->IsJSValue()) {
12660       RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
12661       Script* script = Script::cast(JSValue::cast(*script_object)->value());
12662       script_object = Handle<Object>(script, isolate);
12663     }
12664
12665     LiveEdit::SetFunctionScript(function_wrapper, script_object);
12666   } else {
12667     // Just ignore this. We may not have a SharedFunctionInfo for some functions
12668     // and we check it in this function.
12669   }
12670
12671   return isolate->heap()->undefined_value();
12672 }
12673
12674
12675 // In a code of a parent function replaces original function as embedded object
12676 // with a substitution one.
12677 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
12678   ASSERT(args.length() == 3);
12679   HandleScope scope(isolate);
12680
12681   CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
12682   CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
12683   CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
12684
12685   LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
12686                                        subst_wrapper);
12687
12688   return isolate->heap()->undefined_value();
12689 }
12690
12691
12692 // Updates positions of a shared function info (first parameter) according
12693 // to script source change. Text change is described in second parameter as
12694 // array of groups of 3 numbers:
12695 // (change_begin, change_end, change_end_new_position).
12696 // Each group describes a change in text; groups are sorted by change_begin.
12697 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
12698   ASSERT(args.length() == 2);
12699   HandleScope scope(isolate);
12700   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12701   CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
12702
12703   return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
12704 }
12705
12706
12707 // For array of SharedFunctionInfo's (each wrapped in JSValue)
12708 // checks that none of them have activations on stacks (of any thread).
12709 // Returns array of the same length with corresponding results of
12710 // LiveEdit::FunctionPatchabilityStatus type.
12711 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
12712   ASSERT(args.length() == 2);
12713   HandleScope scope(isolate);
12714   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12715   CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
12716
12717   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
12718 }
12719
12720 // Compares 2 strings line-by-line, then token-wise and returns diff in form
12721 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
12722 // of diff chunks.
12723 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
12724   ASSERT(args.length() == 2);
12725   HandleScope scope(isolate);
12726   CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
12727   CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
12728
12729   return *LiveEdit::CompareStrings(s1, s2);
12730 }
12731
12732
12733 // A testing entry. Returns statement position which is the closest to
12734 // source_position.
12735 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
12736   ASSERT(args.length() == 2);
12737   HandleScope scope(isolate);
12738   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12739   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12740
12741   Handle<Code> code(function->code(), isolate);
12742
12743   if (code->kind() != Code::FUNCTION &&
12744       code->kind() != Code::OPTIMIZED_FUNCTION) {
12745     return isolate->heap()->undefined_value();
12746   }
12747
12748   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
12749   int closest_pc = 0;
12750   int distance = kMaxInt;
12751   while (!it.done()) {
12752     int statement_position = static_cast<int>(it.rinfo()->data());
12753     // Check if this break point is closer that what was previously found.
12754     if (source_position <= statement_position &&
12755         statement_position - source_position < distance) {
12756       closest_pc =
12757           static_cast<int>(it.rinfo()->pc() - code->instruction_start());
12758       distance = statement_position - source_position;
12759       // Check whether we can't get any closer.
12760       if (distance == 0) break;
12761     }
12762     it.next();
12763   }
12764
12765   return Smi::FromInt(closest_pc);
12766 }
12767
12768
12769 // Calls specified function with or without entering the debugger.
12770 // This is used in unit tests to run code as if debugger is entered or simply
12771 // to have a stack with C++ frame in the middle.
12772 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
12773   ASSERT(args.length() == 2);
12774   HandleScope scope(isolate);
12775   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12776   CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
12777
12778   Handle<Object> result;
12779   bool pending_exception;
12780   {
12781     if (without_debugger) {
12782       result = Execution::Call(function, isolate->global(), 0, NULL,
12783                                &pending_exception);
12784     } else {
12785       EnterDebugger enter_debugger;
12786       result = Execution::Call(function, isolate->global(), 0, NULL,
12787                                &pending_exception);
12788     }
12789   }
12790   if (!pending_exception) {
12791     return *result;
12792   } else {
12793     return Failure::Exception();
12794   }
12795 }
12796
12797
12798 // Sets a v8 flag.
12799 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
12800   CONVERT_ARG_CHECKED(String, arg, 0);
12801   SmartArrayPointer<char> flags =
12802       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
12803   FlagList::SetFlagsFromString(*flags, StrLength(*flags));
12804   return isolate->heap()->undefined_value();
12805 }
12806
12807
12808 // Performs a GC.
12809 // Presently, it only does a full GC.
12810 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
12811   isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
12812   return isolate->heap()->undefined_value();
12813 }
12814
12815
12816 // Gets the current heap usage.
12817 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
12818   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
12819   if (!Smi::IsValid(usage)) {
12820     return *isolate->factory()->NewNumberFromInt(usage);
12821   }
12822   return Smi::FromInt(usage);
12823 }
12824
12825
12826 // Captures a live object list from the present heap.
12827 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLOLEnabled) {
12828 #ifdef LIVE_OBJECT_LIST
12829   return isolate->heap()->true_value();
12830 #else
12831   return isolate->heap()->false_value();
12832 #endif
12833 }
12834
12835
12836 // Captures a live object list from the present heap.
12837 RUNTIME_FUNCTION(MaybeObject*, Runtime_CaptureLOL) {
12838 #ifdef LIVE_OBJECT_LIST
12839   return LiveObjectList::Capture();
12840 #else
12841   return isolate->heap()->undefined_value();
12842 #endif
12843 }
12844
12845
12846 // Deletes the specified live object list.
12847 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) {
12848 #ifdef LIVE_OBJECT_LIST
12849   CONVERT_SMI_ARG_CHECKED(id, 0);
12850   bool success = LiveObjectList::Delete(id);
12851   return isolate->heap()->ToBoolean(success);
12852 #else
12853   return isolate->heap()->undefined_value();
12854 #endif
12855 }
12856
12857
12858 // Generates the response to a debugger request for a dump of the objects
12859 // contained in the difference between the captured live object lists
12860 // specified by id1 and id2.
12861 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12862 // dumped.
12863 RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) {
12864 #ifdef LIVE_OBJECT_LIST
12865   HandleScope scope;
12866   CONVERT_SMI_ARG_CHECKED(id1, 0);
12867   CONVERT_SMI_ARG_CHECKED(id2, 1);
12868   CONVERT_SMI_ARG_CHECKED(start, 2);
12869   CONVERT_SMI_ARG_CHECKED(count, 3);
12870   CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 4);
12871   EnterDebugger enter_debugger;
12872   return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
12873 #else
12874   return isolate->heap()->undefined_value();
12875 #endif
12876 }
12877
12878
12879 // Gets the specified object as requested by the debugger.
12880 // This is only used for obj ids shown in live object lists.
12881 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) {
12882 #ifdef LIVE_OBJECT_LIST
12883   CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12884   Object* result = LiveObjectList::GetObj(obj_id);
12885   return result;
12886 #else
12887   return isolate->heap()->undefined_value();
12888 #endif
12889 }
12890
12891
12892 // Gets the obj id for the specified address if valid.
12893 // This is only used for obj ids shown in live object lists.
12894 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) {
12895 #ifdef LIVE_OBJECT_LIST
12896   HandleScope scope;
12897   CONVERT_ARG_HANDLE_CHECKED(String, address, 0);
12898   Object* result = LiveObjectList::GetObjId(address);
12899   return result;
12900 #else
12901   return isolate->heap()->undefined_value();
12902 #endif
12903 }
12904
12905
12906 // Gets the retainers that references the specified object alive.
12907 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) {
12908 #ifdef LIVE_OBJECT_LIST
12909   HandleScope scope;
12910   CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12911   RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject());
12912   RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean());
12913   RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi());
12914   RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi());
12915   CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 5);
12916
12917   Handle<JSObject> instance_filter;
12918   if (args[1]->IsJSObject()) {
12919     instance_filter = args.at<JSObject>(1);
12920   }
12921   bool verbose = false;
12922   if (args[2]->IsBoolean()) {
12923     verbose = args[2]->IsTrue();
12924   }
12925   int start = 0;
12926   if (args[3]->IsSmi()) {
12927     start = args.smi_at(3);
12928   }
12929   int limit = Smi::kMaxValue;
12930   if (args[4]->IsSmi()) {
12931     limit = args.smi_at(4);
12932   }
12933
12934   return LiveObjectList::GetObjRetainers(obj_id,
12935                                          instance_filter,
12936                                          verbose,
12937                                          start,
12938                                          limit,
12939                                          filter_obj);
12940 #else
12941   return isolate->heap()->undefined_value();
12942 #endif
12943 }
12944
12945
12946 // Gets the reference path between 2 objects.
12947 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) {
12948 #ifdef LIVE_OBJECT_LIST
12949   HandleScope scope;
12950   CONVERT_SMI_ARG_CHECKED(obj_id1, 0);
12951   CONVERT_SMI_ARG_CHECKED(obj_id2, 1);
12952   RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject());
12953
12954   Handle<JSObject> instance_filter;
12955   if (args[2]->IsJSObject()) {
12956     instance_filter = args.at<JSObject>(2);
12957   }
12958
12959   Object* result =
12960       LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
12961   return result;
12962 #else
12963   return isolate->heap()->undefined_value();
12964 #endif
12965 }
12966
12967
12968 // Generates the response to a debugger request for a list of all
12969 // previously captured live object lists.
12970 RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) {
12971 #ifdef LIVE_OBJECT_LIST
12972   CONVERT_SMI_ARG_CHECKED(start, 0);
12973   CONVERT_SMI_ARG_CHECKED(count, 1);
12974   return LiveObjectList::Info(start, count);
12975 #else
12976   return isolate->heap()->undefined_value();
12977 #endif
12978 }
12979
12980
12981 // Gets a dump of the specified object as requested by the debugger.
12982 // This is only used for obj ids shown in live object lists.
12983 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) {
12984 #ifdef LIVE_OBJECT_LIST
12985   HandleScope scope;
12986   CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12987   Object* result = LiveObjectList::PrintObj(obj_id);
12988   return result;
12989 #else
12990   return isolate->heap()->undefined_value();
12991 #endif
12992 }
12993
12994
12995 // Resets and releases all previously captured live object lists.
12996 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) {
12997 #ifdef LIVE_OBJECT_LIST
12998   LiveObjectList::Reset();
12999   return isolate->heap()->undefined_value();
13000 #else
13001   return isolate->heap()->undefined_value();
13002 #endif
13003 }
13004
13005
13006 // Generates the response to a debugger request for a summary of the types
13007 // of objects in the difference between the captured live object lists
13008 // specified by id1 and id2.
13009 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
13010 // summarized.
13011 RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) {
13012 #ifdef LIVE_OBJECT_LIST
13013   HandleScope scope;
13014   CONVERT_SMI_ARG_CHECKED(id1, 0);
13015   CONVERT_SMI_ARG_CHECKED(id2, 1);
13016   CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 2);
13017
13018   EnterDebugger enter_debugger;
13019   return LiveObjectList::Summarize(id1, id2, filter_obj);
13020 #else
13021   return isolate->heap()->undefined_value();
13022 #endif
13023 }
13024
13025 #endif  // ENABLE_DEBUGGER_SUPPORT
13026
13027
13028 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) {
13029   NoHandleAllocation ha;
13030   v8::V8::ResumeProfiler();
13031   return isolate->heap()->undefined_value();
13032 }
13033
13034
13035 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) {
13036   NoHandleAllocation ha;
13037   v8::V8::PauseProfiler();
13038   return isolate->heap()->undefined_value();
13039 }
13040
13041
13042 // Finds the script object from the script data. NOTE: This operation uses
13043 // heap traversal to find the function generated for the source position
13044 // for the requested break point. For lazily compiled functions several heap
13045 // traversals might be required rendering this operation as a rather slow
13046 // operation. However for setting break points which is normally done through
13047 // some kind of user interaction the performance is not crucial.
13048 static Handle<Object> Runtime_GetScriptFromScriptName(
13049     Handle<String> script_name) {
13050   // Scan the heap for Script objects to find the script with the requested
13051   // script data.
13052   Handle<Script> script;
13053   script_name->GetHeap()->EnsureHeapIsIterable();
13054   AssertNoAllocation no_allocation_during_heap_iteration;
13055   HeapIterator iterator;
13056   HeapObject* obj = NULL;
13057   while (script.is_null() && ((obj = iterator.next()) != NULL)) {
13058     // If a script is found check if it has the script data requested.
13059     if (obj->IsScript()) {
13060       if (Script::cast(obj)->name()->IsString()) {
13061         if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
13062           script = Handle<Script>(Script::cast(obj));
13063         }
13064       }
13065     }
13066   }
13067
13068   // If no script with the requested script data is found return undefined.
13069   if (script.is_null()) return FACTORY->undefined_value();
13070
13071   // Return the script found.
13072   return GetScriptWrapper(script);
13073 }
13074
13075
13076 // Get the script object from script data. NOTE: Regarding performance
13077 // see the NOTE for GetScriptFromScriptData.
13078 // args[0]: script data for the script to find the source for
13079 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
13080   HandleScope scope(isolate);
13081
13082   ASSERT(args.length() == 1);
13083
13084   CONVERT_ARG_CHECKED(String, script_name, 0);
13085
13086   // Find the requested script.
13087   Handle<Object> result =
13088       Runtime_GetScriptFromScriptName(Handle<String>(script_name));
13089   return *result;
13090 }
13091
13092
13093 // Determines whether the given stack frame should be displayed in
13094 // a stack trace.  The caller is the error constructor that asked
13095 // for the stack trace to be collected.  The first time a construct
13096 // call to this function is encountered it is skipped.  The seen_caller
13097 // in/out parameter is used to remember if the caller has been seen
13098 // yet.
13099 static bool ShowFrameInStackTrace(StackFrame* raw_frame,
13100                                   Object* caller,
13101                                   bool* seen_caller) {
13102   // Only display JS frames.
13103   if (!raw_frame->is_java_script()) {
13104     return false;
13105   }
13106   JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
13107   Object* raw_fun = frame->function();
13108   // Not sure when this can happen but skip it just in case.
13109   if (!raw_fun->IsJSFunction()) {
13110     return false;
13111   }
13112   if ((raw_fun == caller) && !(*seen_caller)) {
13113     *seen_caller = true;
13114     return false;
13115   }
13116   // Skip all frames until we've seen the caller.
13117   if (!(*seen_caller)) return false;
13118   // Also, skip non-visible built-in functions and any call with the builtins
13119   // object as receiver, so as to not reveal either the builtins object or
13120   // an internal function.
13121   // The --builtins-in-stack-traces command line flag allows including
13122   // internal call sites in the stack trace for debugging purposes.
13123   if (!FLAG_builtins_in_stack_traces) {
13124     JSFunction* fun = JSFunction::cast(raw_fun);
13125     if (frame->receiver()->IsJSBuiltinsObject() ||
13126         (fun->IsBuiltin() && !fun->shared()->native())) {
13127       return false;
13128     }
13129   }
13130   return true;
13131 }
13132
13133
13134 // Collect the raw data for a stack trace.  Returns an array of 4
13135 // element segments each containing a receiver, function, code and
13136 // native code offset.
13137 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
13138   ASSERT_EQ(args.length(), 3);
13139   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
13140   Handle<Object> caller = args.at<Object>(1);
13141   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
13142
13143   HandleScope scope(isolate);
13144   Factory* factory = isolate->factory();
13145
13146   limit = Max(limit, 0);  // Ensure that limit is not negative.
13147   int initial_size = Min(limit, 10);
13148   Handle<FixedArray> elements =
13149       factory->NewFixedArrayWithHoles(initial_size * 4);
13150
13151   StackFrameIterator iter(isolate);
13152   // If the caller parameter is a function we skip frames until we're
13153   // under it before starting to collect.
13154   bool seen_caller = !caller->IsJSFunction();
13155   int cursor = 0;
13156   int frames_seen = 0;
13157   while (!iter.done() && frames_seen < limit) {
13158     StackFrame* raw_frame = iter.frame();
13159     if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
13160       frames_seen++;
13161       JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
13162       // Set initial size to the maximum inlining level + 1 for the outermost
13163       // function.
13164       List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1);
13165       frame->Summarize(&frames);
13166       for (int i = frames.length() - 1; i >= 0; i--) {
13167         if (cursor + 4 > elements->length()) {
13168           int new_capacity = JSObject::NewElementsCapacity(elements->length());
13169           Handle<FixedArray> new_elements =
13170               factory->NewFixedArrayWithHoles(new_capacity);
13171           for (int i = 0; i < cursor; i++) {
13172             new_elements->set(i, elements->get(i));
13173           }
13174           elements = new_elements;
13175         }
13176         ASSERT(cursor + 4 <= elements->length());
13177
13178         Handle<Object> recv = frames[i].receiver();
13179         Handle<JSFunction> fun = frames[i].function();
13180         Handle<Code> code = frames[i].code();
13181         Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
13182         elements->set(cursor++, *recv);
13183         elements->set(cursor++, *fun);
13184         elements->set(cursor++, *code);
13185         elements->set(cursor++, *offset);
13186       }
13187     }
13188     iter.Advance();
13189   }
13190   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
13191   // Capture and attach a more detailed stack trace if necessary.
13192   isolate->CaptureAndSetCurrentStackTraceFor(error_object);
13193   result->set_length(Smi::FromInt(cursor));
13194   return *result;
13195 }
13196
13197
13198 // Returns V8 version as a string.
13199 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
13200   ASSERT_EQ(args.length(), 0);
13201
13202   NoHandleAllocation ha;
13203
13204   const char* version_string = v8::V8::GetVersion();
13205
13206   return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
13207                                                   NOT_TENURED);
13208 }
13209
13210
13211 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
13212   ASSERT(args.length() == 2);
13213   OS::PrintError("abort: %s\n",
13214                  reinterpret_cast<char*>(args[0]) + args.smi_at(1));
13215   isolate->PrintStack();
13216   OS::Abort();
13217   UNREACHABLE();
13218   return NULL;
13219 }
13220
13221
13222 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
13223   // This is only called from codegen, so checks might be more lax.
13224   CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
13225   Object* key = args[1];
13226
13227   int finger_index = cache->finger_index();
13228   Object* o = cache->get(finger_index);
13229   if (o == key) {
13230     // The fastest case: hit the same place again.
13231     return cache->get(finger_index + 1);
13232   }
13233
13234   for (int i = finger_index - 2;
13235        i >= JSFunctionResultCache::kEntriesIndex;
13236        i -= 2) {
13237     o = cache->get(i);
13238     if (o == key) {
13239       cache->set_finger_index(i);
13240       return cache->get(i + 1);
13241     }
13242   }
13243
13244   int size = cache->size();
13245   ASSERT(size <= cache->length());
13246
13247   for (int i = size - 2; i > finger_index; i -= 2) {
13248     o = cache->get(i);
13249     if (o == key) {
13250       cache->set_finger_index(i);
13251       return cache->get(i + 1);
13252     }
13253   }
13254
13255   // There is no value in the cache.  Invoke the function and cache result.
13256   HandleScope scope(isolate);
13257
13258   Handle<JSFunctionResultCache> cache_handle(cache);
13259   Handle<Object> key_handle(key);
13260   Handle<Object> value;
13261   {
13262     Handle<JSFunction> factory(JSFunction::cast(
13263           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
13264     // TODO(antonm): consider passing a receiver when constructing a cache.
13265     Handle<Object> receiver(isolate->global_context()->global());
13266     // This handle is nor shared, nor used later, so it's safe.
13267     Handle<Object> argv[] = { key_handle };
13268     bool pending_exception;
13269     value = Execution::Call(factory,
13270                             receiver,
13271                             ARRAY_SIZE(argv),
13272                             argv,
13273                             &pending_exception);
13274     if (pending_exception) return Failure::Exception();
13275   }
13276
13277 #ifdef DEBUG
13278   if (FLAG_verify_heap) {
13279     cache_handle->JSFunctionResultCacheVerify();
13280   }
13281 #endif
13282
13283   // Function invocation may have cleared the cache.  Reread all the data.
13284   finger_index = cache_handle->finger_index();
13285   size = cache_handle->size();
13286
13287   // If we have spare room, put new data into it, otherwise evict post finger
13288   // entry which is likely to be the least recently used.
13289   int index = -1;
13290   if (size < cache_handle->length()) {
13291     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
13292     index = size;
13293   } else {
13294     index = finger_index + JSFunctionResultCache::kEntrySize;
13295     if (index == cache_handle->length()) {
13296       index = JSFunctionResultCache::kEntriesIndex;
13297     }
13298   }
13299
13300   ASSERT(index % 2 == 0);
13301   ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
13302   ASSERT(index < cache_handle->length());
13303
13304   cache_handle->set(index, *key_handle);
13305   cache_handle->set(index + 1, *value);
13306   cache_handle->set_finger_index(index);
13307
13308 #ifdef DEBUG
13309   if (FLAG_verify_heap) {
13310     cache_handle->JSFunctionResultCacheVerify();
13311   }
13312 #endif
13313
13314   return *value;
13315 }
13316
13317
13318 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewMessageObject) {
13319   HandleScope scope(isolate);
13320   CONVERT_ARG_HANDLE_CHECKED(String, type, 0);
13321   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 1);
13322   return *isolate->factory()->NewJSMessageObject(
13323       type,
13324       arguments,
13325       0,
13326       0,
13327       isolate->factory()->undefined_value(),
13328       isolate->factory()->undefined_value(),
13329       isolate->factory()->undefined_value());
13330 }
13331
13332
13333 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetType) {
13334   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13335   return message->type();
13336 }
13337
13338
13339 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetArguments) {
13340   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13341   return message->arguments();
13342 }
13343
13344
13345 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
13346   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13347   return Smi::FromInt(message->start_position());
13348 }
13349
13350
13351 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
13352   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13353   return message->script();
13354 }
13355
13356
13357 #ifdef DEBUG
13358 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
13359 // Exclude the code in release mode.
13360 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
13361   ASSERT(args.length() == 0);
13362   HandleScope scope;
13363 #define COUNT_ENTRY(Name, argc, ressize) + 1
13364   int entry_count = 0
13365       RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
13366       INLINE_FUNCTION_LIST(COUNT_ENTRY)
13367       INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
13368 #undef COUNT_ENTRY
13369   Factory* factory = isolate->factory();
13370   Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
13371   int index = 0;
13372   bool inline_runtime_functions = false;
13373 #define ADD_ENTRY(Name, argc, ressize)                                       \
13374   {                                                                          \
13375     HandleScope inner;                                                       \
13376     Handle<String> name;                                                     \
13377     /* Inline runtime functions have an underscore in front of the name. */  \
13378     if (inline_runtime_functions) {                                          \
13379       name = factory->NewStringFromAscii(                                    \
13380           Vector<const char>("_" #Name, StrLength("_" #Name)));              \
13381     } else {                                                                 \
13382       name = factory->NewStringFromAscii(                                    \
13383           Vector<const char>(#Name, StrLength(#Name)));                      \
13384     }                                                                        \
13385     Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
13386     pair_elements->set(0, *name);                                            \
13387     pair_elements->set(1, Smi::FromInt(argc));                               \
13388     Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
13389     elements->set(index++, *pair);                                           \
13390   }
13391   inline_runtime_functions = false;
13392   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13393   inline_runtime_functions = true;
13394   INLINE_FUNCTION_LIST(ADD_ENTRY)
13395   INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13396 #undef ADD_ENTRY
13397   ASSERT_EQ(index, entry_count);
13398   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
13399   return *result;
13400 }
13401 #endif
13402
13403
13404 RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
13405   ASSERT(args.length() == 2);
13406   CONVERT_ARG_CHECKED(String, format, 0);
13407   CONVERT_ARG_CHECKED(JSArray, elms, 1);
13408   String::FlatContent format_content = format->GetFlatContent();
13409   RUNTIME_ASSERT(format_content.IsAscii());
13410   Vector<const char> chars = format_content.ToAsciiVector();
13411   LOGGER->LogRuntime(chars, elms);
13412   return isolate->heap()->undefined_value();
13413 }
13414
13415
13416 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
13417   UNREACHABLE();  // implemented as macro in the parser
13418   return NULL;
13419 }
13420
13421
13422 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
13423   RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
13424     CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
13425     return isolate->heap()->ToBoolean(obj->Has##Name());  \
13426   }
13427
13428 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOnlyElements)
13429 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements)
13430 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
13431 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
13432 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
13433 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
13434 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
13435 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
13436 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
13437 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
13438 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
13439 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
13440 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
13441 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
13442
13443 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
13444
13445
13446 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
13447   ASSERT(args.length() == 2);
13448   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
13449   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
13450   return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
13451 }
13452
13453 // ----------------------------------------------------------------------------
13454 // Implementation of Runtime
13455
13456 #define F(name, number_of_args, result_size)                             \
13457   { Runtime::k##name, Runtime::RUNTIME, #name,   \
13458     FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
13459
13460
13461 #define I(name, number_of_args, result_size)                             \
13462   { Runtime::kInline##name, Runtime::INLINE,     \
13463     "_" #name, NULL, number_of_args, result_size },
13464
13465 static const Runtime::Function kIntrinsicFunctions[] = {
13466   RUNTIME_FUNCTION_LIST(F)
13467   INLINE_FUNCTION_LIST(I)
13468   INLINE_RUNTIME_FUNCTION_LIST(I)
13469 };
13470
13471
13472 MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
13473                                                        Object* dictionary) {
13474   ASSERT(Isolate::Current()->heap() == heap);
13475   ASSERT(dictionary != NULL);
13476   ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
13477   for (int i = 0; i < kNumFunctions; ++i) {
13478     Object* name_symbol;
13479     { MaybeObject* maybe_name_symbol =
13480           heap->LookupAsciiSymbol(kIntrinsicFunctions[i].name);
13481       if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
13482     }
13483     StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
13484     { MaybeObject* maybe_dictionary = string_dictionary->Add(
13485           String::cast(name_symbol),
13486           Smi::FromInt(i),
13487           PropertyDetails(NONE, NORMAL));
13488       if (!maybe_dictionary->ToObject(&dictionary)) {
13489         // Non-recoverable failure.  Calling code must restart heap
13490         // initialization.
13491         return maybe_dictionary;
13492       }
13493     }
13494   }
13495   return dictionary;
13496 }
13497
13498
13499 const Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
13500   Heap* heap = name->GetHeap();
13501   int entry = heap->intrinsic_function_names()->FindEntry(*name);
13502   if (entry != kNotFound) {
13503     Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
13504     int function_index = Smi::cast(smi_index)->value();
13505     return &(kIntrinsicFunctions[function_index]);
13506   }
13507   return NULL;
13508 }
13509
13510
13511 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
13512   return &(kIntrinsicFunctions[static_cast<int>(id)]);
13513 }
13514
13515
13516 void Runtime::PerformGC(Object* result) {
13517   Isolate* isolate = Isolate::Current();
13518   Failure* failure = Failure::cast(result);
13519   if (failure->IsRetryAfterGC()) {
13520     if (isolate->heap()->new_space()->AddFreshPage()) {
13521       return;
13522     }
13523
13524     // Try to do a garbage collection; ignore it if it fails. The C
13525     // entry stub will throw an out-of-memory exception in that case.
13526     isolate->heap()->CollectGarbage(failure->allocation_space(),
13527                                     "Runtime::PerformGC");
13528   } else {
13529     // Handle last resort GC and make sure to allow future allocations
13530     // to grow the heap without causing GCs (if possible).
13531     isolate->counters()->gc_last_resort_from_js()->Increment();
13532     isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
13533                                        "Runtime::PerformGC");
13534   }
13535 }
13536
13537
13538 } }  // namespace v8::internal