v8: upgrade to 3.20.17
[platform/upstream/nodejs.git] / deps / 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 #include <limits>
30
31 #include "v8.h"
32
33 #include "accessors.h"
34 #include "api.h"
35 #include "arguments.h"
36 #include "bootstrapper.h"
37 #include "codegen.h"
38 #include "compilation-cache.h"
39 #include "compiler.h"
40 #include "cpu.h"
41 #include "cpu-profiler.h"
42 #include "dateparser-inl.h"
43 #include "debug.h"
44 #include "deoptimizer.h"
45 #include "date.h"
46 #include "execution.h"
47 #include "full-codegen.h"
48 #include "global-handles.h"
49 #include "isolate-inl.h"
50 #include "jsregexp.h"
51 #include "jsregexp-inl.h"
52 #include "json-parser.h"
53 #include "json-stringifier.h"
54 #include "liveedit.h"
55 #include "misc-intrinsics.h"
56 #include "parser.h"
57 #include "platform.h"
58 #include "runtime-profiler.h"
59 #include "runtime.h"
60 #include "scopeinfo.h"
61 #include "smart-pointers.h"
62 #include "string-search.h"
63 #include "stub-cache.h"
64 #include "uri.h"
65 #include "v8conversions.h"
66 #include "v8threads.h"
67 #include "vm-state-inl.h"
68
69 #ifdef V8_I18N_SUPPORT
70 #include "i18n.h"
71 #include "unicode/brkiter.h"
72 #include "unicode/calendar.h"
73 #include "unicode/coll.h"
74 #include "unicode/curramt.h"
75 #include "unicode/datefmt.h"
76 #include "unicode/dcfmtsym.h"
77 #include "unicode/decimfmt.h"
78 #include "unicode/dtfmtsym.h"
79 #include "unicode/dtptngen.h"
80 #include "unicode/locid.h"
81 #include "unicode/numfmt.h"
82 #include "unicode/numsys.h"
83 #include "unicode/smpdtfmt.h"
84 #include "unicode/timezone.h"
85 #include "unicode/uchar.h"
86 #include "unicode/ucol.h"
87 #include "unicode/ucurr.h"
88 #include "unicode/uloc.h"
89 #include "unicode/unum.h"
90 #include "unicode/uversion.h"
91 #endif
92
93 #ifndef _STLP_VENDOR_CSTD
94 // STLPort doesn't import fpclassify and isless into the std namespace.
95 using std::fpclassify;
96 using std::isless;
97 #endif
98
99 namespace v8 {
100 namespace internal {
101
102
103 #define RUNTIME_ASSERT(value) \
104   if (!(value)) return isolate->ThrowIllegalOperation();
105
106 // Cast the given object to a value of the specified type and store
107 // it in a variable with the given name.  If the object is not of the
108 // expected type call IllegalOperation and return.
109 #define CONVERT_ARG_CHECKED(Type, name, index)                       \
110   RUNTIME_ASSERT(args[index]->Is##Type());                           \
111   Type* name = Type::cast(args[index]);
112
113 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
114   RUNTIME_ASSERT(args[index]->Is##Type());                           \
115   Handle<Type> name = args.at<Type>(index);
116
117 // Cast the given object to a boolean and store it in a variable with
118 // the given name.  If the object is not a boolean call IllegalOperation
119 // and return.
120 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
121   RUNTIME_ASSERT(args[index]->IsBoolean());                          \
122   bool name = args[index]->IsTrue();
123
124 // Cast the given argument to a Smi and store its value in an int variable
125 // with the given name.  If the argument is not a Smi call IllegalOperation
126 // and return.
127 #define CONVERT_SMI_ARG_CHECKED(name, index)                         \
128   RUNTIME_ASSERT(args[index]->IsSmi());                              \
129   int name = args.smi_at(index);
130
131 // Cast the given argument to a double and store it in a variable with
132 // the given name.  If the argument is not a number (as opposed to
133 // the number not-a-number) call IllegalOperation and return.
134 #define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
135   RUNTIME_ASSERT(args[index]->IsNumber());                           \
136   double name = args.number_at(index);
137
138 // Call the specified converter on the object *comand store the result in
139 // a variable of the specified type with the given name.  If the
140 // object is not a Number call IllegalOperation and return.
141 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
142   RUNTIME_ASSERT(obj->IsNumber());                                   \
143   type name = NumberTo##Type(obj);
144
145
146 // Cast the given argument to PropertyDetails and store its value in a
147 // variable with the given name.  If the argument is not a Smi call
148 // IllegalOperation and return.
149 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
150   RUNTIME_ASSERT(args[index]->IsSmi());                              \
151   PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
152
153
154 // Assert that the given argument has a valid value for a StrictModeFlag
155 // and store it in a StrictModeFlag variable with the given name.
156 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
157   RUNTIME_ASSERT(args[index]->IsSmi());                              \
158   RUNTIME_ASSERT(args.smi_at(index) == kStrictMode ||                \
159                  args.smi_at(index) == kNonStrictMode);              \
160   StrictModeFlag name =                                              \
161       static_cast<StrictModeFlag>(args.smi_at(index));
162
163
164 // Assert that the given argument has a valid value for a LanguageMode
165 // and store it in a LanguageMode variable with the given name.
166 #define CONVERT_LANGUAGE_MODE_ARG(name, index)                       \
167   ASSERT(args[index]->IsSmi());                                      \
168   ASSERT(args.smi_at(index) == CLASSIC_MODE ||                       \
169          args.smi_at(index) == STRICT_MODE ||                        \
170          args.smi_at(index) == EXTENDED_MODE);                       \
171   LanguageMode name =                                                \
172       static_cast<LanguageMode>(args.smi_at(index));
173
174
175 static Handle<Map> ComputeObjectLiteralMap(
176     Handle<Context> context,
177     Handle<FixedArray> constant_properties,
178     bool* is_result_from_cache) {
179   Isolate* isolate = context->GetIsolate();
180   int properties_length = constant_properties->length();
181   int number_of_properties = properties_length / 2;
182   // Check that there are only internal strings and array indices among keys.
183   int number_of_string_keys = 0;
184   for (int p = 0; p != properties_length; p += 2) {
185     Object* key = constant_properties->get(p);
186     uint32_t element_index = 0;
187     if (key->IsInternalizedString()) {
188       number_of_string_keys++;
189     } else if (key->ToArrayIndex(&element_index)) {
190       // An index key does not require space in the property backing store.
191       number_of_properties--;
192     } else {
193       // Bail out as a non-internalized-string non-index key makes caching
194       // impossible.
195       // ASSERT to make sure that the if condition after the loop is false.
196       ASSERT(number_of_string_keys != number_of_properties);
197       break;
198     }
199   }
200   // If we only have internalized strings and array indices among keys then we
201   // can use the map cache in the native context.
202   const int kMaxKeys = 10;
203   if ((number_of_string_keys == number_of_properties) &&
204       (number_of_string_keys < kMaxKeys)) {
205     // Create the fixed array with the key.
206     Handle<FixedArray> keys =
207         isolate->factory()->NewFixedArray(number_of_string_keys);
208     if (number_of_string_keys > 0) {
209       int index = 0;
210       for (int p = 0; p < properties_length; p += 2) {
211         Object* key = constant_properties->get(p);
212         if (key->IsInternalizedString()) {
213           keys->set(index++, key);
214         }
215       }
216       ASSERT(index == number_of_string_keys);
217     }
218     *is_result_from_cache = true;
219     return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
220   }
221   *is_result_from_cache = false;
222   return isolate->factory()->CopyMap(
223       Handle<Map>(context->object_function()->initial_map()),
224       number_of_properties);
225 }
226
227
228 static Handle<Object> CreateLiteralBoilerplate(
229     Isolate* isolate,
230     Handle<FixedArray> literals,
231     Handle<FixedArray> constant_properties);
232
233
234 static Handle<Object> CreateObjectLiteralBoilerplate(
235     Isolate* isolate,
236     Handle<FixedArray> literals,
237     Handle<FixedArray> constant_properties,
238     bool should_have_fast_elements,
239     bool has_function_literal) {
240   // Get the native context from the literals array.  This is the
241   // context in which the function was created and we use the object
242   // function from this context to create the object literal.  We do
243   // not use the object function from the current native context
244   // because this might be the object function from another context
245   // which we should not have access to.
246   Handle<Context> context =
247       Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
248
249   // In case we have function literals, we want the object to be in
250   // slow properties mode for now. We don't go in the map cache because
251   // maps with constant functions can't be shared if the functions are
252   // not the same (which is the common case).
253   bool is_result_from_cache = false;
254   Handle<Map> map = has_function_literal
255       ? Handle<Map>(context->object_function()->initial_map())
256       : ComputeObjectLiteralMap(context,
257                                 constant_properties,
258                                 &is_result_from_cache);
259
260   Handle<JSObject> boilerplate =
261       isolate->factory()->NewJSObjectFromMap(
262           map, isolate->heap()->GetPretenureMode());
263
264   // Normalize the elements of the boilerplate to save space if needed.
265   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
266
267   // Add the constant properties to the boilerplate.
268   int length = constant_properties->length();
269   bool should_transform =
270       !is_result_from_cache && boilerplate->HasFastProperties();
271   if (should_transform || has_function_literal) {
272     // Normalize the properties of object to avoid n^2 behavior
273     // when extending the object multiple properties. Indicate the number of
274     // properties to be added.
275     JSObject::NormalizeProperties(
276         boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
277   }
278
279   // TODO(verwaest): Support tracking representations in the boilerplate.
280   for (int index = 0; index < length; index +=2) {
281     Handle<Object> key(constant_properties->get(index+0), isolate);
282     Handle<Object> value(constant_properties->get(index+1), isolate);
283     if (value->IsFixedArray()) {
284       // The value contains the constant_properties of a
285       // simple object or array literal.
286       Handle<FixedArray> array = Handle<FixedArray>::cast(value);
287       value = CreateLiteralBoilerplate(isolate, literals, array);
288       if (value.is_null()) return value;
289     }
290     Handle<Object> result;
291     uint32_t element_index = 0;
292     JSReceiver::StoreMode mode = value->IsJSObject()
293         ? JSReceiver::FORCE_FIELD
294         : JSReceiver::ALLOW_AS_CONSTANT;
295     if (key->IsInternalizedString()) {
296       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
297         // Array index as string (uint32).
298         result = JSObject::SetOwnElement(
299             boilerplate, element_index, value, kNonStrictMode);
300       } else {
301         Handle<String> name(String::cast(*key));
302         ASSERT(!name->AsArrayIndex(&element_index));
303         result = JSObject::SetLocalPropertyIgnoreAttributes(
304             boilerplate, name, value, NONE,
305             Object::OPTIMAL_REPRESENTATION, mode);
306       }
307     } else if (key->ToArrayIndex(&element_index)) {
308       // Array index (uint32).
309       result = JSObject::SetOwnElement(
310           boilerplate, element_index, value, kNonStrictMode);
311     } else {
312       // Non-uint32 number.
313       ASSERT(key->IsNumber());
314       double num = key->Number();
315       char arr[100];
316       Vector<char> buffer(arr, ARRAY_SIZE(arr));
317       const char* str = DoubleToCString(num, buffer);
318       Handle<String> name =
319           isolate->factory()->NewStringFromAscii(CStrVector(str));
320       result = JSObject::SetLocalPropertyIgnoreAttributes(
321           boilerplate, name, value, NONE,
322           Object::OPTIMAL_REPRESENTATION, mode);
323     }
324     // If setting the property on the boilerplate throws an
325     // exception, the exception is converted to an empty handle in
326     // the handle based operations.  In that case, we need to
327     // convert back to an exception.
328     if (result.is_null()) return result;
329   }
330
331   // Transform to fast properties if necessary. For object literals with
332   // containing function literals we defer this operation until after all
333   // computed properties have been assigned so that we can generate
334   // constant function properties.
335   if (should_transform && !has_function_literal) {
336     JSObject::TransformToFastProperties(
337         boilerplate, boilerplate->map()->unused_property_fields());
338   }
339
340   return boilerplate;
341 }
342
343
344 MaybeObject* TransitionElements(Handle<Object> object,
345                                 ElementsKind to_kind,
346                                 Isolate* isolate) {
347   HandleScope scope(isolate);
348   if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
349   ElementsKind from_kind =
350       Handle<JSObject>::cast(object)->map()->elements_kind();
351   if (Map::IsValidElementsTransition(from_kind, to_kind)) {
352     Handle<Object> result = JSObject::TransitionElementsKind(
353         Handle<JSObject>::cast(object), to_kind);
354     if (result.is_null()) return isolate->ThrowIllegalOperation();
355     return *result;
356   }
357   return isolate->ThrowIllegalOperation();
358 }
359
360
361 static const int kSmiLiteralMinimumLength = 1024;
362
363
364 Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
365     Isolate* isolate,
366     Handle<FixedArray> literals,
367     Handle<FixedArray> elements) {
368   // Create the JSArray.
369   Handle<JSFunction> constructor(
370       JSFunction::NativeContextFromLiterals(*literals)->array_function());
371
372   Handle<JSArray> object = Handle<JSArray>::cast(
373       isolate->factory()->NewJSObject(
374           constructor, isolate->heap()->GetPretenureMode()));
375
376   ElementsKind constant_elements_kind =
377       static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
378   Handle<FixedArrayBase> constant_elements_values(
379       FixedArrayBase::cast(elements->get(1)));
380
381   ASSERT(IsFastElementsKind(constant_elements_kind));
382   Context* native_context = isolate->context()->native_context();
383   Object* maybe_maps_array = native_context->js_array_maps();
384   ASSERT(!maybe_maps_array->IsUndefined());
385   Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
386       constant_elements_kind);
387   ASSERT(maybe_map->IsMap());
388   object->set_map(Map::cast(maybe_map));
389
390   Handle<FixedArrayBase> copied_elements_values;
391   if (IsFastDoubleElementsKind(constant_elements_kind)) {
392     ASSERT(FLAG_smi_only_arrays);
393     copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
394         Handle<FixedDoubleArray>::cast(constant_elements_values));
395   } else {
396     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
397     const bool is_cow =
398         (constant_elements_values->map() ==
399          isolate->heap()->fixed_cow_array_map());
400     if (is_cow) {
401       copied_elements_values = constant_elements_values;
402 #if DEBUG
403       Handle<FixedArray> fixed_array_values =
404           Handle<FixedArray>::cast(copied_elements_values);
405       for (int i = 0; i < fixed_array_values->length(); i++) {
406         ASSERT(!fixed_array_values->get(i)->IsFixedArray());
407       }
408 #endif
409     } else {
410       Handle<FixedArray> fixed_array_values =
411           Handle<FixedArray>::cast(constant_elements_values);
412       Handle<FixedArray> fixed_array_values_copy =
413           isolate->factory()->CopyFixedArray(fixed_array_values);
414       copied_elements_values = fixed_array_values_copy;
415       for (int i = 0; i < fixed_array_values->length(); i++) {
416         Object* current = fixed_array_values->get(i);
417         if (current->IsFixedArray()) {
418           // The value contains the constant_properties of a
419           // simple object or array literal.
420           Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
421           Handle<Object> result =
422               CreateLiteralBoilerplate(isolate, literals, fa);
423           if (result.is_null()) return result;
424           fixed_array_values_copy->set(i, *result);
425         }
426       }
427     }
428   }
429   object->set_elements(*copied_elements_values);
430   object->set_length(Smi::FromInt(copied_elements_values->length()));
431
432   //  Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
433   //  on or the object is larger than the threshold.
434   if (!FLAG_smi_only_arrays &&
435       constant_elements_values->length() < kSmiLiteralMinimumLength) {
436     ElementsKind elements_kind = object->GetElementsKind();
437     if (!IsFastObjectElementsKind(elements_kind)) {
438       if (IsFastHoleyElementsKind(elements_kind)) {
439         CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
440                                   isolate)->IsFailure());
441       } else {
442         CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
443       }
444     }
445   }
446
447   object->ValidateElements();
448   return object;
449 }
450
451
452 static Handle<Object> CreateLiteralBoilerplate(
453     Isolate* isolate,
454     Handle<FixedArray> literals,
455     Handle<FixedArray> array) {
456   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
457   const bool kHasNoFunctionLiteral = false;
458   switch (CompileTimeValue::GetLiteralType(array)) {
459     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
460       return CreateObjectLiteralBoilerplate(isolate,
461                                             literals,
462                                             elements,
463                                             true,
464                                             kHasNoFunctionLiteral);
465     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
466       return CreateObjectLiteralBoilerplate(isolate,
467                                             literals,
468                                             elements,
469                                             false,
470                                             kHasNoFunctionLiteral);
471     case CompileTimeValue::ARRAY_LITERAL:
472       return Runtime::CreateArrayLiteralBoilerplate(
473           isolate, literals, elements);
474     default:
475       UNREACHABLE();
476       return Handle<Object>::null();
477   }
478 }
479
480
481 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
482   HandleScope scope(isolate);
483   ASSERT(args.length() == 4);
484   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
485   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
486   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
487   CONVERT_SMI_ARG_CHECKED(flags, 3);
488   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
489   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
490
491   // Check if boilerplate exists. If not, create it first.
492   Handle<Object> boilerplate(literals->get(literals_index), isolate);
493   if (*boilerplate == isolate->heap()->undefined_value()) {
494     boilerplate = CreateObjectLiteralBoilerplate(isolate,
495                                                  literals,
496                                                  constant_properties,
497                                                  should_have_fast_elements,
498                                                  has_function_literal);
499     RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
500     // Update the functions literal and return the boilerplate.
501     literals->set(literals_index, *boilerplate);
502   }
503   return JSObject::cast(*boilerplate)->DeepCopy(isolate);
504 }
505
506
507 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
508   HandleScope scope(isolate);
509   ASSERT(args.length() == 4);
510   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
511   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
512   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
513   CONVERT_SMI_ARG_CHECKED(flags, 3);
514   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
515   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
516
517   // Check if boilerplate exists. If not, create it first.
518   Handle<Object> boilerplate(literals->get(literals_index), isolate);
519   if (*boilerplate == isolate->heap()->undefined_value()) {
520     boilerplate = CreateObjectLiteralBoilerplate(isolate,
521                                                  literals,
522                                                  constant_properties,
523                                                  should_have_fast_elements,
524                                                  has_function_literal);
525     RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
526     // Update the functions literal and return the boilerplate.
527     literals->set(literals_index, *boilerplate);
528   }
529   return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
530 }
531
532
533 static Handle<AllocationSite> GetLiteralAllocationSite(
534     Isolate* isolate,
535     Handle<FixedArray> literals,
536     int literals_index,
537     Handle<FixedArray> elements) {
538   // Check if boilerplate exists. If not, create it first.
539   Handle<Object> literal_site(literals->get(literals_index), isolate);
540   Handle<AllocationSite> site;
541   if (*literal_site == isolate->heap()->undefined_value()) {
542     ASSERT(*elements != isolate->heap()->empty_fixed_array());
543     Handle<Object> boilerplate =
544         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
545     if (boilerplate.is_null()) return site;
546     site = isolate->factory()->NewAllocationSite();
547     site->set_transition_info(*boilerplate);
548     literals->set(literals_index, *site);
549   } else {
550     site = Handle<AllocationSite>::cast(literal_site);
551   }
552
553   return site;
554 }
555
556
557 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
558   HandleScope scope(isolate);
559   ASSERT(args.length() == 3);
560   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
561   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
562   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
563
564   Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
565       literals_index, elements);
566   RETURN_IF_EMPTY_HANDLE(isolate, site);
567
568   JSObject* boilerplate = JSObject::cast(site->transition_info());
569   return boilerplate->DeepCopy(isolate);
570 }
571
572
573 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
574   HandleScope scope(isolate);
575   ASSERT(args.length() == 3);
576   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
577   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
578   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
579
580   Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
581       literals_index, elements);
582   RETURN_IF_EMPTY_HANDLE(isolate, site);
583
584   JSObject* boilerplate = JSObject::cast(site->transition_info());
585   if (boilerplate->elements()->map() ==
586       isolate->heap()->fixed_cow_array_map()) {
587     isolate->counters()->cow_arrays_created_runtime()->Increment();
588   }
589
590   AllocationSiteMode mode = AllocationSite::GetMode(
591       boilerplate->GetElementsKind());
592   if (mode == TRACK_ALLOCATION_SITE) {
593     return isolate->heap()->CopyJSObjectWithAllocationSite(
594         boilerplate, *site);
595   }
596
597   return isolate->heap()->CopyJSObject(boilerplate);
598 }
599
600
601 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
602   HandleScope scope(isolate);
603   ASSERT(args.length() == 1);
604   Handle<Object> name(args[0], isolate);
605   RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
606   Symbol* symbol;
607   MaybeObject* maybe = isolate->heap()->AllocateSymbol();
608   if (!maybe->To(&symbol)) return maybe;
609   if (name->IsString()) symbol->set_name(*name);
610   return symbol;
611 }
612
613
614 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
615   SealHandleScope shs(isolate);
616   ASSERT(args.length() == 1);
617   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
618   return symbol->name();
619 }
620
621
622 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
623   SealHandleScope shs(isolate);
624   ASSERT(args.length() == 2);
625   CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
626   Object* prototype = args[1];
627   Object* used_prototype =
628       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
629   return isolate->heap()->AllocateJSProxy(handler, used_prototype);
630 }
631
632
633 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
634   SealHandleScope shs(isolate);
635   ASSERT(args.length() == 4);
636   CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
637   Object* call_trap = args[1];
638   RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
639   CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
640   Object* prototype = args[3];
641   Object* used_prototype =
642       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
643   return isolate->heap()->AllocateJSFunctionProxy(
644       handler, call_trap, construct_trap, used_prototype);
645 }
646
647
648 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
649   SealHandleScope shs(isolate);
650   ASSERT(args.length() == 1);
651   Object* obj = args[0];
652   return isolate->heap()->ToBoolean(obj->IsJSProxy());
653 }
654
655
656 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
657   SealHandleScope shs(isolate);
658   ASSERT(args.length() == 1);
659   Object* obj = args[0];
660   return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
661 }
662
663
664 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
665   SealHandleScope shs(isolate);
666   ASSERT(args.length() == 1);
667   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
668   return proxy->handler();
669 }
670
671
672 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
673   SealHandleScope shs(isolate);
674   ASSERT(args.length() == 1);
675   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
676   return proxy->call_trap();
677 }
678
679
680 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
681   SealHandleScope shs(isolate);
682   ASSERT(args.length() == 1);
683   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
684   return proxy->construct_trap();
685 }
686
687
688 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
689   SealHandleScope shs(isolate);
690   ASSERT(args.length() == 1);
691   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
692   proxy->Fix();
693   return isolate->heap()->undefined_value();
694 }
695
696
697 void Runtime::FreeArrayBuffer(Isolate* isolate,
698                               JSArrayBuffer* phantom_array_buffer) {
699   if (phantom_array_buffer->is_external()) return;
700
701   size_t allocated_length = NumberToSize(
702       isolate, phantom_array_buffer->byte_length());
703
704   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
705       -static_cast<intptr_t>(allocated_length));
706   CHECK(V8::ArrayBufferAllocator() != NULL);
707   V8::ArrayBufferAllocator()->Free(
708       phantom_array_buffer->backing_store(),
709       allocated_length);
710 }
711
712
713 void Runtime::SetupArrayBuffer(Isolate* isolate,
714                                Handle<JSArrayBuffer> array_buffer,
715                                bool is_external,
716                                void* data,
717                                size_t allocated_length) {
718   ASSERT(array_buffer->GetInternalFieldCount() ==
719       v8::ArrayBuffer::kInternalFieldCount);
720   for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
721     array_buffer->SetInternalField(i, Smi::FromInt(0));
722   }
723   array_buffer->set_backing_store(data);
724   array_buffer->set_flag(Smi::FromInt(0));
725   array_buffer->set_is_external(is_external);
726
727   Handle<Object> byte_length =
728       isolate->factory()->NewNumberFromSize(allocated_length);
729   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
730   array_buffer->set_byte_length(*byte_length);
731
732   array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
733   isolate->heap()->set_array_buffers_list(*array_buffer);
734   array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
735 }
736
737
738 bool Runtime::SetupArrayBufferAllocatingData(
739     Isolate* isolate,
740     Handle<JSArrayBuffer> array_buffer,
741     size_t allocated_length,
742     bool initialize) {
743   void* data;
744   CHECK(V8::ArrayBufferAllocator() != NULL);
745   if (allocated_length != 0) {
746     if (initialize) {
747       data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
748     } else {
749       data =
750         V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
751     }
752     if (data == NULL) return false;
753   } else {
754     data = NULL;
755   }
756
757   SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
758
759   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
760
761   return true;
762 }
763
764
765 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
766   HandleScope scope(isolate);
767   ASSERT(args.length() == 2);
768   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
769   CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
770   size_t allocated_length;
771   if (byteLength->IsSmi()) {
772     allocated_length = Smi::cast(*byteLength)->value();
773   } else {
774     ASSERT(byteLength->IsHeapNumber());
775     double value = HeapNumber::cast(*byteLength)->value();
776
777     ASSERT(value >= 0);
778
779     if (value > std::numeric_limits<size_t>::max()) {
780       return isolate->Throw(
781           *isolate->factory()->NewRangeError("invalid_array_buffer_length",
782             HandleVector<Object>(NULL, 0)));
783     }
784
785     allocated_length = static_cast<size_t>(value);
786   }
787
788   if (!Runtime::SetupArrayBufferAllocatingData(isolate,
789                                                holder, allocated_length)) {
790       return isolate->Throw(*isolate->factory()->
791           NewRangeError("invalid_array_buffer_length",
792             HandleVector<Object>(NULL, 0)));
793   }
794
795   return *holder;
796 }
797
798
799 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
800   SealHandleScope shs(isolate);
801   ASSERT(args.length() == 1);
802   CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
803   return holder->byte_length();
804 }
805
806
807 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
808   HandleScope scope(isolate);
809   ASSERT(args.length() == 3);
810   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
811   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
812   CONVERT_DOUBLE_ARG_CHECKED(first, 2);
813   size_t start = static_cast<size_t>(first);
814   size_t target_length = NumberToSize(isolate, target->byte_length());
815
816   if (target_length == 0) return isolate->heap()->undefined_value();
817
818   ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
819   uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
820   uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
821   CopyBytes(target_data, source_data + start, target_length);
822   return isolate->heap()->undefined_value();
823 }
824
825
826 enum TypedArrayId {
827   // arrayIds below should be synchromized with typedarray.js natives.
828   ARRAY_ID_UINT8 = 1,
829   ARRAY_ID_INT8 = 2,
830   ARRAY_ID_UINT16 = 3,
831   ARRAY_ID_INT16 = 4,
832   ARRAY_ID_UINT32 = 5,
833   ARRAY_ID_INT32 = 6,
834   ARRAY_ID_FLOAT32 = 7,
835   ARRAY_ID_FLOAT64 = 8,
836   ARRAY_ID_UINT8C = 9
837 };
838
839 static void ArrayIdToTypeAndSize(
840     int arrayId, ExternalArrayType* array_type, size_t* element_size) {
841   switch (arrayId) {
842     case ARRAY_ID_UINT8:
843       *array_type = kExternalUnsignedByteArray;
844       *element_size = 1;
845       break;
846     case ARRAY_ID_INT8:
847       *array_type = kExternalByteArray;
848       *element_size = 1;
849       break;
850     case ARRAY_ID_UINT16:
851       *array_type = kExternalUnsignedShortArray;
852       *element_size = 2;
853       break;
854     case ARRAY_ID_INT16:
855       *array_type = kExternalShortArray;
856       *element_size = 2;
857       break;
858     case ARRAY_ID_UINT32:
859       *array_type = kExternalUnsignedIntArray;
860       *element_size = 4;
861       break;
862     case ARRAY_ID_INT32:
863       *array_type = kExternalIntArray;
864       *element_size = 4;
865       break;
866     case ARRAY_ID_FLOAT32:
867       *array_type = kExternalFloatArray;
868       *element_size = 4;
869       break;
870     case ARRAY_ID_FLOAT64:
871       *array_type = kExternalDoubleArray;
872       *element_size = 8;
873       break;
874     case ARRAY_ID_UINT8C:
875       *array_type = kExternalPixelArray;
876       *element_size = 1;
877       break;
878     default:
879       UNREACHABLE();
880   }
881 }
882
883
884 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
885   HandleScope scope(isolate);
886   ASSERT(args.length() == 5);
887   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
888   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
889   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
890   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
891   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
892
893   ASSERT(holder->GetInternalFieldCount() ==
894       v8::ArrayBufferView::kInternalFieldCount);
895   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
896     holder->SetInternalField(i, Smi::FromInt(0));
897   }
898
899   ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
900   size_t element_size = 1;  // Bogus initialization.
901   ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
902
903   holder->set_buffer(*buffer);
904   holder->set_byte_offset(*byte_offset_object);
905   holder->set_byte_length(*byte_length_object);
906
907   size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
908   size_t byte_length = NumberToSize(isolate, *byte_length_object);
909   ASSERT(byte_length % element_size == 0);
910   size_t length = byte_length / element_size;
911
912   Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
913   holder->set_length(*length_obj);
914   holder->set_weak_next(buffer->weak_first_view());
915   buffer->set_weak_first_view(*holder);
916
917   Handle<ExternalArray> elements =
918       isolate->factory()->NewExternalArray(
919           static_cast<int>(length), array_type,
920           static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
921   holder->set_elements(*elements);
922   return isolate->heap()->undefined_value();
923 }
924
925
926 // Initializes a typed array from an array-like object.
927 // If an array-like object happens to be a typed array of the same type,
928 // initializes backing store using memove.
929 //
930 // Returns true if backing store was initialized or false otherwise.
931 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
932   HandleScope scope(isolate);
933   ASSERT(args.length() == 4);
934   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
935   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
936   CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
937   CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
938
939   ASSERT(holder->GetInternalFieldCount() ==
940       v8::ArrayBufferView::kInternalFieldCount);
941   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
942     holder->SetInternalField(i, Smi::FromInt(0));
943   }
944
945   ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
946   size_t element_size = 1;  // Bogus initialization.
947   ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
948
949   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
950   size_t length = NumberToSize(isolate, *length_obj);
951   size_t byte_length = length * element_size;
952   if (byte_length < length) {  // Overflow
953     return isolate->Throw(*isolate->factory()->
954           NewRangeError("invalid_array_buffer_length",
955             HandleVector<Object>(NULL, 0)));
956   }
957
958   // We assume that the caller of this function will initialize holder
959   // with the loop
960   //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
961   // If source is a typed array, this loop will always run to completion,
962   // so we are sure that the backing store will be initialized.
963   // Otherwise, we do not know (the indexing operation might throw).
964   // Hence we require zero initialization unless our source is a typed array.
965   bool should_zero_initialize = !source->IsJSTypedArray();
966
967   if (!Runtime::SetupArrayBufferAllocatingData(
968         isolate, buffer, byte_length, should_zero_initialize)) {
969     return isolate->Throw(*isolate->factory()->
970           NewRangeError("invalid_array_buffer_length",
971             HandleVector<Object>(NULL, 0)));
972   }
973
974   holder->set_buffer(*buffer);
975   holder->set_byte_offset(Smi::FromInt(0));
976   Handle<Object> byte_length_obj(
977       isolate->factory()->NewNumberFromSize(byte_length));
978   holder->set_byte_length(*byte_length_obj);
979   holder->set_length(*length_obj);
980   holder->set_weak_next(buffer->weak_first_view());
981   buffer->set_weak_first_view(*holder);
982
983   Handle<ExternalArray> elements =
984       isolate->factory()->NewExternalArray(
985           static_cast<int>(length), array_type,
986           static_cast<uint8_t*>(buffer->backing_store()));
987   holder->set_elements(*elements);
988
989   if (source->IsJSTypedArray()) {
990     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
991
992     if (typed_array->type() == holder->type()) {
993       uint8_t* backing_store =
994         static_cast<uint8_t*>(
995           JSArrayBuffer::cast(typed_array->buffer())->backing_store());
996       size_t source_byte_offset =
997           NumberToSize(isolate, typed_array->byte_offset());
998       OS::MemCopy(
999           buffer->backing_store(),
1000           backing_store + source_byte_offset,
1001           byte_length);
1002       return *isolate->factory()->true_value();
1003     } else {
1004       return *isolate->factory()->false_value();
1005     }
1006   }
1007
1008   return *isolate->factory()->false_value();
1009 }
1010
1011
1012 #define TYPED_ARRAY_GETTER(getter, accessor) \
1013   RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) {             \
1014     HandleScope scope(isolate);                                               \
1015     ASSERT(args.length() == 1);                                               \
1016     CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0);                            \
1017     if (!holder->IsJSTypedArray())                                            \
1018       return isolate->Throw(*isolate->factory()->NewTypeError(                \
1019           "not_typed_array", HandleVector<Object>(NULL, 0)));                 \
1020     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder));            \
1021     return typed_array->accessor();                                           \
1022   }
1023
1024 TYPED_ARRAY_GETTER(Buffer, buffer)
1025 TYPED_ARRAY_GETTER(ByteLength, byte_length)
1026 TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
1027 TYPED_ARRAY_GETTER(Length, length)
1028
1029 #undef TYPED_ARRAY_GETTER
1030
1031 // Return codes for Runtime_TypedArraySetFastCases.
1032 // Should be synchronized with typedarray.js natives.
1033 enum TypedArraySetResultCodes {
1034   // Set from typed array of the same type.
1035   // This is processed by TypedArraySetFastCases
1036   TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
1037   // Set from typed array of the different type, overlapping in memory.
1038   TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
1039   // Set from typed array of the different type, non-overlapping.
1040   TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
1041   // Set from non-typed array.
1042   TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
1043 };
1044
1045
1046 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
1047   HandleScope scope(isolate);
1048   CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
1049   CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
1050   CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
1051
1052   if (!target_obj->IsJSTypedArray())
1053     return isolate->Throw(*isolate->factory()->NewTypeError(
1054         "not_typed_array", HandleVector<Object>(NULL, 0)));
1055
1056   if (!source_obj->IsJSTypedArray())
1057     return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
1058
1059   Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1060   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1061   size_t offset = NumberToSize(isolate, *offset_obj);
1062   size_t target_length = NumberToSize(isolate, target->length());
1063   size_t source_length = NumberToSize(isolate, source->length());
1064   size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1065   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1066   if (offset > target_length ||
1067       offset + source_length > target_length ||
1068       offset + source_length < offset)  // overflow
1069     return isolate->Throw(*isolate->factory()->NewRangeError(
1070           "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
1071
1072   size_t target_offset = NumberToSize(isolate, target->byte_offset());
1073   size_t source_offset = NumberToSize(isolate, source->byte_offset());
1074   uint8_t* target_base =
1075       static_cast<uint8_t*>(
1076         JSArrayBuffer::cast(target->buffer())->backing_store()) + target_offset;
1077   uint8_t* source_base =
1078       static_cast<uint8_t*>(
1079         JSArrayBuffer::cast(source->buffer())->backing_store()) + source_offset;
1080
1081   // Typed arrays of the same type: use memmove.
1082   if (target->type() == source->type()) {
1083     memmove(target_base + offset * target->element_size(),
1084         source_base, source_byte_length);
1085     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
1086   }
1087
1088   // Typed arrays of different types over the same backing store
1089   if ((source_base <= target_base &&
1090         source_base + source_byte_length > target_base) ||
1091       (target_base <= source_base &&
1092         target_base + target_byte_length > source_base)) {
1093     // We do not support overlapping ArrayBuffers
1094     ASSERT(
1095       JSArrayBuffer::cast(target->buffer())->backing_store() ==
1096       JSArrayBuffer::cast(source->buffer())->backing_store());
1097     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
1098   } else {  // Non-overlapping typed arrays
1099     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
1100   }
1101 }
1102
1103
1104 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
1105   HandleScope scope(isolate);
1106   ASSERT(args.length() == 4);
1107   CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
1108   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
1109   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
1110   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
1111
1112   ASSERT(holder->GetInternalFieldCount() ==
1113       v8::ArrayBufferView::kInternalFieldCount);
1114   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1115     holder->SetInternalField(i, Smi::FromInt(0));
1116   }
1117
1118   holder->set_buffer(*buffer);
1119   ASSERT(byte_offset->IsNumber());
1120   ASSERT(
1121       NumberToSize(isolate, buffer->byte_length()) >=
1122         NumberToSize(isolate, *byte_offset)
1123         + NumberToSize(isolate, *byte_length));
1124   holder->set_byte_offset(*byte_offset);
1125   ASSERT(byte_length->IsNumber());
1126   holder->set_byte_length(*byte_length);
1127
1128   holder->set_weak_next(buffer->weak_first_view());
1129   buffer->set_weak_first_view(*holder);
1130
1131   return isolate->heap()->undefined_value();
1132 }
1133
1134
1135 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
1136   HandleScope scope(isolate);
1137   ASSERT(args.length() == 1);
1138   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1139   return data_view->buffer();
1140 }
1141
1142
1143 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
1144   HandleScope scope(isolate);
1145   ASSERT(args.length() == 1);
1146   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1147   return data_view->byte_offset();
1148 }
1149
1150
1151 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
1152   HandleScope scope(isolate);
1153   ASSERT(args.length() == 1);
1154   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1155   return data_view->byte_length();
1156 }
1157
1158
1159 inline static bool NeedToFlipBytes(bool is_little_endian) {
1160 #ifdef V8_TARGET_LITTLE_ENDIAN
1161   return !is_little_endian;
1162 #else
1163   return is_little_endian;
1164 #endif
1165 }
1166
1167
1168 template<int n>
1169 inline void CopyBytes(uint8_t* target, uint8_t* source) {
1170   for (int i = 0; i < n; i++) {
1171     *(target++) = *(source++);
1172   }
1173 }
1174
1175
1176 template<int n>
1177 inline void FlipBytes(uint8_t* target, uint8_t* source) {
1178   source = source + (n-1);
1179   for (int i = 0; i < n; i++) {
1180     *(target++) = *(source--);
1181   }
1182 }
1183
1184
1185 template<typename T>
1186 inline static bool DataViewGetValue(
1187     Isolate* isolate,
1188     Handle<JSDataView> data_view,
1189     Handle<Object> byte_offset_obj,
1190     bool is_little_endian,
1191     T* result) {
1192   size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
1193   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1194
1195   size_t data_view_byte_offset =
1196       NumberToSize(isolate, data_view->byte_offset());
1197   size_t data_view_byte_length =
1198       NumberToSize(isolate, data_view->byte_length());
1199   if (byte_offset + sizeof(T) > data_view_byte_length ||
1200       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1201     return false;
1202   }
1203
1204   union Value {
1205     T data;
1206     uint8_t bytes[sizeof(T)];
1207   };
1208
1209   Value value;
1210   size_t buffer_offset = data_view_byte_offset + byte_offset;
1211   ASSERT(
1212       NumberToSize(isolate, buffer->byte_length())
1213       >= buffer_offset + sizeof(T));
1214   uint8_t* source =
1215         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1216   if (NeedToFlipBytes(is_little_endian)) {
1217     FlipBytes<sizeof(T)>(value.bytes, source);
1218   } else {
1219     CopyBytes<sizeof(T)>(value.bytes, source);
1220   }
1221   *result = value.data;
1222   return true;
1223 }
1224
1225
1226 template<typename T>
1227 static bool DataViewSetValue(
1228     Isolate* isolate,
1229     Handle<JSDataView> data_view,
1230     Handle<Object> byte_offset_obj,
1231     bool is_little_endian,
1232     T data) {
1233   size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
1234   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1235
1236   size_t data_view_byte_offset =
1237       NumberToSize(isolate, data_view->byte_offset());
1238   size_t data_view_byte_length =
1239       NumberToSize(isolate, data_view->byte_length());
1240   if (byte_offset + sizeof(T) > data_view_byte_length ||
1241       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1242     return false;
1243   }
1244
1245   union Value {
1246     T data;
1247     uint8_t bytes[sizeof(T)];
1248   };
1249
1250   Value value;
1251   value.data = data;
1252   size_t buffer_offset = data_view_byte_offset + byte_offset;
1253   ASSERT(
1254       NumberToSize(isolate, buffer->byte_length())
1255       >= buffer_offset + sizeof(T));
1256   uint8_t* target =
1257         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1258   if (NeedToFlipBytes(is_little_endian)) {
1259     FlipBytes<sizeof(T)>(target, value.bytes);
1260   } else {
1261     CopyBytes<sizeof(T)>(target, value.bytes);
1262   }
1263   return true;
1264 }
1265
1266
1267 #define DATA_VIEW_GETTER(TypeName, Type, Converter)                           \
1268   RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) {             \
1269     HandleScope scope(isolate);                                               \
1270     ASSERT(args.length() == 3);                                               \
1271     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1272     CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1273     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2);                         \
1274     Type result;                                                              \
1275     if (DataViewGetValue(                                                     \
1276           isolate, holder, offset, is_little_endian, &result)) {              \
1277       return isolate->heap()->Converter(result);                              \
1278     } else {                                                                  \
1279       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1280           "invalid_data_view_accessor_offset",                                \
1281           HandleVector<Object>(NULL, 0)));                                    \
1282     }                                                                         \
1283   }
1284
1285 DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
1286 DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
1287 DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
1288 DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
1289 DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
1290 DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
1291 DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
1292 DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
1293
1294 #undef DATA_VIEW_GETTER
1295
1296
1297 template <typename T>
1298 static T DataViewConvertValue(double value);
1299
1300
1301 template <>
1302 int8_t DataViewConvertValue<int8_t>(double value) {
1303   return static_cast<int8_t>(DoubleToInt32(value));
1304 }
1305
1306
1307 template <>
1308 int16_t DataViewConvertValue<int16_t>(double value) {
1309   return static_cast<int16_t>(DoubleToInt32(value));
1310 }
1311
1312
1313 template <>
1314 int32_t DataViewConvertValue<int32_t>(double value) {
1315   return DoubleToInt32(value);
1316 }
1317
1318
1319 template <>
1320 uint8_t DataViewConvertValue<uint8_t>(double value) {
1321   return static_cast<uint8_t>(DoubleToUint32(value));
1322 }
1323
1324
1325 template <>
1326 uint16_t DataViewConvertValue<uint16_t>(double value) {
1327   return static_cast<uint16_t>(DoubleToUint32(value));
1328 }
1329
1330
1331 template <>
1332 uint32_t DataViewConvertValue<uint32_t>(double value) {
1333   return DoubleToUint32(value);
1334 }
1335
1336
1337 template <>
1338 float DataViewConvertValue<float>(double value) {
1339   return static_cast<float>(value);
1340 }
1341
1342
1343 template <>
1344 double DataViewConvertValue<double>(double value) {
1345   return value;
1346 }
1347
1348
1349 #define DATA_VIEW_SETTER(TypeName, Type)                                      \
1350   RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) {             \
1351     HandleScope scope(isolate);                                               \
1352     ASSERT(args.length() == 4);                                               \
1353     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1354     CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1355     CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);                             \
1356     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3);                         \
1357     Type v = DataViewConvertValue<Type>(value->Number());                     \
1358     if (DataViewSetValue(                                                     \
1359           isolate, holder, offset, is_little_endian, v)) {                    \
1360       return isolate->heap()->undefined_value();                              \
1361     } else {                                                                  \
1362       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1363           "invalid_data_view_accessor_offset",                                \
1364           HandleVector<Object>(NULL, 0)));                                    \
1365     }                                                                         \
1366   }
1367
1368 DATA_VIEW_SETTER(Uint8, uint8_t)
1369 DATA_VIEW_SETTER(Int8, int8_t)
1370 DATA_VIEW_SETTER(Uint16, uint16_t)
1371 DATA_VIEW_SETTER(Int16, int16_t)
1372 DATA_VIEW_SETTER(Uint32, uint32_t)
1373 DATA_VIEW_SETTER(Int32, int32_t)
1374 DATA_VIEW_SETTER(Float32, float)
1375 DATA_VIEW_SETTER(Float64, double)
1376
1377 #undef DATA_VIEW_SETTER
1378
1379
1380 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
1381   HandleScope scope(isolate);
1382   ASSERT(args.length() == 1);
1383   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1384   Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
1385   holder->set_table(*table);
1386   return *holder;
1387 }
1388
1389
1390 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
1391   HandleScope scope(isolate);
1392   ASSERT(args.length() == 2);
1393   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1394   Handle<Object> key(args[1], isolate);
1395   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1396   table = ObjectHashSetAdd(table, key);
1397   holder->set_table(*table);
1398   return isolate->heap()->undefined_value();
1399 }
1400
1401
1402 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
1403   HandleScope scope(isolate);
1404   ASSERT(args.length() == 2);
1405   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1406   Handle<Object> key(args[1], isolate);
1407   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1408   return isolate->heap()->ToBoolean(table->Contains(*key));
1409 }
1410
1411
1412 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
1413   HandleScope scope(isolate);
1414   ASSERT(args.length() == 2);
1415   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1416   Handle<Object> key(args[1], isolate);
1417   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1418   table = ObjectHashSetRemove(table, key);
1419   holder->set_table(*table);
1420   return isolate->heap()->undefined_value();
1421 }
1422
1423
1424 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
1425   HandleScope scope(isolate);
1426   ASSERT(args.length() == 1);
1427   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1428   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1429   return Smi::FromInt(table->NumberOfElements());
1430 }
1431
1432
1433 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
1434   HandleScope scope(isolate);
1435   ASSERT(args.length() == 1);
1436   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1437   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1438   holder->set_table(*table);
1439   return *holder;
1440 }
1441
1442
1443 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
1444   HandleScope scope(isolate);
1445   ASSERT(args.length() == 2);
1446   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1447   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1448   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1449   Handle<Object> lookup(table->Lookup(*key), isolate);
1450   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1451 }
1452
1453
1454 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
1455   HandleScope scope(isolate);
1456   ASSERT(args.length() == 2);
1457   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1458   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1459   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1460   Handle<Object> lookup(table->Lookup(*key), isolate);
1461   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1462 }
1463
1464
1465 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
1466   HandleScope scope(isolate);
1467   ASSERT(args.length() == 2);
1468   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1469   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1470   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1471   Handle<Object> lookup(table->Lookup(*key), isolate);
1472   Handle<ObjectHashTable> new_table =
1473       PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
1474   holder->set_table(*new_table);
1475   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1476 }
1477
1478
1479 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
1480   HandleScope scope(isolate);
1481   ASSERT(args.length() == 3);
1482   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1483   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1484   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1485   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1486   Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
1487   holder->set_table(*new_table);
1488   return isolate->heap()->undefined_value();
1489 }
1490
1491
1492 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
1493   HandleScope scope(isolate);
1494   ASSERT(args.length() == 1);
1495   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1496   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1497   return Smi::FromInt(table->NumberOfElements());
1498 }
1499
1500
1501 static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
1502     Handle<JSWeakCollection> weak_collection) {
1503   ASSERT(weak_collection->map()->inobject_properties() == 0);
1504   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1505   weak_collection->set_table(*table);
1506   weak_collection->set_next(Smi::FromInt(0));
1507   return *weak_collection;
1508 }
1509
1510
1511 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
1512   HandleScope scope(isolate);
1513   ASSERT(args.length() == 1);
1514   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1515   return WeakCollectionInitialize(isolate, weak_collection);
1516 }
1517
1518
1519 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
1520   HandleScope scope(isolate);
1521   ASSERT(args.length() == 2);
1522   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1523   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1524   Handle<ObjectHashTable> table(
1525       ObjectHashTable::cast(weak_collection->table()));
1526   Handle<Object> lookup(table->Lookup(*key), isolate);
1527   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1528 }
1529
1530
1531 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
1532   HandleScope scope(isolate);
1533   ASSERT(args.length() == 2);
1534   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1535   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1536   Handle<ObjectHashTable> table(
1537       ObjectHashTable::cast(weak_collection->table()));
1538   Handle<Object> lookup(table->Lookup(*key), isolate);
1539   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1540 }
1541
1542
1543 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
1544   HandleScope scope(isolate);
1545   ASSERT(args.length() == 2);
1546   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1547   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1548   Handle<ObjectHashTable> table(ObjectHashTable::cast(
1549       weak_collection->table()));
1550   Handle<Object> lookup(table->Lookup(*key), isolate);
1551   Handle<ObjectHashTable> new_table =
1552       PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
1553   weak_collection->set_table(*new_table);
1554   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1555 }
1556
1557
1558 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
1559   HandleScope scope(isolate);
1560   ASSERT(args.length() == 3);
1561   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1562   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1563   Handle<Object> value(args[2], isolate);
1564   Handle<ObjectHashTable> table(
1565       ObjectHashTable::cast(weak_collection->table()));
1566   Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
1567   weak_collection->set_table(*new_table);
1568   return isolate->heap()->undefined_value();
1569 }
1570
1571
1572 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
1573   SealHandleScope shs(isolate);
1574   ASSERT(args.length() == 1);
1575   Object* obj = args[0];
1576   if (!obj->IsJSObject()) return isolate->heap()->null_value();
1577   return JSObject::cast(obj)->class_name();
1578 }
1579
1580
1581 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
1582   SealHandleScope shs(isolate);
1583   ASSERT(args.length() == 1);
1584   CONVERT_ARG_CHECKED(Object, obj, 0);
1585   // We don't expect access checks to be needed on JSProxy objects.
1586   ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1587   do {
1588     if (obj->IsAccessCheckNeeded() &&
1589         !isolate->MayNamedAccess(JSObject::cast(obj),
1590                                  isolate->heap()->proto_string(),
1591                                  v8::ACCESS_GET)) {
1592       isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
1593       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1594       return isolate->heap()->undefined_value();
1595     }
1596     obj = obj->GetPrototype(isolate);
1597   } while (obj->IsJSObject() &&
1598            JSObject::cast(obj)->map()->is_hidden_prototype());
1599   return obj;
1600 }
1601
1602
1603 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
1604                                                        Object* receiver) {
1605   Object* current = receiver->GetPrototype(isolate);
1606   while (current->IsJSObject() &&
1607          JSObject::cast(current)->map()->is_hidden_prototype()) {
1608     current = current->GetPrototype(isolate);
1609   }
1610   return current;
1611 }
1612
1613
1614 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
1615   HandleScope scope(isolate);
1616   ASSERT(args.length() == 2);
1617   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1618   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1619   if (FLAG_harmony_observation && obj->map()->is_observed()) {
1620     Handle<Object> old_value(
1621         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1622
1623     Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1624     RETURN_IF_EMPTY_HANDLE(isolate, result);
1625
1626     Handle<Object> new_value(
1627         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1628     if (!new_value->SameValue(*old_value)) {
1629       JSObject::EnqueueChangeRecord(obj, "prototype",
1630                                     isolate->factory()->proto_string(),
1631                                     old_value);
1632     }
1633     return *result;
1634   }
1635   Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1636   RETURN_IF_EMPTY_HANDLE(isolate, result);
1637   return *result;
1638 }
1639
1640
1641 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
1642   SealHandleScope shs(isolate);
1643   ASSERT(args.length() == 2);
1644   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1645   Object* O = args[0];
1646   Object* V = args[1];
1647   while (true) {
1648     Object* prototype = V->GetPrototype(isolate);
1649     if (prototype->IsNull()) return isolate->heap()->false_value();
1650     if (O == prototype) return isolate->heap()->true_value();
1651     V = prototype;
1652   }
1653 }
1654
1655
1656 static bool CheckAccessException(Object* callback,
1657                                  v8::AccessType access_type) {
1658   if (callback->IsAccessorInfo()) {
1659     AccessorInfo* info = AccessorInfo::cast(callback);
1660     return
1661         (access_type == v8::ACCESS_HAS &&
1662            (info->all_can_read() || info->all_can_write())) ||
1663         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1664         (access_type == v8::ACCESS_SET && info->all_can_write());
1665   }
1666   return false;
1667 }
1668
1669
1670 template<class Key>
1671 static bool CheckGenericAccess(
1672     JSObject* receiver,
1673     JSObject* holder,
1674     Key key,
1675     v8::AccessType access_type,
1676     bool (Isolate::*mayAccess)(JSObject*, Key, v8::AccessType)) {
1677   Isolate* isolate = receiver->GetIsolate();
1678   for (JSObject* current = receiver;
1679        true;
1680        current = JSObject::cast(current->GetPrototype())) {
1681     if (current->IsAccessCheckNeeded() &&
1682         !(isolate->*mayAccess)(current, key, access_type)) {
1683       return false;
1684     }
1685     if (current == holder) break;
1686   }
1687   return true;
1688 }
1689
1690
1691 enum AccessCheckResult {
1692   ACCESS_FORBIDDEN,
1693   ACCESS_ALLOWED,
1694   ACCESS_ABSENT
1695 };
1696
1697
1698 static AccessCheckResult CheckPropertyAccess(
1699     JSObject* obj,
1700     Name* name,
1701     v8::AccessType access_type) {
1702   uint32_t index;
1703   if (name->AsArrayIndex(&index)) {
1704     // TODO(1095): we should traverse hidden prototype hierachy as well.
1705     if (CheckGenericAccess(
1706             obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
1707       return ACCESS_ALLOWED;
1708     }
1709
1710     obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
1711     return ACCESS_FORBIDDEN;
1712   }
1713
1714   LookupResult lookup(obj->GetIsolate());
1715   obj->LocalLookup(name, &lookup, true);
1716
1717   if (!lookup.IsProperty()) return ACCESS_ABSENT;
1718   if (CheckGenericAccess<Object*>(
1719           obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) {
1720     return ACCESS_ALLOWED;
1721   }
1722
1723   // Access check callback denied the access, but some properties
1724   // can have a special permissions which override callbacks descision
1725   // (currently see v8::AccessControl).
1726   // API callbacks can have per callback access exceptions.
1727   switch (lookup.type()) {
1728     case CALLBACKS:
1729       if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1730         return ACCESS_ALLOWED;
1731       }
1732       break;
1733     case INTERCEPTOR:
1734       // If the object has an interceptor, try real named properties.
1735       // Overwrite the result to fetch the correct property later.
1736       lookup.holder()->LookupRealNamedProperty(name, &lookup);
1737       if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1738         if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1739           return ACCESS_ALLOWED;
1740         }
1741       }
1742       break;
1743     default:
1744       break;
1745   }
1746
1747   obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
1748   return ACCESS_FORBIDDEN;
1749 }
1750
1751
1752 // Enumerator used as indices into the array returned from GetOwnProperty
1753 enum PropertyDescriptorIndices {
1754   IS_ACCESSOR_INDEX,
1755   VALUE_INDEX,
1756   GETTER_INDEX,
1757   SETTER_INDEX,
1758   WRITABLE_INDEX,
1759   ENUMERABLE_INDEX,
1760   CONFIGURABLE_INDEX,
1761   DESCRIPTOR_SIZE
1762 };
1763
1764
1765 static MaybeObject* GetOwnProperty(Isolate* isolate,
1766                                    Handle<JSObject> obj,
1767                                    Handle<Name> name) {
1768   Heap* heap = isolate->heap();
1769   // Due to some WebKit tests, we want to make sure that we do not log
1770   // more than one access failure here.
1771   AccessCheckResult access_check_result =
1772       CheckPropertyAccess(*obj, *name, v8::ACCESS_HAS);
1773   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1774   switch (access_check_result) {
1775     case ACCESS_FORBIDDEN: return heap->false_value();
1776     case ACCESS_ALLOWED: break;
1777     case ACCESS_ABSENT: return heap->undefined_value();
1778   }
1779
1780   PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
1781   if (attrs == ABSENT) {
1782     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1783     return heap->undefined_value();
1784   }
1785   ASSERT(!isolate->has_scheduled_exception());
1786   AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
1787   Handle<AccessorPair> accessors(raw_accessors, isolate);
1788
1789   Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1790   elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
1791   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
1792   elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
1793
1794   if (raw_accessors == NULL) {
1795     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
1796     // GetProperty does access check.
1797     Handle<Object> value = GetProperty(isolate, obj, name);
1798     RETURN_IF_EMPTY_HANDLE(isolate, value);
1799     elms->set(VALUE_INDEX, *value);
1800   } else {
1801     // Access checks are performed for both accessors separately.
1802     // When they fail, the respective field is not set in the descriptor.
1803     Object* getter = accessors->GetComponent(ACCESSOR_GETTER);
1804     Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
1805     if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) {
1806       ASSERT(!isolate->has_scheduled_exception());
1807       elms->set(GETTER_INDEX, getter);
1808     } else {
1809       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1810     }
1811     if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) {
1812       ASSERT(!isolate->has_scheduled_exception());
1813       elms->set(SETTER_INDEX, setter);
1814     } else {
1815       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1816     }
1817   }
1818
1819   return *isolate->factory()->NewJSArrayWithElements(elms);
1820 }
1821
1822
1823 // Returns an array with the property description:
1824 //  if args[1] is not a property on args[0]
1825 //          returns undefined
1826 //  if args[1] is a data property on args[0]
1827 //         [false, value, Writeable, Enumerable, Configurable]
1828 //  if args[1] is an accessor on args[0]
1829 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
1830 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1831   HandleScope scope(isolate);
1832   ASSERT(args.length() == 2);
1833   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1834   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1835   return GetOwnProperty(isolate, obj, name);
1836 }
1837
1838
1839 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1840   SealHandleScope shs(isolate);
1841   ASSERT(args.length() == 1);
1842   CONVERT_ARG_CHECKED(JSObject, obj, 0);
1843   return obj->PreventExtensions();
1844 }
1845
1846
1847 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1848   SealHandleScope shs(isolate);
1849   ASSERT(args.length() == 1);
1850   CONVERT_ARG_CHECKED(JSObject, obj, 0);
1851   if (obj->IsJSGlobalProxy()) {
1852     Object* proto = obj->GetPrototype();
1853     if (proto->IsNull()) return isolate->heap()->false_value();
1854     ASSERT(proto->IsJSGlobalObject());
1855     obj = JSObject::cast(proto);
1856   }
1857   return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1858 }
1859
1860
1861 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1862   HandleScope scope(isolate);
1863   ASSERT(args.length() == 3);
1864   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
1865   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1866   CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
1867   Handle<Object> result =
1868       RegExpImpl::Compile(re, pattern, flags);
1869   RETURN_IF_EMPTY_HANDLE(isolate, result);
1870   return *result;
1871 }
1872
1873
1874 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1875   HandleScope scope(isolate);
1876   ASSERT(args.length() == 1);
1877   CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
1878   return *isolate->factory()->CreateApiFunction(data);
1879 }
1880
1881
1882 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1883   SealHandleScope shs(isolate);
1884   ASSERT(args.length() == 1);
1885   Object* arg = args[0];
1886   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1887   return isolate->heap()->ToBoolean(result);
1888 }
1889
1890
1891 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1892   SealHandleScope shs(isolate);
1893   ASSERT(args.length() == 2);
1894   CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1895   CONVERT_SMI_ARG_CHECKED(index, 1)
1896   int offset = index * kPointerSize + HeapObject::kHeaderSize;
1897   InstanceType type = templ->map()->instance_type();
1898   RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
1899                  type ==  OBJECT_TEMPLATE_INFO_TYPE);
1900   RUNTIME_ASSERT(offset > 0);
1901   if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1902     RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1903   } else {
1904     RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1905   }
1906   return *HeapObject::RawField(templ, offset);
1907 }
1908
1909
1910 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1911   SealHandleScope shs(isolate);
1912   ASSERT(args.length() == 1);
1913   CONVERT_ARG_CHECKED(HeapObject, object, 0);
1914   Map* old_map = object->map();
1915   bool needs_access_checks = old_map->is_access_check_needed();
1916   if (needs_access_checks) {
1917     // Copy map so it won't interfere constructor's initial map.
1918     Map* new_map;
1919     MaybeObject* maybe_new_map = old_map->Copy();
1920     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1921
1922     new_map->set_is_access_check_needed(false);
1923     object->set_map(new_map);
1924   }
1925   return isolate->heap()->ToBoolean(needs_access_checks);
1926 }
1927
1928
1929 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1930   SealHandleScope shs(isolate);
1931   ASSERT(args.length() == 1);
1932   CONVERT_ARG_CHECKED(HeapObject, object, 0);
1933   Map* old_map = object->map();
1934   if (!old_map->is_access_check_needed()) {
1935     // Copy map so it won't interfere constructor's initial map.
1936     Map* new_map;
1937     MaybeObject* maybe_new_map = old_map->Copy();
1938     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1939
1940     new_map->set_is_access_check_needed(true);
1941     object->set_map(new_map);
1942   }
1943   return isolate->heap()->undefined_value();
1944 }
1945
1946
1947 static Failure* ThrowRedeclarationError(Isolate* isolate,
1948                                         const char* type,
1949                                         Handle<String> name) {
1950   HandleScope scope(isolate);
1951   Handle<Object> type_handle =
1952       isolate->factory()->NewStringFromAscii(CStrVector(type));
1953   Handle<Object> args[2] = { type_handle, name };
1954   Handle<Object> error =
1955       isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1956   return isolate->Throw(*error);
1957 }
1958
1959
1960 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1961   HandleScope scope(isolate);
1962   ASSERT(args.length() == 3);
1963   Handle<GlobalObject> global = Handle<GlobalObject>(
1964       isolate->context()->global_object());
1965
1966   Handle<Context> context = args.at<Context>(0);
1967   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
1968   CONVERT_SMI_ARG_CHECKED(flags, 2);
1969
1970   // Traverse the name/value pairs and set the properties.
1971   int length = pairs->length();
1972   for (int i = 0; i < length; i += 2) {
1973     HandleScope scope(isolate);
1974     Handle<String> name(String::cast(pairs->get(i)));
1975     Handle<Object> value(pairs->get(i + 1), isolate);
1976
1977     // We have to declare a global const property. To capture we only
1978     // assign to it when evaluating the assignment for "const x =
1979     // <expr>" the initial value is the hole.
1980     bool is_var = value->IsUndefined();
1981     bool is_const = value->IsTheHole();
1982     bool is_function = value->IsSharedFunctionInfo();
1983     ASSERT(is_var + is_const + is_function == 1);
1984
1985     if (is_var || is_const) {
1986       // Lookup the property in the global object, and don't set the
1987       // value of the variable if the property is already there.
1988       // Do the lookup locally only, see ES5 erratum.
1989       LookupResult lookup(isolate);
1990       if (FLAG_es52_globals) {
1991         global->LocalLookup(*name, &lookup, true);
1992       } else {
1993         global->Lookup(*name, &lookup);
1994       }
1995       if (lookup.IsFound()) {
1996         // We found an existing property. Unless it was an interceptor
1997         // that claims the property is absent, skip this declaration.
1998         if (!lookup.IsInterceptor()) continue;
1999         PropertyAttributes attributes = global->GetPropertyAttribute(*name);
2000         if (attributes != ABSENT) continue;
2001         // Fall-through and introduce the absent property by using
2002         // SetProperty.
2003       }
2004     } else if (is_function) {
2005       // Copy the function and update its context. Use it as value.
2006       Handle<SharedFunctionInfo> shared =
2007           Handle<SharedFunctionInfo>::cast(value);
2008       Handle<JSFunction> function =
2009           isolate->factory()->NewFunctionFromSharedFunctionInfo(
2010               shared, context, TENURED);
2011       value = function;
2012     }
2013
2014     LookupResult lookup(isolate);
2015     global->LocalLookup(*name, &lookup, true);
2016
2017     // Compute the property attributes. According to ECMA-262,
2018     // the property must be non-configurable except in eval.
2019     int attr = NONE;
2020     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2021     if (!is_eval) {
2022       attr |= DONT_DELETE;
2023     }
2024     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2025     if (is_const || (is_native && is_function)) {
2026       attr |= READ_ONLY;
2027     }
2028
2029     LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
2030
2031     if (!lookup.IsFound() || is_function) {
2032       // If the local property exists, check that we can reconfigure it
2033       // as required for function declarations.
2034       if (lookup.IsFound() && lookup.IsDontDelete()) {
2035         if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2036             lookup.IsPropertyCallbacks()) {
2037           return ThrowRedeclarationError(isolate, "function", name);
2038         }
2039         // If the existing property is not configurable, keep its attributes.
2040         attr = lookup.GetAttributes();
2041       }
2042       // Define or redefine own property.
2043       RETURN_IF_EMPTY_HANDLE(isolate,
2044           JSObject::SetLocalPropertyIgnoreAttributes(
2045               global, name, value, static_cast<PropertyAttributes>(attr)));
2046     } else {
2047       // Do a [[Put]] on the existing (own) property.
2048       RETURN_IF_EMPTY_HANDLE(isolate,
2049           JSObject::SetProperty(
2050               global, name, value, static_cast<PropertyAttributes>(attr),
2051               language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
2052     }
2053   }
2054
2055   ASSERT(!isolate->has_pending_exception());
2056   return isolate->heap()->undefined_value();
2057 }
2058
2059
2060 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
2061   HandleScope scope(isolate);
2062   ASSERT(args.length() == 4);
2063
2064   // Declarations are always made in a function or native context.  In the
2065   // case of eval code, the context passed is the context of the caller,
2066   // which may be some nested context and not the declaration context.
2067   RUNTIME_ASSERT(args[0]->IsContext());
2068   Handle<Context> context(Context::cast(args[0])->declaration_context());
2069
2070   Handle<String> name(String::cast(args[1]));
2071   PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
2072   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2073   Handle<Object> initial_value(args[3], isolate);
2074
2075   int index;
2076   PropertyAttributes attributes;
2077   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2078   BindingFlags binding_flags;
2079   Handle<Object> holder =
2080       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2081
2082   if (attributes != ABSENT) {
2083     // The name was declared before; check for conflicting re-declarations.
2084     // Note: this is actually inconsistent with what happens for globals (where
2085     // we silently ignore such declarations).
2086     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2087       // Functions are not read-only.
2088       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2089       const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
2090       return ThrowRedeclarationError(isolate, type, name);
2091     }
2092
2093     // Initialize it if necessary.
2094     if (*initial_value != NULL) {
2095       if (index >= 0) {
2096         ASSERT(holder.is_identical_to(context));
2097         if (((attributes & READ_ONLY) == 0) ||
2098             context->get(index)->IsTheHole()) {
2099           context->set(index, *initial_value);
2100         }
2101       } else {
2102         // Slow case: The property is in the context extension object of a
2103         // function context or the global object of a native context.
2104         Handle<JSObject> object = Handle<JSObject>::cast(holder);
2105         RETURN_IF_EMPTY_HANDLE(
2106             isolate,
2107             JSReceiver::SetProperty(object, name, initial_value, mode,
2108                                     kNonStrictMode));
2109       }
2110     }
2111
2112   } else {
2113     // The property is not in the function context. It needs to be
2114     // "declared" in the function context's extension context or as a
2115     // property of the the global object.
2116     Handle<JSObject> object;
2117     if (context->has_extension()) {
2118       object = Handle<JSObject>(JSObject::cast(context->extension()));
2119     } else {
2120       // Context extension objects are allocated lazily.
2121       ASSERT(context->IsFunctionContext());
2122       object = isolate->factory()->NewJSObject(
2123           isolate->context_extension_function());
2124       context->set_extension(*object);
2125     }
2126     ASSERT(*object != NULL);
2127
2128     // Declare the property by setting it to the initial value if provided,
2129     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2130     // constant declarations).
2131     ASSERT(!object->HasLocalProperty(*name));
2132     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2133     if (*initial_value != NULL) value = initial_value;
2134     // Declaring a const context slot is a conflicting declaration if
2135     // there is a callback with that name in a prototype. It is
2136     // allowed to introduce const variables in
2137     // JSContextExtensionObjects. They are treated specially in
2138     // SetProperty and no setters are invoked for those since they are
2139     // not real JSObjects.
2140     if (initial_value->IsTheHole() &&
2141         !object->IsJSContextExtensionObject()) {
2142       LookupResult lookup(isolate);
2143       object->Lookup(*name, &lookup);
2144       if (lookup.IsPropertyCallbacks()) {
2145         return ThrowRedeclarationError(isolate, "const", name);
2146       }
2147     }
2148     if (object->IsJSGlobalObject()) {
2149       // Define own property on the global object.
2150       RETURN_IF_EMPTY_HANDLE(isolate,
2151          JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
2152     } else {
2153       RETURN_IF_EMPTY_HANDLE(isolate,
2154          JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
2155     }
2156   }
2157
2158   return isolate->heap()->undefined_value();
2159 }
2160
2161
2162 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
2163   SealHandleScope shs(isolate);
2164   // args[0] == name
2165   // args[1] == language_mode
2166   // args[2] == value (optional)
2167
2168   // Determine if we need to assign to the variable if it already
2169   // exists (based on the number of arguments).
2170   RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
2171   bool assign = args.length() == 3;
2172
2173   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2174   GlobalObject* global = isolate->context()->global_object();
2175   RUNTIME_ASSERT(args[1]->IsSmi());
2176   CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
2177   StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
2178       ? kNonStrictMode : kStrictMode;
2179
2180   // According to ECMA-262, section 12.2, page 62, the property must
2181   // not be deletable.
2182   PropertyAttributes attributes = DONT_DELETE;
2183
2184   // Lookup the property locally in the global object. If it isn't
2185   // there, there is a property with this name in the prototype chain.
2186   // We follow Safari and Firefox behavior and only set the property
2187   // locally if there is an explicit initialization value that we have
2188   // to assign to the property.
2189   // Note that objects can have hidden prototypes, so we need to traverse
2190   // the whole chain of hidden prototypes to do a 'local' lookup.
2191   Object* object = global;
2192   LookupResult lookup(isolate);
2193   JSObject::cast(object)->LocalLookup(*name, &lookup, true);
2194   if (lookup.IsInterceptor()) {
2195     HandleScope handle_scope(isolate);
2196     PropertyAttributes intercepted =
2197         lookup.holder()->GetPropertyAttribute(*name);
2198     if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2199       // Found an interceptor that's not read only.
2200       if (assign) {
2201         return lookup.holder()->SetProperty(
2202             &lookup, *name, args[2], attributes, strict_mode_flag);
2203       } else {
2204         return isolate->heap()->undefined_value();
2205       }
2206     }
2207   }
2208
2209   // Reload global in case the loop above performed a GC.
2210   global = isolate->context()->global_object();
2211   if (assign) {
2212     return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
2213   }
2214   return isolate->heap()->undefined_value();
2215 }
2216
2217
2218 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
2219   SealHandleScope shs(isolate);
2220   // All constants are declared with an initial value. The name
2221   // of the constant is the first argument and the initial value
2222   // is the second.
2223   RUNTIME_ASSERT(args.length() == 2);
2224   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2225   Handle<Object> value = args.at<Object>(1);
2226
2227   // Get the current global object from top.
2228   GlobalObject* global = isolate->context()->global_object();
2229
2230   // According to ECMA-262, section 12.2, page 62, the property must
2231   // not be deletable. Since it's a const, it must be READ_ONLY too.
2232   PropertyAttributes attributes =
2233       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2234
2235   // Lookup the property locally in the global object. If it isn't
2236   // there, we add the property and take special precautions to always
2237   // add it as a local property even in case of callbacks in the
2238   // prototype chain (this rules out using SetProperty).
2239   // We use SetLocalPropertyIgnoreAttributes instead
2240   LookupResult lookup(isolate);
2241   global->LocalLookup(*name, &lookup);
2242   if (!lookup.IsFound()) {
2243     return global->SetLocalPropertyIgnoreAttributes(*name,
2244                                                     *value,
2245                                                     attributes);
2246   }
2247
2248   if (!lookup.IsReadOnly()) {
2249     // Restore global object from context (in case of GC) and continue
2250     // with setting the value.
2251     HandleScope handle_scope(isolate);
2252     Handle<GlobalObject> global(isolate->context()->global_object());
2253
2254     // BUG 1213575: Handle the case where we have to set a read-only
2255     // property through an interceptor and only do it if it's
2256     // uninitialized, e.g. the hole. Nirk...
2257     // Passing non-strict mode because the property is writable.
2258     RETURN_IF_EMPTY_HANDLE(
2259         isolate,
2260         JSReceiver::SetProperty(global, name, value, attributes,
2261                                 kNonStrictMode));
2262     return *value;
2263   }
2264
2265   // Set the value, but only if we're assigning the initial value to a
2266   // constant. For now, we determine this by checking if the
2267   // current value is the hole.
2268   // Strict mode handling not needed (const is disallowed in strict mode).
2269   if (lookup.IsField()) {
2270     FixedArray* properties = global->properties();
2271     int index = lookup.GetFieldIndex().field_index();
2272     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2273       properties->set(index, *value);
2274     }
2275   } else if (lookup.IsNormal()) {
2276     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2277         !lookup.IsReadOnly()) {
2278       HandleScope scope(isolate);
2279       JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2280     }
2281   } else {
2282     // Ignore re-initialization of constants that have already been
2283     // assigned a constant value.
2284     ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2285   }
2286
2287   // Use the set value as the result of the operation.
2288   return *value;
2289 }
2290
2291
2292 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
2293   HandleScope scope(isolate);
2294   ASSERT(args.length() == 3);
2295
2296   Handle<Object> value(args[0], isolate);
2297   ASSERT(!value->IsTheHole());
2298
2299   // Initializations are always done in a function or native context.
2300   RUNTIME_ASSERT(args[1]->IsContext());
2301   Handle<Context> context(Context::cast(args[1])->declaration_context());
2302
2303   Handle<String> name(String::cast(args[2]));
2304
2305   int index;
2306   PropertyAttributes attributes;
2307   ContextLookupFlags flags = FOLLOW_CHAINS;
2308   BindingFlags binding_flags;
2309   Handle<Object> holder =
2310       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2311
2312   if (index >= 0) {
2313     ASSERT(holder->IsContext());
2314     // Property was found in a context.  Perform the assignment if we
2315     // found some non-constant or an uninitialized constant.
2316     Handle<Context> context = Handle<Context>::cast(holder);
2317     if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
2318       context->set(index, *value);
2319     }
2320     return *value;
2321   }
2322
2323   // The property could not be found, we introduce it as a property of the
2324   // global object.
2325   if (attributes == ABSENT) {
2326     Handle<JSObject> global = Handle<JSObject>(
2327         isolate->context()->global_object());
2328     // Strict mode not needed (const disallowed in strict mode).
2329     RETURN_IF_EMPTY_HANDLE(
2330         isolate,
2331         JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
2332     return *value;
2333   }
2334
2335   // The property was present in some function's context extension object,
2336   // as a property on the subject of a with, or as a property of the global
2337   // object.
2338   //
2339   // In most situations, eval-introduced consts should still be present in
2340   // the context extension object.  However, because declaration and
2341   // initialization are separate, the property might have been deleted
2342   // before we reach the initialization point.
2343   //
2344   // Example:
2345   //
2346   //    function f() { eval("delete x; const x;"); }
2347   //
2348   // In that case, the initialization behaves like a normal assignment.
2349   Handle<JSObject> object = Handle<JSObject>::cast(holder);
2350
2351   if (*object == context->extension()) {
2352     // This is the property that was introduced by the const declaration.
2353     // Set it if it hasn't been set before.  NOTE: We cannot use
2354     // GetProperty() to get the current value as it 'unholes' the value.
2355     LookupResult lookup(isolate);
2356     object->LocalLookupRealNamedProperty(*name, &lookup);
2357     ASSERT(lookup.IsFound());  // the property was declared
2358     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
2359
2360     if (lookup.IsField()) {
2361       FixedArray* properties = object->properties();
2362       int index = lookup.GetFieldIndex().field_index();
2363       if (properties->get(index)->IsTheHole()) {
2364         properties->set(index, *value);
2365       }
2366     } else if (lookup.IsNormal()) {
2367       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2368         JSObject::SetNormalizedProperty(object, &lookup, value);
2369       }
2370     } else {
2371       // We should not reach here. Any real, named property should be
2372       // either a field or a dictionary slot.
2373       UNREACHABLE();
2374     }
2375   } else {
2376     // The property was found on some other object.  Set it if it is not a
2377     // read-only property.
2378     if ((attributes & READ_ONLY) == 0) {
2379       // Strict mode not needed (const disallowed in strict mode).
2380       RETURN_IF_EMPTY_HANDLE(
2381           isolate,
2382           JSReceiver::SetProperty(object, name, value, attributes,
2383                                   kNonStrictMode));
2384     }
2385   }
2386
2387   return *value;
2388 }
2389
2390
2391 RUNTIME_FUNCTION(MaybeObject*,
2392                  Runtime_OptimizeObjectForAddingMultipleProperties) {
2393   HandleScope scope(isolate);
2394   ASSERT(args.length() == 2);
2395   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2396   CONVERT_SMI_ARG_CHECKED(properties, 1);
2397   if (object->HasFastProperties()) {
2398     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
2399   }
2400   return *object;
2401 }
2402
2403
2404 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
2405   HandleScope scope(isolate);
2406   ASSERT(args.length() == 4);
2407   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2408   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2409   // Due to the way the JS calls are constructed this must be less than the
2410   // length of a string, i.e. it is always a Smi.  We check anyway for security.
2411   CONVERT_SMI_ARG_CHECKED(index, 2);
2412   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2413   RUNTIME_ASSERT(index >= 0);
2414   RUNTIME_ASSERT(index <= subject->length());
2415   isolate->counters()->regexp_entry_runtime()->Increment();
2416   Handle<Object> result = RegExpImpl::Exec(regexp,
2417                                            subject,
2418                                            index,
2419                                            last_match_info);
2420   RETURN_IF_EMPTY_HANDLE(isolate, result);
2421   return *result;
2422 }
2423
2424
2425 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
2426   SealHandleScope shs(isolate);
2427   ASSERT(args.length() == 3);
2428   CONVERT_SMI_ARG_CHECKED(elements_count, 0);
2429   if (elements_count < 0 ||
2430       elements_count > FixedArray::kMaxLength ||
2431       !Smi::IsValid(elements_count)) {
2432     return isolate->ThrowIllegalOperation();
2433   }
2434   Object* new_object;
2435   { MaybeObject* maybe_new_object =
2436         isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
2437     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2438   }
2439   FixedArray* elements = FixedArray::cast(new_object);
2440   { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
2441       JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
2442     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2443   }
2444   {
2445     DisallowHeapAllocation no_gc;
2446     HandleScope scope(isolate);
2447     reinterpret_cast<HeapObject*>(new_object)->
2448         set_map(isolate->native_context()->regexp_result_map());
2449   }
2450   JSArray* array = JSArray::cast(new_object);
2451   array->set_properties(isolate->heap()->empty_fixed_array());
2452   array->set_elements(elements);
2453   array->set_length(Smi::FromInt(elements_count));
2454   // Write in-object properties after the length of the array.
2455   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
2456   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
2457   return array;
2458 }
2459
2460
2461 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
2462   SealHandleScope shs(isolate);
2463   DisallowHeapAllocation no_allocation;
2464   ASSERT(args.length() == 5);
2465   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
2466   CONVERT_ARG_CHECKED(String, source, 1);
2467   // If source is the empty string we set it to "(?:)" instead as
2468   // suggested by ECMA-262, 5th, section 15.10.4.1.
2469   if (source->length() == 0) source = isolate->heap()->query_colon_string();
2470
2471   Object* global = args[2];
2472   if (!global->IsTrue()) global = isolate->heap()->false_value();
2473
2474   Object* ignoreCase = args[3];
2475   if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
2476
2477   Object* multiline = args[4];
2478   if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
2479
2480   Map* map = regexp->map();
2481   Object* constructor = map->constructor();
2482   if (constructor->IsJSFunction() &&
2483       JSFunction::cast(constructor)->initial_map() == map) {
2484     // If we still have the original map, set in-object properties directly.
2485     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
2486     // Both true and false are immovable immortal objects so no need for write
2487     // barrier.
2488     regexp->InObjectPropertyAtPut(
2489         JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
2490     regexp->InObjectPropertyAtPut(
2491         JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
2492     regexp->InObjectPropertyAtPut(
2493         JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
2494     regexp->InObjectPropertyAtPut(
2495         JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
2496     return regexp;
2497   }
2498
2499   // Map has changed, so use generic, but slower, method.
2500   PropertyAttributes final =
2501       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2502   PropertyAttributes writable =
2503       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2504   Heap* heap = isolate->heap();
2505   MaybeObject* result;
2506   result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_string(),
2507                                                     source,
2508                                                     final);
2509   // TODO(jkummerow): Turn these back into ASSERTs when we can be certain
2510   // that it never fires in Release mode in the wild.
2511   CHECK(!result->IsFailure());
2512   result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_string(),
2513                                                     global,
2514                                                     final);
2515   CHECK(!result->IsFailure());
2516   result =
2517       regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_string(),
2518                                                ignoreCase,
2519                                                final);
2520   CHECK(!result->IsFailure());
2521   result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_string(),
2522                                                     multiline,
2523                                                     final);
2524   CHECK(!result->IsFailure());
2525   result =
2526       regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_string(),
2527                                                Smi::FromInt(0),
2528                                                writable);
2529   CHECK(!result->IsFailure());
2530   USE(result);
2531   return regexp;
2532 }
2533
2534
2535 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
2536   HandleScope scope(isolate);
2537   ASSERT(args.length() == 1);
2538   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2539   // This is necessary to enable fast checks for absence of elements
2540   // on Array.prototype and below.
2541   prototype->set_elements(isolate->heap()->empty_fixed_array());
2542   return Smi::FromInt(0);
2543 }
2544
2545
2546 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
2547                                          Handle<JSObject> holder,
2548                                          const char* name,
2549                                          Builtins::Name builtin_name) {
2550   Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2551   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2552   Handle<JSFunction> optimized =
2553       isolate->factory()->NewFunction(key,
2554                                       JS_OBJECT_TYPE,
2555                                       JSObject::kHeaderSize,
2556                                       code,
2557                                       false);
2558   optimized->shared()->DontAdaptArguments();
2559   JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
2560   return optimized;
2561 }
2562
2563
2564 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
2565   HandleScope scope(isolate);
2566   ASSERT(args.length() == 1);
2567   CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
2568
2569   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2570   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2571   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2572   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2573   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2574   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2575   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2576
2577   return *holder;
2578 }
2579
2580
2581 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) {
2582   SealHandleScope shs(isolate);
2583   ASSERT(args.length() == 1);
2584   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2585   if (!callable->IsJSFunction()) {
2586     HandleScope scope(isolate);
2587     bool threw = false;
2588     Handle<Object> delegate =
2589         Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
2590     if (threw) return Failure::Exception();
2591     callable = JSFunction::cast(*delegate);
2592   }
2593   JSFunction* function = JSFunction::cast(callable);
2594   SharedFunctionInfo* shared = function->shared();
2595   return isolate->heap()->ToBoolean(shared->is_classic_mode());
2596 }
2597
2598
2599 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
2600   SealHandleScope shs(isolate);
2601   ASSERT(args.length() == 1);
2602   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2603
2604   if (!callable->IsJSFunction()) {
2605     HandleScope scope(isolate);
2606     bool threw = false;
2607     Handle<Object> delegate =
2608         Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
2609     if (threw) return Failure::Exception();
2610     callable = JSFunction::cast(*delegate);
2611   }
2612   JSFunction* function = JSFunction::cast(callable);
2613
2614   SharedFunctionInfo* shared = function->shared();
2615   if (shared->native() || !shared->is_classic_mode()) {
2616     return isolate->heap()->undefined_value();
2617   }
2618   // Returns undefined for strict or native functions, or
2619   // the associated global receiver for "normal" functions.
2620
2621   Context* native_context =
2622       function->context()->global_object()->native_context();
2623   return native_context->global_object()->global_receiver();
2624 }
2625
2626
2627 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
2628   HandleScope scope(isolate);
2629   ASSERT(args.length() == 4);
2630   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2631   int index = args.smi_at(1);
2632   Handle<String> pattern = args.at<String>(2);
2633   Handle<String> flags = args.at<String>(3);
2634
2635   // Get the RegExp function from the context in the literals array.
2636   // This is the RegExp function from the context in which the
2637   // function was created.  We do not use the RegExp function from the
2638   // current native context because this might be the RegExp function
2639   // from another context which we should not have access to.
2640   Handle<JSFunction> constructor =
2641       Handle<JSFunction>(
2642           JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2643   // Compute the regular expression literal.
2644   bool has_pending_exception;
2645   Handle<Object> regexp =
2646       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2647                                       &has_pending_exception);
2648   if (has_pending_exception) {
2649     ASSERT(isolate->has_pending_exception());
2650     return Failure::Exception();
2651   }
2652   literals->set(index, *regexp);
2653   return *regexp;
2654 }
2655
2656
2657 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2658   SealHandleScope shs(isolate);
2659   ASSERT(args.length() == 1);
2660
2661   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2662   return f->shared()->name();
2663 }
2664
2665
2666 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2667   SealHandleScope shs(isolate);
2668   ASSERT(args.length() == 2);
2669
2670   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2671   CONVERT_ARG_CHECKED(String, name, 1);
2672   f->shared()->set_name(name);
2673   return isolate->heap()->undefined_value();
2674 }
2675
2676
2677 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2678   SealHandleScope shs(isolate);
2679   ASSERT(args.length() == 1);
2680   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2681   return isolate->heap()->ToBoolean(
2682       f->shared()->name_should_print_as_anonymous());
2683 }
2684
2685
2686 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2687   SealHandleScope shs(isolate);
2688   ASSERT(args.length() == 1);
2689   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2690   f->shared()->set_name_should_print_as_anonymous(true);
2691   return isolate->heap()->undefined_value();
2692 }
2693
2694
2695 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
2696   SealHandleScope shs(isolate);
2697   ASSERT(args.length() == 1);
2698   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2699   return isolate->heap()->ToBoolean(f->shared()->is_generator());
2700 }
2701
2702
2703 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2704   SealHandleScope shs(isolate);
2705   ASSERT(args.length() == 1);
2706
2707   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2708   f->RemovePrototype();
2709
2710   return isolate->heap()->undefined_value();
2711 }
2712
2713
2714 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2715   HandleScope scope(isolate);
2716   ASSERT(args.length() == 1);
2717
2718   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2719   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2720   if (!script->IsScript()) return isolate->heap()->undefined_value();
2721
2722   return *GetScriptWrapper(Handle<Script>::cast(script));
2723 }
2724
2725
2726 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2727   HandleScope scope(isolate);
2728   ASSERT(args.length() == 1);
2729
2730   CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2731   Handle<SharedFunctionInfo> shared(f->shared());
2732   return *shared->GetSourceCode();
2733 }
2734
2735
2736 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2737   SealHandleScope shs(isolate);
2738   ASSERT(args.length() == 1);
2739
2740   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2741   int pos = fun->shared()->start_position();
2742   return Smi::FromInt(pos);
2743 }
2744
2745
2746 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2747   SealHandleScope shs(isolate);
2748   ASSERT(args.length() == 2);
2749
2750   CONVERT_ARG_CHECKED(Code, code, 0);
2751   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2752
2753   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2754
2755   Address pc = code->address() + offset;
2756   return Smi::FromInt(code->SourcePosition(pc));
2757 }
2758
2759
2760 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2761   SealHandleScope shs(isolate);
2762   ASSERT(args.length() == 2);
2763
2764   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2765   CONVERT_ARG_CHECKED(String, name, 1);
2766   fun->SetInstanceClassName(name);
2767   return isolate->heap()->undefined_value();
2768 }
2769
2770
2771 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2772   SealHandleScope shs(isolate);
2773   ASSERT(args.length() == 2);
2774
2775   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2776   CONVERT_SMI_ARG_CHECKED(length, 1);
2777   fun->shared()->set_length(length);
2778   return isolate->heap()->undefined_value();
2779 }
2780
2781
2782 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2783   SealHandleScope shs(isolate);
2784   ASSERT(args.length() == 2);
2785
2786   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2787   ASSERT(fun->should_have_prototype());
2788   Object* obj;
2789   { MaybeObject* maybe_obj =
2790         Accessors::FunctionSetPrototype(fun, args[1], NULL);
2791     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2792   }
2793   return args[0];  // return TOS
2794 }
2795
2796
2797 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2798   SealHandleScope shs(isolate);
2799   RUNTIME_ASSERT(args.length() == 1);
2800   CONVERT_ARG_CHECKED(JSFunction, function, 0);
2801
2802   String* name = isolate->heap()->prototype_string();
2803
2804   if (function->HasFastProperties()) {
2805     // Construct a new field descriptor with updated attributes.
2806     DescriptorArray* instance_desc = function->map()->instance_descriptors();
2807
2808     int index = instance_desc->SearchWithCache(name, function->map());
2809     ASSERT(index != DescriptorArray::kNotFound);
2810     PropertyDetails details = instance_desc->GetDetails(index);
2811
2812     CallbacksDescriptor new_desc(name,
2813         instance_desc->GetValue(index),
2814         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
2815
2816     // Create a new map featuring the new field descriptors array.
2817     Map* new_map;
2818     MaybeObject* maybe_map =
2819         function->map()->CopyReplaceDescriptor(
2820             instance_desc, &new_desc, index, OMIT_TRANSITION);
2821     if (!maybe_map->To(&new_map)) return maybe_map;
2822
2823     function->set_map(new_map);
2824   } else {  // Dictionary properties.
2825     // Directly manipulate the property details.
2826     int entry = function->property_dictionary()->FindEntry(name);
2827     ASSERT(entry != NameDictionary::kNotFound);
2828     PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2829     PropertyDetails new_details(
2830         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2831         details.type(),
2832         details.dictionary_index());
2833     function->property_dictionary()->DetailsAtPut(entry, new_details);
2834   }
2835   return function;
2836 }
2837
2838
2839 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2840   SealHandleScope shs(isolate);
2841   ASSERT(args.length() == 1);
2842
2843   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2844   return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2845 }
2846
2847
2848 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2849   SealHandleScope shs(isolate);
2850   ASSERT(args.length() == 1);
2851
2852   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2853   return isolate->heap()->ToBoolean(f->IsBuiltin());
2854 }
2855
2856
2857 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2858   HandleScope scope(isolate);
2859   ASSERT(args.length() == 2);
2860
2861   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2862   Handle<Object> code = args.at<Object>(1);
2863
2864   if (code->IsNull()) return *target;
2865   RUNTIME_ASSERT(code->IsJSFunction());
2866   Handle<JSFunction> source = Handle<JSFunction>::cast(code);
2867   Handle<SharedFunctionInfo> target_shared(target->shared());
2868   Handle<SharedFunctionInfo> source_shared(source->shared());
2869
2870   if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
2871     return Failure::Exception();
2872   }
2873
2874   // Mark both, the source and the target, as un-flushable because the
2875   // shared unoptimized code makes them impossible to enqueue in a list.
2876   ASSERT(target_shared->code()->gc_metadata() == NULL);
2877   ASSERT(source_shared->code()->gc_metadata() == NULL);
2878   target_shared->set_dont_flush(true);
2879   source_shared->set_dont_flush(true);
2880
2881   // Set the code, scope info, formal parameter count, and the length
2882   // of the target shared function info.  Set the source code of the
2883   // target function to undefined.  SetCode is only used for built-in
2884   // constructors like String, Array, and Object, and some web code
2885   // doesn't like seeing source code for constructors.
2886   target_shared->ReplaceCode(source_shared->code());
2887   target_shared->set_scope_info(source_shared->scope_info());
2888   target_shared->set_length(source_shared->length());
2889   target_shared->set_formal_parameter_count(
2890       source_shared->formal_parameter_count());
2891   target_shared->set_script(isolate->heap()->undefined_value());
2892
2893   // Since we don't store the source we should never optimize this.
2894   target_shared->code()->set_optimizable(false);
2895
2896   // Set the code of the target function.
2897   target->ReplaceCode(source_shared->code());
2898   ASSERT(target->next_function_link()->IsUndefined());
2899
2900   // Make sure we get a fresh copy of the literal vector to avoid cross
2901   // context contamination.
2902   Handle<Context> context(source->context());
2903   int number_of_literals = source->NumberOfLiterals();
2904   Handle<FixedArray> literals =
2905       isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2906   if (number_of_literals > 0) {
2907     literals->set(JSFunction::kLiteralNativeContextIndex,
2908                   context->native_context());
2909   }
2910   target->set_context(*context);
2911   target->set_literals(*literals);
2912
2913   if (isolate->logger()->is_logging_code_events() ||
2914       isolate->cpu_profiler()->is_profiling()) {
2915     isolate->logger()->LogExistingFunction(
2916         source_shared, Handle<Code>(source_shared->code()));
2917   }
2918
2919   return *target;
2920 }
2921
2922
2923 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2924   HandleScope scope(isolate);
2925   ASSERT(args.length() == 2);
2926   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2927   CONVERT_SMI_ARG_CHECKED(num, 1);
2928   RUNTIME_ASSERT(num >= 0);
2929   SetExpectedNofProperties(function, num);
2930   return isolate->heap()->undefined_value();
2931 }
2932
2933
2934 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
2935   SealHandleScope shs(isolate);
2936   ASSERT(args.length() == 0);
2937
2938   JavaScriptFrameIterator it(isolate);
2939   JavaScriptFrame* frame = it.frame();
2940   JSFunction* function = frame->function();
2941   RUNTIME_ASSERT(function->shared()->is_generator());
2942
2943   JSGeneratorObject* generator;
2944   if (frame->IsConstructor()) {
2945     generator = JSGeneratorObject::cast(frame->receiver());
2946   } else {
2947     MaybeObject* maybe_generator =
2948         isolate->heap()->AllocateJSGeneratorObject(function);
2949     if (!maybe_generator->To(&generator)) return maybe_generator;
2950   }
2951   generator->set_function(function);
2952   generator->set_context(Context::cast(frame->context()));
2953   generator->set_receiver(frame->receiver());
2954   generator->set_continuation(0);
2955   generator->set_operand_stack(isolate->heap()->empty_fixed_array());
2956   generator->set_stack_handler_index(-1);
2957
2958   return generator;
2959 }
2960
2961
2962 RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
2963   SealHandleScope shs(isolate);
2964   ASSERT(args.length() == 1);
2965   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
2966
2967   JavaScriptFrameIterator stack_iterator(isolate);
2968   JavaScriptFrame* frame = stack_iterator.frame();
2969   RUNTIME_ASSERT(frame->function()->shared()->is_generator());
2970   ASSERT_EQ(frame->function(), generator_object->function());
2971
2972   // The caller should have saved the context and continuation already.
2973   ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
2974   ASSERT_LT(0, generator_object->continuation());
2975
2976   // We expect there to be at least two values on the operand stack: the return
2977   // value of the yield expression, and the argument to this runtime call.
2978   // Neither of those should be saved.
2979   int operands_count = frame->ComputeOperandsCount();
2980   ASSERT_GE(operands_count, 2);
2981   operands_count -= 2;
2982
2983   if (operands_count == 0) {
2984     // Although it's semantically harmless to call this function with an
2985     // operands_count of zero, it is also unnecessary.
2986     ASSERT_EQ(generator_object->operand_stack(),
2987               isolate->heap()->empty_fixed_array());
2988     ASSERT_EQ(generator_object->stack_handler_index(), -1);
2989     // If there are no operands on the stack, there shouldn't be a handler
2990     // active either.
2991     ASSERT(!frame->HasHandler());
2992   } else {
2993     int stack_handler_index = -1;
2994     MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
2995     FixedArray* operand_stack;
2996     if (!alloc->To(&operand_stack)) return alloc;
2997     frame->SaveOperandStack(operand_stack, &stack_handler_index);
2998     generator_object->set_operand_stack(operand_stack);
2999     generator_object->set_stack_handler_index(stack_handler_index);
3000   }
3001
3002   return isolate->heap()->undefined_value();
3003 }
3004
3005
3006 // Note that this function is the slow path for resuming generators.  It is only
3007 // called if the suspended activation had operands on the stack, stack handlers
3008 // needing rewinding, or if the resume should throw an exception.  The fast path
3009 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3010 // inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
3011 // called in any case, as it needs to reconstruct the stack frame and make space
3012 // for arguments and operands.
3013 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
3014   SealHandleScope shs(isolate);
3015   ASSERT(args.length() == 3);
3016   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3017   CONVERT_ARG_CHECKED(Object, value, 1);
3018   CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3019   JavaScriptFrameIterator stack_iterator(isolate);
3020   JavaScriptFrame* frame = stack_iterator.frame();
3021
3022   ASSERT_EQ(frame->function(), generator_object->function());
3023   ASSERT(frame->function()->is_compiled());
3024
3025   STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
3026   STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
3027
3028   Address pc = generator_object->function()->code()->instruction_start();
3029   int offset = generator_object->continuation();
3030   ASSERT(offset > 0);
3031   frame->set_pc(pc + offset);
3032   generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3033
3034   FixedArray* operand_stack = generator_object->operand_stack();
3035   int operands_count = operand_stack->length();
3036   if (operands_count != 0) {
3037     frame->RestoreOperandStack(operand_stack,
3038                                generator_object->stack_handler_index());
3039     generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3040     generator_object->set_stack_handler_index(-1);
3041   }
3042
3043   JSGeneratorObject::ResumeMode resume_mode =
3044       static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3045   switch (resume_mode) {
3046     case JSGeneratorObject::NEXT:
3047       return value;
3048     case JSGeneratorObject::THROW:
3049       return isolate->Throw(value);
3050   }
3051
3052   UNREACHABLE();
3053   return isolate->ThrowIllegalOperation();
3054 }
3055
3056
3057 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
3058   HandleScope scope(isolate);
3059   ASSERT(args.length() == 1);
3060   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
3061   int continuation = generator->continuation();
3062   const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3063       "generator_finished" : "generator_running";
3064   Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3065   Handle<Object> error = isolate->factory()->NewError(message, argv);
3066   return isolate->Throw(*error);
3067 }
3068
3069
3070 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
3071   SealHandleScope shs(isolate);
3072   ASSERT(args.length() == 1);
3073   CONVERT_ARG_CHECKED(JSObject, object, 0);
3074   return object->Freeze(isolate);
3075 }
3076
3077
3078 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
3079                                                  Object* char_code) {
3080   if (char_code->IsNumber()) {
3081     return isolate->heap()->LookupSingleCharacterStringFromCode(
3082         NumberToUint32(char_code) & 0xffff);
3083   }
3084   return isolate->heap()->empty_string();
3085 }
3086
3087
3088 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
3089   SealHandleScope shs(isolate);
3090   ASSERT(args.length() == 2);
3091
3092   CONVERT_ARG_CHECKED(String, subject, 0);
3093   CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3094
3095   // Flatten the string.  If someone wants to get a char at an index
3096   // in a cons string, it is likely that more indices will be
3097   // accessed.
3098   Object* flat;
3099   { MaybeObject* maybe_flat = subject->TryFlatten();
3100     if (!maybe_flat->ToObject(&flat)) return maybe_flat;
3101   }
3102   subject = String::cast(flat);
3103
3104   if (i >= static_cast<uint32_t>(subject->length())) {
3105     return isolate->heap()->nan_value();
3106   }
3107
3108   return Smi::FromInt(subject->Get(i));
3109 }
3110
3111
3112 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
3113   SealHandleScope shs(isolate);
3114   ASSERT(args.length() == 1);
3115   return CharFromCode(isolate, args[0]);
3116 }
3117
3118
3119 class FixedArrayBuilder {
3120  public:
3121   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3122       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3123         length_(0),
3124         has_non_smi_elements_(false) {
3125     // Require a non-zero initial size. Ensures that doubling the size to
3126     // extend the array will work.
3127     ASSERT(initial_capacity > 0);
3128   }
3129
3130   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3131       : array_(backing_store),
3132         length_(0),
3133         has_non_smi_elements_(false) {
3134     // Require a non-zero initial size. Ensures that doubling the size to
3135     // extend the array will work.
3136     ASSERT(backing_store->length() > 0);
3137   }
3138
3139   bool HasCapacity(int elements) {
3140     int length = array_->length();
3141     int required_length = length_ + elements;
3142     return (length >= required_length);
3143   }
3144
3145   void EnsureCapacity(int elements) {
3146     int length = array_->length();
3147     int required_length = length_ + elements;
3148     if (length < required_length) {
3149       int new_length = length;
3150       do {
3151         new_length *= 2;
3152       } while (new_length < required_length);
3153       Handle<FixedArray> extended_array =
3154           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3155       array_->CopyTo(0, *extended_array, 0, length_);
3156       array_ = extended_array;
3157     }
3158   }
3159
3160   void Add(Object* value) {
3161     ASSERT(!value->IsSmi());
3162     ASSERT(length_ < capacity());
3163     array_->set(length_, value);
3164     length_++;
3165     has_non_smi_elements_ = true;
3166   }
3167
3168   void Add(Smi* value) {
3169     ASSERT(value->IsSmi());
3170     ASSERT(length_ < capacity());
3171     array_->set(length_, value);
3172     length_++;
3173   }
3174
3175   Handle<FixedArray> array() {
3176     return array_;
3177   }
3178
3179   int length() {
3180     return length_;
3181   }
3182
3183   int capacity() {
3184     return array_->length();
3185   }
3186
3187   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
3188     Factory* factory = target_array->GetIsolate()->factory();
3189     factory->SetContent(target_array, array_);
3190     target_array->set_length(Smi::FromInt(length_));
3191     return target_array;
3192   }
3193
3194
3195  private:
3196   Handle<FixedArray> array_;
3197   int length_;
3198   bool has_non_smi_elements_;
3199 };
3200
3201
3202 // Forward declarations.
3203 const int kStringBuilderConcatHelperLengthBits = 11;
3204 const int kStringBuilderConcatHelperPositionBits = 19;
3205
3206 template <typename schar>
3207 static inline void StringBuilderConcatHelper(String*,
3208                                              schar*,
3209                                              FixedArray*,
3210                                              int);
3211
3212 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
3213     StringBuilderSubstringLength;
3214 typedef BitField<int,
3215                  kStringBuilderConcatHelperLengthBits,
3216                  kStringBuilderConcatHelperPositionBits>
3217     StringBuilderSubstringPosition;
3218
3219
3220 class ReplacementStringBuilder {
3221  public:
3222   ReplacementStringBuilder(Heap* heap,
3223                            Handle<String> subject,
3224                            int estimated_part_count)
3225       : heap_(heap),
3226         array_builder_(heap->isolate(), estimated_part_count),
3227         subject_(subject),
3228         character_count_(0),
3229         is_ascii_(subject->IsOneByteRepresentation()) {
3230     // Require a non-zero initial size. Ensures that doubling the size to
3231     // extend the array will work.
3232     ASSERT(estimated_part_count > 0);
3233   }
3234
3235   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3236                                      int from,
3237                                      int to) {
3238     ASSERT(from >= 0);
3239     int length = to - from;
3240     ASSERT(length > 0);
3241     if (StringBuilderSubstringLength::is_valid(length) &&
3242         StringBuilderSubstringPosition::is_valid(from)) {
3243       int encoded_slice = StringBuilderSubstringLength::encode(length) |
3244           StringBuilderSubstringPosition::encode(from);
3245       builder->Add(Smi::FromInt(encoded_slice));
3246     } else {
3247       // Otherwise encode as two smis.
3248       builder->Add(Smi::FromInt(-length));
3249       builder->Add(Smi::FromInt(from));
3250     }
3251   }
3252
3253
3254   void EnsureCapacity(int elements) {
3255     array_builder_.EnsureCapacity(elements);
3256   }
3257
3258
3259   void AddSubjectSlice(int from, int to) {
3260     AddSubjectSlice(&array_builder_, from, to);
3261     IncrementCharacterCount(to - from);
3262   }
3263
3264
3265   void AddString(Handle<String> string) {
3266     int length = string->length();
3267     ASSERT(length > 0);
3268     AddElement(*string);
3269     if (!string->IsOneByteRepresentation()) {
3270       is_ascii_ = false;
3271     }
3272     IncrementCharacterCount(length);
3273   }
3274
3275
3276   Handle<String> ToString() {
3277     if (array_builder_.length() == 0) {
3278       return heap_->isolate()->factory()->empty_string();
3279     }
3280
3281     Handle<String> joined_string;
3282     if (is_ascii_) {
3283       Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3284       DisallowHeapAllocation no_gc;
3285       uint8_t* char_buffer = seq->GetChars();
3286       StringBuilderConcatHelper(*subject_,
3287                                 char_buffer,
3288                                 *array_builder_.array(),
3289                                 array_builder_.length());
3290       joined_string = Handle<String>::cast(seq);
3291     } else {
3292       // Non-ASCII.
3293       Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3294       DisallowHeapAllocation no_gc;
3295       uc16* char_buffer = seq->GetChars();
3296       StringBuilderConcatHelper(*subject_,
3297                                 char_buffer,
3298                                 *array_builder_.array(),
3299                                 array_builder_.length());
3300       joined_string = Handle<String>::cast(seq);
3301     }
3302     return joined_string;
3303   }
3304
3305
3306   void IncrementCharacterCount(int by) {
3307     if (character_count_ > String::kMaxLength - by) {
3308       V8::FatalProcessOutOfMemory("String.replace result too large.");
3309     }
3310     character_count_ += by;
3311   }
3312
3313  private:
3314   Handle<SeqOneByteString> NewRawOneByteString(int length) {
3315     return heap_->isolate()->factory()->NewRawOneByteString(length);
3316   }
3317
3318
3319   Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3320     return heap_->isolate()->factory()->NewRawTwoByteString(length);
3321   }
3322
3323
3324   void AddElement(Object* element) {
3325     ASSERT(element->IsSmi() || element->IsString());
3326     ASSERT(array_builder_.capacity() > array_builder_.length());
3327     array_builder_.Add(element);
3328   }
3329
3330   Heap* heap_;
3331   FixedArrayBuilder array_builder_;
3332   Handle<String> subject_;
3333   int character_count_;
3334   bool is_ascii_;
3335 };
3336
3337
3338 class CompiledReplacement {
3339  public:
3340   explicit CompiledReplacement(Zone* zone)
3341       : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3342
3343   // Return whether the replacement is simple.
3344   bool Compile(Handle<String> replacement,
3345                int capture_count,
3346                int subject_length);
3347
3348   // Use Apply only if Compile returned false.
3349   void Apply(ReplacementStringBuilder* builder,
3350              int match_from,
3351              int match_to,
3352              int32_t* match);
3353
3354   // Number of distinct parts of the replacement pattern.
3355   int parts() {
3356     return parts_.length();
3357   }
3358
3359   Zone* zone() const { return zone_; }
3360
3361  private:
3362   enum PartType {
3363     SUBJECT_PREFIX = 1,
3364     SUBJECT_SUFFIX,
3365     SUBJECT_CAPTURE,
3366     REPLACEMENT_SUBSTRING,
3367     REPLACEMENT_STRING,
3368
3369     NUMBER_OF_PART_TYPES
3370   };
3371
3372   struct ReplacementPart {
3373     static inline ReplacementPart SubjectMatch() {
3374       return ReplacementPart(SUBJECT_CAPTURE, 0);
3375     }
3376     static inline ReplacementPart SubjectCapture(int capture_index) {
3377       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3378     }
3379     static inline ReplacementPart SubjectPrefix() {
3380       return ReplacementPart(SUBJECT_PREFIX, 0);
3381     }
3382     static inline ReplacementPart SubjectSuffix(int subject_length) {
3383       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3384     }
3385     static inline ReplacementPart ReplacementString() {
3386       return ReplacementPart(REPLACEMENT_STRING, 0);
3387     }
3388     static inline ReplacementPart ReplacementSubString(int from, int to) {
3389       ASSERT(from >= 0);
3390       ASSERT(to > from);
3391       return ReplacementPart(-from, to);
3392     }
3393
3394     // If tag <= 0 then it is the negation of a start index of a substring of
3395     // the replacement pattern, otherwise it's a value from PartType.
3396     ReplacementPart(int tag, int data)
3397         : tag(tag), data(data) {
3398       // Must be non-positive or a PartType value.
3399       ASSERT(tag < NUMBER_OF_PART_TYPES);
3400     }
3401     // Either a value of PartType or a non-positive number that is
3402     // the negation of an index into the replacement string.
3403     int tag;
3404     // The data value's interpretation depends on the value of tag:
3405     // tag == SUBJECT_PREFIX ||
3406     // tag == SUBJECT_SUFFIX:  data is unused.
3407     // tag == SUBJECT_CAPTURE: data is the number of the capture.
3408     // tag == REPLACEMENT_SUBSTRING ||
3409     // tag == REPLACEMENT_STRING:    data is index into array of substrings
3410     //                               of the replacement string.
3411     // tag <= 0: Temporary representation of the substring of the replacement
3412     //           string ranging over -tag .. data.
3413     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3414     //           substring objects.
3415     int data;
3416   };
3417
3418   template<typename Char>
3419   bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3420                                Vector<Char> characters,
3421                                int capture_count,
3422                                int subject_length,
3423                                Zone* zone) {
3424     int length = characters.length();
3425     int last = 0;
3426     for (int i = 0; i < length; i++) {
3427       Char c = characters[i];
3428       if (c == '$') {
3429         int next_index = i + 1;
3430         if (next_index == length) {  // No next character!
3431           break;
3432         }
3433         Char c2 = characters[next_index];
3434         switch (c2) {
3435         case '$':
3436           if (i > last) {
3437             // There is a substring before. Include the first "$".
3438             parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3439                        zone);
3440             last = next_index + 1;  // Continue after the second "$".
3441           } else {
3442             // Let the next substring start with the second "$".
3443             last = next_index;
3444           }
3445           i = next_index;
3446           break;
3447         case '`':
3448           if (i > last) {
3449             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3450           }
3451           parts->Add(ReplacementPart::SubjectPrefix(), zone);
3452           i = next_index;
3453           last = i + 1;
3454           break;
3455         case '\'':
3456           if (i > last) {
3457             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3458           }
3459           parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3460           i = next_index;
3461           last = i + 1;
3462           break;
3463         case '&':
3464           if (i > last) {
3465             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3466           }
3467           parts->Add(ReplacementPart::SubjectMatch(), zone);
3468           i = next_index;
3469           last = i + 1;
3470           break;
3471         case '0':
3472         case '1':
3473         case '2':
3474         case '3':
3475         case '4':
3476         case '5':
3477         case '6':
3478         case '7':
3479         case '8':
3480         case '9': {
3481           int capture_ref = c2 - '0';
3482           if (capture_ref > capture_count) {
3483             i = next_index;
3484             continue;
3485           }
3486           int second_digit_index = next_index + 1;
3487           if (second_digit_index < length) {
3488             // Peek ahead to see if we have two digits.
3489             Char c3 = characters[second_digit_index];
3490             if ('0' <= c3 && c3 <= '9') {  // Double digits.
3491               int double_digit_ref = capture_ref * 10 + c3 - '0';
3492               if (double_digit_ref <= capture_count) {
3493                 next_index = second_digit_index;
3494                 capture_ref = double_digit_ref;
3495               }
3496             }
3497           }
3498           if (capture_ref > 0) {
3499             if (i > last) {
3500               parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3501             }
3502             ASSERT(capture_ref <= capture_count);
3503             parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3504             last = next_index + 1;
3505           }
3506           i = next_index;
3507           break;
3508         }
3509         default:
3510           i = next_index;
3511           break;
3512         }
3513       }
3514     }
3515     if (length > last) {
3516       if (last == 0) {
3517         // Replacement is simple.  Do not use Apply to do the replacement.
3518         return true;
3519       } else {
3520         parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3521       }
3522     }
3523     return false;
3524   }
3525
3526   ZoneList<ReplacementPart> parts_;
3527   ZoneList<Handle<String> > replacement_substrings_;
3528   Zone* zone_;
3529 };
3530
3531
3532 bool CompiledReplacement::Compile(Handle<String> replacement,
3533                                   int capture_count,
3534                                   int subject_length) {
3535   {
3536     DisallowHeapAllocation no_gc;
3537     String::FlatContent content = replacement->GetFlatContent();
3538     ASSERT(content.IsFlat());
3539     bool simple = false;
3540     if (content.IsAscii()) {
3541       simple = ParseReplacementPattern(&parts_,
3542                                        content.ToOneByteVector(),
3543                                        capture_count,
3544                                        subject_length,
3545                                        zone());
3546     } else {
3547       ASSERT(content.IsTwoByte());
3548       simple = ParseReplacementPattern(&parts_,
3549                                        content.ToUC16Vector(),
3550                                        capture_count,
3551                                        subject_length,
3552                                        zone());
3553     }
3554     if (simple) return true;
3555   }
3556
3557   Isolate* isolate = replacement->GetIsolate();
3558   // Find substrings of replacement string and create them as String objects.
3559   int substring_index = 0;
3560   for (int i = 0, n = parts_.length(); i < n; i++) {
3561     int tag = parts_[i].tag;
3562     if (tag <= 0) {  // A replacement string slice.
3563       int from = -tag;
3564       int to = parts_[i].data;
3565       replacement_substrings_.Add(
3566           isolate->factory()->NewSubString(replacement, from, to), zone());
3567       parts_[i].tag = REPLACEMENT_SUBSTRING;
3568       parts_[i].data = substring_index;
3569       substring_index++;
3570     } else if (tag == REPLACEMENT_STRING) {
3571       replacement_substrings_.Add(replacement, zone());
3572       parts_[i].data = substring_index;
3573       substring_index++;
3574     }
3575   }
3576   return false;
3577 }
3578
3579
3580 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
3581                                 int match_from,
3582                                 int match_to,
3583                                 int32_t* match) {
3584   ASSERT_LT(0, parts_.length());
3585   for (int i = 0, n = parts_.length(); i < n; i++) {
3586     ReplacementPart part = parts_[i];
3587     switch (part.tag) {
3588       case SUBJECT_PREFIX:
3589         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3590         break;
3591       case SUBJECT_SUFFIX: {
3592         int subject_length = part.data;
3593         if (match_to < subject_length) {
3594           builder->AddSubjectSlice(match_to, subject_length);
3595         }
3596         break;
3597       }
3598       case SUBJECT_CAPTURE: {
3599         int capture = part.data;
3600         int from = match[capture * 2];
3601         int to = match[capture * 2 + 1];
3602         if (from >= 0 && to > from) {
3603           builder->AddSubjectSlice(from, to);
3604         }
3605         break;
3606       }
3607       case REPLACEMENT_SUBSTRING:
3608       case REPLACEMENT_STRING:
3609         builder->AddString(replacement_substrings_[part.data]);
3610         break;
3611       default:
3612         UNREACHABLE();
3613     }
3614   }
3615 }
3616
3617
3618 void FindAsciiStringIndices(Vector<const uint8_t> subject,
3619                             char pattern,
3620                             ZoneList<int>* indices,
3621                             unsigned int limit,
3622                             Zone* zone) {
3623   ASSERT(limit > 0);
3624   // Collect indices of pattern in subject using memchr.
3625   // Stop after finding at most limit values.
3626   const uint8_t* subject_start = subject.start();
3627   const uint8_t* subject_end = subject_start + subject.length();
3628   const uint8_t* pos = subject_start;
3629   while (limit > 0) {
3630     pos = reinterpret_cast<const uint8_t*>(
3631         memchr(pos, pattern, subject_end - pos));
3632     if (pos == NULL) return;
3633     indices->Add(static_cast<int>(pos - subject_start), zone);
3634     pos++;
3635     limit--;
3636   }
3637 }
3638
3639
3640 void FindTwoByteStringIndices(const Vector<const uc16> subject,
3641                               uc16 pattern,
3642                               ZoneList<int>* indices,
3643                               unsigned int limit,
3644                               Zone* zone) {
3645   ASSERT(limit > 0);
3646   const uc16* subject_start = subject.start();
3647   const uc16* subject_end = subject_start + subject.length();
3648   for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3649     if (*pos == pattern) {
3650       indices->Add(static_cast<int>(pos - subject_start), zone);
3651       limit--;
3652     }
3653   }
3654 }
3655
3656
3657 template <typename SubjectChar, typename PatternChar>
3658 void FindStringIndices(Isolate* isolate,
3659                        Vector<const SubjectChar> subject,
3660                        Vector<const PatternChar> pattern,
3661                        ZoneList<int>* indices,
3662                        unsigned int limit,
3663                        Zone* zone) {
3664   ASSERT(limit > 0);
3665   // Collect indices of pattern in subject.
3666   // Stop after finding at most limit values.
3667   int pattern_length = pattern.length();
3668   int index = 0;
3669   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3670   while (limit > 0) {
3671     index = search.Search(subject, index);
3672     if (index < 0) return;
3673     indices->Add(index, zone);
3674     index += pattern_length;
3675     limit--;
3676   }
3677 }
3678
3679
3680 void FindStringIndicesDispatch(Isolate* isolate,
3681                                String* subject,
3682                                String* pattern,
3683                                ZoneList<int>* indices,
3684                                unsigned int limit,
3685                                Zone* zone) {
3686   {
3687     DisallowHeapAllocation no_gc;
3688     String::FlatContent subject_content = subject->GetFlatContent();
3689     String::FlatContent pattern_content = pattern->GetFlatContent();
3690     ASSERT(subject_content.IsFlat());
3691     ASSERT(pattern_content.IsFlat());
3692     if (subject_content.IsAscii()) {
3693       Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3694       if (pattern_content.IsAscii()) {
3695         Vector<const uint8_t> pattern_vector =
3696             pattern_content.ToOneByteVector();
3697         if (pattern_vector.length() == 1) {
3698           FindAsciiStringIndices(subject_vector,
3699                                  pattern_vector[0],
3700                                  indices,
3701                                  limit,
3702                                  zone);
3703         } else {
3704           FindStringIndices(isolate,
3705                             subject_vector,
3706                             pattern_vector,
3707                             indices,
3708                             limit,
3709                             zone);
3710         }
3711       } else {
3712         FindStringIndices(isolate,
3713                           subject_vector,
3714                           pattern_content.ToUC16Vector(),
3715                           indices,
3716                           limit,
3717                           zone);
3718       }
3719     } else {
3720       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3721       if (pattern_content.IsAscii()) {
3722         Vector<const uint8_t> pattern_vector =
3723             pattern_content.ToOneByteVector();
3724         if (pattern_vector.length() == 1) {
3725           FindTwoByteStringIndices(subject_vector,
3726                                    pattern_vector[0],
3727                                    indices,
3728                                    limit,
3729                                    zone);
3730         } else {
3731           FindStringIndices(isolate,
3732                             subject_vector,
3733                             pattern_vector,
3734                             indices,
3735                             limit,
3736                             zone);
3737         }
3738       } else {
3739         Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3740         if (pattern_vector.length() == 1) {
3741           FindTwoByteStringIndices(subject_vector,
3742                                    pattern_vector[0],
3743                                    indices,
3744                                    limit,
3745                                    zone);
3746         } else {
3747           FindStringIndices(isolate,
3748                             subject_vector,
3749                             pattern_vector,
3750                             indices,
3751                             limit,
3752                             zone);
3753         }
3754       }
3755     }
3756   }
3757 }
3758
3759
3760 template<typename ResultSeqString>
3761 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
3762     Isolate* isolate,
3763     Handle<String> subject,
3764     Handle<JSRegExp> pattern_regexp,
3765     Handle<String> replacement,
3766     Handle<JSArray> last_match_info) {
3767   ASSERT(subject->IsFlat());
3768   ASSERT(replacement->IsFlat());
3769
3770   ZoneScope zone_scope(isolate->runtime_zone());
3771   ZoneList<int> indices(8, zone_scope.zone());
3772   ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3773   String* pattern =
3774       String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
3775   int subject_len = subject->length();
3776   int pattern_len = pattern->length();
3777   int replacement_len = replacement->length();
3778
3779   FindStringIndicesDispatch(
3780       isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3781
3782   int matches = indices.length();
3783   if (matches == 0) return *subject;
3784
3785   // Detect integer overflow.
3786   int64_t result_len_64 =
3787       (static_cast<int64_t>(replacement_len) -
3788        static_cast<int64_t>(pattern_len)) *
3789       static_cast<int64_t>(matches) +
3790       static_cast<int64_t>(subject_len);
3791   if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11);
3792   int result_len = static_cast<int>(result_len_64);
3793
3794   int subject_pos = 0;
3795   int result_pos = 0;
3796
3797   Handle<ResultSeqString> result;
3798   if (ResultSeqString::kHasAsciiEncoding) {
3799     result = Handle<ResultSeqString>::cast(
3800         isolate->factory()->NewRawOneByteString(result_len));
3801   } else {
3802     result = Handle<ResultSeqString>::cast(
3803         isolate->factory()->NewRawTwoByteString(result_len));
3804   }
3805
3806   for (int i = 0; i < matches; i++) {
3807     // Copy non-matched subject content.
3808     if (subject_pos < indices.at(i)) {
3809       String::WriteToFlat(*subject,
3810                           result->GetChars() + result_pos,
3811                           subject_pos,
3812                           indices.at(i));
3813       result_pos += indices.at(i) - subject_pos;
3814     }
3815
3816     // Replace match.
3817     if (replacement_len > 0) {
3818       String::WriteToFlat(*replacement,
3819                           result->GetChars() + result_pos,
3820                           0,
3821                           replacement_len);
3822       result_pos += replacement_len;
3823     }
3824
3825     subject_pos = indices.at(i) + pattern_len;
3826   }
3827   // Add remaining subject content at the end.
3828   if (subject_pos < subject_len) {
3829     String::WriteToFlat(*subject,
3830                         result->GetChars() + result_pos,
3831                         subject_pos,
3832                         subject_len);
3833   }
3834
3835   int32_t match_indices[] = { indices.at(matches - 1),
3836                               indices.at(matches - 1) + pattern_len };
3837   RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
3838
3839   return *result;
3840 }
3841
3842
3843 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
3844     Isolate* isolate,
3845     Handle<String> subject,
3846     Handle<JSRegExp> regexp,
3847     Handle<String> replacement,
3848     Handle<JSArray> last_match_info) {
3849   ASSERT(subject->IsFlat());
3850   ASSERT(replacement->IsFlat());
3851
3852   int capture_count = regexp->CaptureCount();
3853   int subject_length = subject->length();
3854
3855   // CompiledReplacement uses zone allocation.
3856   ZoneScope zone_scope(isolate->runtime_zone());
3857   CompiledReplacement compiled_replacement(zone_scope.zone());
3858   bool simple_replace = compiled_replacement.Compile(replacement,
3859                                                      capture_count,
3860                                                      subject_length);
3861
3862   // Shortcut for simple non-regexp global replacements
3863   if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
3864     if (subject->HasOnlyOneByteChars() &&
3865         replacement->HasOnlyOneByteChars()) {
3866       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
3867           isolate, subject, regexp, replacement, last_match_info);
3868     } else {
3869       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
3870           isolate, subject, regexp, replacement, last_match_info);
3871     }
3872   }
3873
3874   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3875   if (global_cache.HasException()) return Failure::Exception();
3876
3877   int32_t* current_match = global_cache.FetchNext();
3878   if (current_match == NULL) {
3879     if (global_cache.HasException()) return Failure::Exception();
3880     return *subject;
3881   }
3882
3883   // Guessing the number of parts that the final result string is built
3884   // from. Global regexps can match any number of times, so we guess
3885   // conservatively.
3886   int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
3887   ReplacementStringBuilder builder(isolate->heap(),
3888                                    subject,
3889                                    expected_parts);
3890
3891   // Number of parts added by compiled replacement plus preceeding
3892   // string and possibly suffix after last match.  It is possible for
3893   // all components to use two elements when encoded as two smis.
3894   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3895
3896   int prev = 0;
3897
3898   do {
3899     builder.EnsureCapacity(parts_added_per_loop);
3900
3901     int start = current_match[0];
3902     int end = current_match[1];
3903
3904     if (prev < start) {
3905       builder.AddSubjectSlice(prev, start);
3906     }
3907
3908     if (simple_replace) {
3909       builder.AddString(replacement);
3910     } else {
3911       compiled_replacement.Apply(&builder,
3912                                  start,
3913                                  end,
3914                                  current_match);
3915     }
3916     prev = end;
3917
3918     current_match = global_cache.FetchNext();
3919   } while (current_match != NULL);
3920
3921   if (global_cache.HasException()) return Failure::Exception();
3922
3923   if (prev < subject_length) {
3924     builder.EnsureCapacity(2);
3925     builder.AddSubjectSlice(prev, subject_length);
3926   }
3927
3928   RegExpImpl::SetLastMatchInfo(last_match_info,
3929                                subject,
3930                                capture_count,
3931                                global_cache.LastSuccessfulMatch());
3932
3933   return *(builder.ToString());
3934 }
3935
3936
3937 template <typename ResultSeqString>
3938 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
3939     Isolate* isolate,
3940     Handle<String> subject,
3941     Handle<JSRegExp> regexp,
3942     Handle<JSArray> last_match_info) {
3943   ASSERT(subject->IsFlat());
3944
3945   // Shortcut for simple non-regexp global replacements
3946   if (regexp->TypeTag() == JSRegExp::ATOM) {
3947     Handle<String> empty_string = isolate->factory()->empty_string();
3948     if (subject->IsOneByteRepresentation()) {
3949       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
3950           isolate, subject, regexp, empty_string, last_match_info);
3951     } else {
3952       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
3953           isolate, subject, regexp, empty_string, last_match_info);
3954     }
3955   }
3956
3957   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3958   if (global_cache.HasException()) return Failure::Exception();
3959
3960   int32_t* current_match = global_cache.FetchNext();
3961   if (current_match == NULL) {
3962     if (global_cache.HasException()) return Failure::Exception();
3963     return *subject;
3964   }
3965
3966   int start = current_match[0];
3967   int end = current_match[1];
3968   int capture_count = regexp->CaptureCount();
3969   int subject_length = subject->length();
3970
3971   int new_length = subject_length - (end - start);
3972   if (new_length == 0) return isolate->heap()->empty_string();
3973
3974   Handle<ResultSeqString> answer;
3975   if (ResultSeqString::kHasAsciiEncoding) {
3976     answer = Handle<ResultSeqString>::cast(
3977         isolate->factory()->NewRawOneByteString(new_length));
3978   } else {
3979     answer = Handle<ResultSeqString>::cast(
3980         isolate->factory()->NewRawTwoByteString(new_length));
3981   }
3982
3983   int prev = 0;
3984   int position = 0;
3985
3986   do {
3987     start = current_match[0];
3988     end = current_match[1];
3989     if (prev < start) {
3990       // Add substring subject[prev;start] to answer string.
3991       String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
3992       position += start - prev;
3993     }
3994     prev = end;
3995
3996     current_match = global_cache.FetchNext();
3997   } while (current_match != NULL);
3998
3999   if (global_cache.HasException()) return Failure::Exception();
4000
4001   RegExpImpl::SetLastMatchInfo(last_match_info,
4002                                subject,
4003                                capture_count,
4004                                global_cache.LastSuccessfulMatch());
4005
4006   if (prev < subject_length) {
4007     // Add substring subject[prev;length] to answer string.
4008     String::WriteToFlat(
4009         *subject, answer->GetChars() + position, prev, subject_length);
4010     position += subject_length - prev;
4011   }
4012
4013   if (position == 0) return isolate->heap()->empty_string();
4014
4015   // Shorten string and fill
4016   int string_size = ResultSeqString::SizeFor(position);
4017   int allocated_string_size = ResultSeqString::SizeFor(new_length);
4018   int delta = allocated_string_size - string_size;
4019
4020   answer->set_length(position);
4021   if (delta == 0) return *answer;
4022
4023   Address end_of_string = answer->address() + string_size;
4024   isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
4025   if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
4026     MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
4027   }
4028
4029   return *answer;
4030 }
4031
4032
4033 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
4034   HandleScope scope(isolate);
4035   ASSERT(args.length() == 4);
4036
4037   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4038   CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4039   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4040   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4041
4042   ASSERT(regexp->GetFlags().is_global());
4043
4044   if (!subject->IsFlat()) subject = FlattenGetString(subject);
4045
4046   if (replacement->length() == 0) {
4047     if (subject->HasOnlyOneByteChars()) {
4048       return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4049           isolate, subject, regexp, last_match_info);
4050     } else {
4051       return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4052           isolate, subject, regexp, last_match_info);
4053     }
4054   }
4055
4056   if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
4057
4058   return StringReplaceGlobalRegExpWithString(
4059       isolate, subject, regexp, replacement, last_match_info);
4060 }
4061
4062
4063 Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
4064                                               Handle<String> subject,
4065                                               Handle<String> search,
4066                                               Handle<String> replace,
4067                                               bool* found,
4068                                               int recursion_limit) {
4069   if (recursion_limit == 0) return Handle<String>::null();
4070   if (subject->IsConsString()) {
4071     ConsString* cons = ConsString::cast(*subject);
4072     Handle<String> first = Handle<String>(cons->first());
4073     Handle<String> second = Handle<String>(cons->second());
4074     Handle<String> new_first =
4075         StringReplaceOneCharWithString(isolate,
4076                                        first,
4077                                        search,
4078                                        replace,
4079                                        found,
4080                                        recursion_limit - 1);
4081     if (*found) return isolate->factory()->NewConsString(new_first, second);
4082     if (new_first.is_null()) return new_first;
4083
4084     Handle<String> new_second =
4085         StringReplaceOneCharWithString(isolate,
4086                                        second,
4087                                        search,
4088                                        replace,
4089                                        found,
4090                                        recursion_limit - 1);
4091     if (*found) return isolate->factory()->NewConsString(first, new_second);
4092     if (new_second.is_null()) return new_second;
4093
4094     return subject;
4095   } else {
4096     int index = Runtime::StringMatch(isolate, subject, search, 0);
4097     if (index == -1) return subject;
4098     *found = true;
4099     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4100     Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
4101     Handle<String> second =
4102         isolate->factory()->NewSubString(subject, index + 1, subject->length());
4103     return isolate->factory()->NewConsString(cons1, second);
4104   }
4105 }
4106
4107
4108 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
4109   HandleScope scope(isolate);
4110   ASSERT(args.length() == 3);
4111   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4112   CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4113   CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4114
4115   // If the cons string tree is too deep, we simply abort the recursion and
4116   // retry with a flattened subject string.
4117   const int kRecursionLimit = 0x1000;
4118   bool found = false;
4119   Handle<String> result = StringReplaceOneCharWithString(isolate,
4120                                                          subject,
4121                                                          search,
4122                                                          replace,
4123                                                          &found,
4124                                                          kRecursionLimit);
4125   if (!result.is_null()) return *result;
4126   return *StringReplaceOneCharWithString(isolate,
4127                                          FlattenGetString(subject),
4128                                          search,
4129                                          replace,
4130                                          &found,
4131                                          kRecursionLimit);
4132 }
4133
4134
4135 // Perform string match of pattern on subject, starting at start index.
4136 // Caller must ensure that 0 <= start_index <= sub->length(),
4137 // and should check that pat->length() + start_index <= sub->length().
4138 int Runtime::StringMatch(Isolate* isolate,
4139                          Handle<String> sub,
4140                          Handle<String> pat,
4141                          int start_index) {
4142   ASSERT(0 <= start_index);
4143   ASSERT(start_index <= sub->length());
4144
4145   int pattern_length = pat->length();
4146   if (pattern_length == 0) return start_index;
4147
4148   int subject_length = sub->length();
4149   if (start_index + pattern_length > subject_length) return -1;
4150
4151   if (!sub->IsFlat()) FlattenString(sub);
4152   if (!pat->IsFlat()) FlattenString(pat);
4153
4154   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4155   // Extract flattened substrings of cons strings before determining asciiness.
4156   String::FlatContent seq_sub = sub->GetFlatContent();
4157   String::FlatContent seq_pat = pat->GetFlatContent();
4158
4159   // dispatch on type of strings
4160   if (seq_pat.IsAscii()) {
4161     Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4162     if (seq_sub.IsAscii()) {
4163       return SearchString(isolate,
4164                           seq_sub.ToOneByteVector(),
4165                           pat_vector,
4166                           start_index);
4167     }
4168     return SearchString(isolate,
4169                         seq_sub.ToUC16Vector(),
4170                         pat_vector,
4171                         start_index);
4172   }
4173   Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4174   if (seq_sub.IsAscii()) {
4175     return SearchString(isolate,
4176                         seq_sub.ToOneByteVector(),
4177                         pat_vector,
4178                         start_index);
4179   }
4180   return SearchString(isolate,
4181                       seq_sub.ToUC16Vector(),
4182                       pat_vector,
4183                       start_index);
4184 }
4185
4186
4187 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
4188   HandleScope scope(isolate);
4189   ASSERT(args.length() == 3);
4190
4191   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4192   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4193
4194   Object* index = args[2];
4195   uint32_t start_index;
4196   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4197
4198   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4199   int position =
4200       Runtime::StringMatch(isolate, sub, pat, start_index);
4201   return Smi::FromInt(position);
4202 }
4203
4204
4205 template <typename schar, typename pchar>
4206 static int StringMatchBackwards(Vector<const schar> subject,
4207                                 Vector<const pchar> pattern,
4208                                 int idx) {
4209   int pattern_length = pattern.length();
4210   ASSERT(pattern_length >= 1);
4211   ASSERT(idx + pattern_length <= subject.length());
4212
4213   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4214     for (int i = 0; i < pattern_length; i++) {
4215       uc16 c = pattern[i];
4216       if (c > String::kMaxOneByteCharCode) {
4217         return -1;
4218       }
4219     }
4220   }
4221
4222   pchar pattern_first_char = pattern[0];
4223   for (int i = idx; i >= 0; i--) {
4224     if (subject[i] != pattern_first_char) continue;
4225     int j = 1;
4226     while (j < pattern_length) {
4227       if (pattern[j] != subject[i+j]) {
4228         break;
4229       }
4230       j++;
4231     }
4232     if (j == pattern_length) {
4233       return i;
4234     }
4235   }
4236   return -1;
4237 }
4238
4239
4240 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
4241   HandleScope scope(isolate);
4242   ASSERT(args.length() == 3);
4243
4244   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4245   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4246
4247   Object* index = args[2];
4248   uint32_t start_index;
4249   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4250
4251   uint32_t pat_length = pat->length();
4252   uint32_t sub_length = sub->length();
4253
4254   if (start_index + pat_length > sub_length) {
4255     start_index = sub_length - pat_length;
4256   }
4257
4258   if (pat_length == 0) {
4259     return Smi::FromInt(start_index);
4260   }
4261
4262   if (!sub->IsFlat()) FlattenString(sub);
4263   if (!pat->IsFlat()) FlattenString(pat);
4264
4265   int position = -1;
4266   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4267
4268   String::FlatContent sub_content = sub->GetFlatContent();
4269   String::FlatContent pat_content = pat->GetFlatContent();
4270
4271   if (pat_content.IsAscii()) {
4272     Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4273     if (sub_content.IsAscii()) {
4274       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4275                                       pat_vector,
4276                                       start_index);
4277     } else {
4278       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4279                                       pat_vector,
4280                                       start_index);
4281     }
4282   } else {
4283     Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4284     if (sub_content.IsAscii()) {
4285       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4286                                       pat_vector,
4287                                       start_index);
4288     } else {
4289       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4290                                       pat_vector,
4291                                       start_index);
4292     }
4293   }
4294
4295   return Smi::FromInt(position);
4296 }
4297
4298
4299 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
4300   SealHandleScope shs(isolate);
4301   ASSERT(args.length() == 2);
4302
4303   CONVERT_ARG_CHECKED(String, str1, 0);
4304   CONVERT_ARG_CHECKED(String, str2, 1);
4305
4306   if (str1 == str2) return Smi::FromInt(0);  // Equal.
4307   int str1_length = str1->length();
4308   int str2_length = str2->length();
4309
4310   // Decide trivial cases without flattening.
4311   if (str1_length == 0) {
4312     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
4313     return Smi::FromInt(-str2_length);
4314   } else {
4315     if (str2_length == 0) return Smi::FromInt(str1_length);
4316   }
4317
4318   int end = str1_length < str2_length ? str1_length : str2_length;
4319
4320   // No need to flatten if we are going to find the answer on the first
4321   // character.  At this point we know there is at least one character
4322   // in each string, due to the trivial case handling above.
4323   int d = str1->Get(0) - str2->Get(0);
4324   if (d != 0) return Smi::FromInt(d);
4325
4326   str1->TryFlatten();
4327   str2->TryFlatten();
4328
4329   ConsStringIteratorOp* op1 =
4330       isolate->runtime_state()->string_locale_compare_it1();
4331   ConsStringIteratorOp* op2 =
4332       isolate->runtime_state()->string_locale_compare_it2();
4333   // TODO(dcarney) Can do array compares here more efficiently.
4334   StringCharacterStream stream1(str1, op1);
4335   StringCharacterStream stream2(str2, op2);
4336
4337   for (int i = 0; i < end; i++) {
4338     uint16_t char1 = stream1.GetNext();
4339     uint16_t char2 = stream2.GetNext();
4340     if (char1 != char2) return Smi::FromInt(char1 - char2);
4341   }
4342
4343   return Smi::FromInt(str1_length - str2_length);
4344 }
4345
4346
4347 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
4348   SealHandleScope shs(isolate);
4349   ASSERT(args.length() == 3);
4350
4351   CONVERT_ARG_CHECKED(String, value, 0);
4352   int start, end;
4353   // We have a fast integer-only case here to avoid a conversion to double in
4354   // the common case where from and to are Smis.
4355   if (args[1]->IsSmi() && args[2]->IsSmi()) {
4356     CONVERT_SMI_ARG_CHECKED(from_number, 1);
4357     CONVERT_SMI_ARG_CHECKED(to_number, 2);
4358     start = from_number;
4359     end = to_number;
4360   } else {
4361     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4362     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4363     start = FastD2IChecked(from_number);
4364     end = FastD2IChecked(to_number);
4365   }
4366   RUNTIME_ASSERT(end >= start);
4367   RUNTIME_ASSERT(start >= 0);
4368   RUNTIME_ASSERT(end <= value->length());
4369   isolate->counters()->sub_string_runtime()->Increment();
4370   if (end - start == 1) {
4371      return isolate->heap()->LookupSingleCharacterStringFromCode(
4372          value->Get(start));
4373   }
4374   return value->SubString(start, end);
4375 }
4376
4377
4378 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
4379   HandleScope handles(isolate);
4380   ASSERT_EQ(3, args.length());
4381
4382   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4383   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4384   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4385
4386   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4387   if (global_cache.HasException()) return Failure::Exception();
4388
4389   int capture_count = regexp->CaptureCount();
4390
4391   ZoneScope zone_scope(isolate->runtime_zone());
4392   ZoneList<int> offsets(8, zone_scope.zone());
4393
4394   while (true) {
4395     int32_t* match = global_cache.FetchNext();
4396     if (match == NULL) break;
4397     offsets.Add(match[0], zone_scope.zone());  // start
4398     offsets.Add(match[1], zone_scope.zone());  // end
4399   }
4400
4401   if (global_cache.HasException()) return Failure::Exception();
4402
4403   if (offsets.length() == 0) {
4404     // Not a single match.
4405     return isolate->heap()->null_value();
4406   }
4407
4408   RegExpImpl::SetLastMatchInfo(regexp_info,
4409                                subject,
4410                                capture_count,
4411                                global_cache.LastSuccessfulMatch());
4412
4413   int matches = offsets.length() / 2;
4414   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4415   Handle<String> substring =
4416       isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4417   elements->set(0, *substring);
4418   for (int i = 1; i < matches; i++) {
4419     HandleScope temp_scope(isolate);
4420     int from = offsets.at(i * 2);
4421     int to = offsets.at(i * 2 + 1);
4422     Handle<String> substring =
4423         isolate->factory()->NewProperSubString(subject, from, to);
4424     elements->set(i, *substring);
4425   }
4426   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4427   result->set_length(Smi::FromInt(matches));
4428   return *result;
4429 }
4430
4431
4432 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4433 // separate last match info.  See comment on that function.
4434 template<bool has_capture>
4435 static MaybeObject* SearchRegExpMultiple(
4436     Isolate* isolate,
4437     Handle<String> subject,
4438     Handle<JSRegExp> regexp,
4439     Handle<JSArray> last_match_array,
4440     Handle<JSArray> result_array) {
4441   ASSERT(subject->IsFlat());
4442   ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
4443
4444   int capture_count = regexp->CaptureCount();
4445   int subject_length = subject->length();
4446
4447   static const int kMinLengthToCache = 0x1000;
4448
4449   if (subject_length > kMinLengthToCache) {
4450     Handle<Object> cached_answer(RegExpResultsCache::Lookup(
4451         isolate->heap(),
4452         *subject,
4453         regexp->data(),
4454         RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
4455     if (*cached_answer != Smi::FromInt(0)) {
4456       Handle<FixedArray> cached_fixed_array =
4457           Handle<FixedArray>(FixedArray::cast(*cached_answer));
4458       // The cache FixedArray is a COW-array and can therefore be reused.
4459       isolate->factory()->SetContent(result_array, cached_fixed_array);
4460       // The actual length of the result array is stored in the last element of
4461       // the backing store (the backing FixedArray may have a larger capacity).
4462       Object* cached_fixed_array_last_element =
4463           cached_fixed_array->get(cached_fixed_array->length() - 1);
4464       Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4465       result_array->set_length(js_array_length);
4466       RegExpImpl::SetLastMatchInfo(
4467           last_match_array, subject, capture_count, NULL);
4468       return *result_array;
4469     }
4470   }
4471
4472   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4473   if (global_cache.HasException()) return Failure::Exception();
4474
4475   Handle<FixedArray> result_elements;
4476   if (result_array->HasFastObjectElements()) {
4477     result_elements =
4478         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4479   }
4480   if (result_elements.is_null() || result_elements->length() < 16) {
4481     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4482   }
4483
4484   FixedArrayBuilder builder(result_elements);
4485
4486   // Position to search from.
4487   int match_start = -1;
4488   int match_end = 0;
4489   bool first = true;
4490
4491   // Two smis before and after the match, for very long strings.
4492   static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4493
4494   while (true) {
4495     int32_t* current_match = global_cache.FetchNext();
4496     if (current_match == NULL) break;
4497     match_start = current_match[0];
4498     builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4499     if (match_end < match_start) {
4500       ReplacementStringBuilder::AddSubjectSlice(&builder,
4501                                                 match_end,
4502                                                 match_start);
4503     }
4504     match_end = current_match[1];
4505     {
4506       // Avoid accumulating new handles inside loop.
4507       HandleScope temp_scope(isolate);
4508       Handle<String> match;
4509       if (!first) {
4510         match = isolate->factory()->NewProperSubString(subject,
4511                                                        match_start,
4512                                                        match_end);
4513       } else {
4514         match = isolate->factory()->NewSubString(subject,
4515                                                  match_start,
4516                                                  match_end);
4517         first = false;
4518       }
4519
4520       if (has_capture) {
4521         // Arguments array to replace function is match, captures, index and
4522         // subject, i.e., 3 + capture count in total.
4523         Handle<FixedArray> elements =
4524             isolate->factory()->NewFixedArray(3 + capture_count);
4525
4526         elements->set(0, *match);
4527         for (int i = 1; i <= capture_count; i++) {
4528           int start = current_match[i * 2];
4529           if (start >= 0) {
4530             int end = current_match[i * 2 + 1];
4531             ASSERT(start <= end);
4532             Handle<String> substring =
4533                 isolate->factory()->NewSubString(subject, start, end);
4534             elements->set(i, *substring);
4535           } else {
4536             ASSERT(current_match[i * 2 + 1] < 0);
4537             elements->set(i, isolate->heap()->undefined_value());
4538           }
4539         }
4540         elements->set(capture_count + 1, Smi::FromInt(match_start));
4541         elements->set(capture_count + 2, *subject);
4542         builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4543       } else {
4544         builder.Add(*match);
4545       }
4546     }
4547   }
4548
4549   if (global_cache.HasException()) return Failure::Exception();
4550
4551   if (match_start >= 0) {
4552     // Finished matching, with at least one match.
4553     if (match_end < subject_length) {
4554       ReplacementStringBuilder::AddSubjectSlice(&builder,
4555                                                 match_end,
4556                                                 subject_length);
4557     }
4558
4559     RegExpImpl::SetLastMatchInfo(
4560         last_match_array, subject, capture_count, NULL);
4561
4562     if (subject_length > kMinLengthToCache) {
4563       // Store the length of the result array into the last element of the
4564       // backing FixedArray.
4565       builder.EnsureCapacity(1);
4566       Handle<FixedArray> fixed_array = builder.array();
4567       fixed_array->set(fixed_array->length() - 1,
4568                        Smi::FromInt(builder.length()));
4569       // Cache the result and turn the FixedArray into a COW array.
4570       RegExpResultsCache::Enter(isolate->heap(),
4571                                 *subject,
4572                                 regexp->data(),
4573                                 *fixed_array,
4574                                 RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
4575     }
4576     return *builder.ToJSArray(result_array);
4577   } else {
4578     return isolate->heap()->null_value();  // No matches at all.
4579   }
4580 }
4581
4582
4583 // This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4584 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4585 // set any other last match array info.
4586 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4587   HandleScope handles(isolate);
4588   ASSERT(args.length() == 4);
4589
4590   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4591   if (!subject->IsFlat()) FlattenString(subject);
4592   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4593   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4594   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4595
4596   ASSERT(regexp->GetFlags().is_global());
4597
4598   if (regexp->CaptureCount() == 0) {
4599     return SearchRegExpMultiple<false>(
4600         isolate, subject, regexp, last_match_info, result_array);
4601   } else {
4602     return SearchRegExpMultiple<true>(
4603         isolate, subject, regexp, last_match_info, result_array);
4604   }
4605 }
4606
4607
4608 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4609   SealHandleScope shs(isolate);
4610   ASSERT(args.length() == 2);
4611   CONVERT_SMI_ARG_CHECKED(radix, 1);
4612   RUNTIME_ASSERT(2 <= radix && radix <= 36);
4613
4614   // Fast case where the result is a one character string.
4615   if (args[0]->IsSmi()) {
4616     int value = args.smi_at(0);
4617     if (value >= 0 && value < radix) {
4618       // Character array used for conversion.
4619       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4620       return isolate->heap()->
4621           LookupSingleCharacterStringFromCode(kCharTable[value]);
4622     }
4623   }
4624
4625   // Slow case.
4626   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4627   if (std::isnan(value)) {
4628     return *isolate->factory()->nan_string();
4629   }
4630   if (std::isinf(value)) {
4631     if (value < 0) {
4632       return *isolate->factory()->minus_infinity_string();
4633     }
4634     return *isolate->factory()->infinity_string();
4635   }
4636   char* str = DoubleToRadixCString(value, radix);
4637   MaybeObject* result =
4638       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4639   DeleteArray(str);
4640   return result;
4641 }
4642
4643
4644 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4645   SealHandleScope shs(isolate);
4646   ASSERT(args.length() == 2);
4647
4648   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4649   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4650   int f = FastD2IChecked(f_number);
4651   RUNTIME_ASSERT(f >= 0);
4652   char* str = DoubleToFixedCString(value, f);
4653   MaybeObject* res =
4654       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4655   DeleteArray(str);
4656   return res;
4657 }
4658
4659
4660 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4661   SealHandleScope shs(isolate);
4662   ASSERT(args.length() == 2);
4663
4664   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4665   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4666   int f = FastD2IChecked(f_number);
4667   RUNTIME_ASSERT(f >= -1 && f <= 20);
4668   char* str = DoubleToExponentialCString(value, f);
4669   MaybeObject* res =
4670       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4671   DeleteArray(str);
4672   return res;
4673 }
4674
4675
4676 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4677   SealHandleScope shs(isolate);
4678   ASSERT(args.length() == 2);
4679
4680   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4681   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4682   int f = FastD2IChecked(f_number);
4683   RUNTIME_ASSERT(f >= 1 && f <= 21);
4684   char* str = DoubleToPrecisionCString(value, f);
4685   MaybeObject* res =
4686       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4687   DeleteArray(str);
4688   return res;
4689 }
4690
4691
4692 // Returns a single character string where first character equals
4693 // string->Get(index).
4694 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4695   if (index < static_cast<uint32_t>(string->length())) {
4696     string->TryFlatten();
4697     return LookupSingleCharacterStringFromCode(
4698         string->GetIsolate(),
4699         string->Get(index));
4700   }
4701   return Execution::CharAt(string, index);
4702 }
4703
4704
4705 MaybeObject* Runtime::GetElementOrCharAtOrFail(Isolate* isolate,
4706                                                Handle<Object> object,
4707                                                uint32_t index) {
4708   CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4709       GetElementOrCharAt(isolate, object, index));
4710 }
4711
4712
4713 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4714                                          Handle<Object> object,
4715                                          uint32_t index) {
4716   // Handle [] indexing on Strings
4717   if (object->IsString()) {
4718     Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4719     if (!result->IsUndefined()) return *result;
4720   }
4721
4722   // Handle [] indexing on String objects
4723   if (object->IsStringObjectWithCharacterAt(index)) {
4724     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4725     Handle<Object> result =
4726         GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4727     if (!result->IsUndefined()) return *result;
4728   }
4729
4730   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4731     return object->GetPrototype(isolate)->GetElement(index);
4732   }
4733
4734   return object->GetElement(index);
4735 }
4736
4737
4738 MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
4739                                         Handle<JSReceiver> object,
4740                                         Handle<Object> key) {
4741   HandleScope scope(isolate);
4742
4743   // Check if the given key is an array index.
4744   uint32_t index;
4745   if (key->ToArrayIndex(&index)) {
4746     return isolate->heap()->ToBoolean(object->HasElement(index));
4747   }
4748
4749   // Convert the key to a name - possibly by calling back into JavaScript.
4750   Handle<Name> name;
4751   if (key->IsName()) {
4752     name = Handle<Name>::cast(key);
4753   } else {
4754     bool has_pending_exception = false;
4755     Handle<Object> converted =
4756         Execution::ToString(key, &has_pending_exception);
4757     if (has_pending_exception) return Failure::Exception();
4758     name = Handle<Name>::cast(converted);
4759   }
4760
4761   return isolate->heap()->ToBoolean(object->HasProperty(*name));
4762 }
4763
4764 MaybeObject* Runtime::GetObjectPropertyOrFail(
4765     Isolate* isolate,
4766     Handle<Object> object,
4767     Handle<Object> key) {
4768   CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4769       GetObjectProperty(isolate, object, key));
4770 }
4771
4772 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4773                                         Handle<Object> object,
4774                                         Handle<Object> key) {
4775   HandleScope scope(isolate);
4776
4777   if (object->IsUndefined() || object->IsNull()) {
4778     Handle<Object> args[2] = { key, object };
4779     Handle<Object> error =
4780         isolate->factory()->NewTypeError("non_object_property_load",
4781                                          HandleVector(args, 2));
4782     return isolate->Throw(*error);
4783   }
4784
4785   // Check if the given key is an array index.
4786   uint32_t index;
4787   if (key->ToArrayIndex(&index)) {
4788     return GetElementOrCharAt(isolate, object, index);
4789   }
4790
4791   // Convert the key to a name - possibly by calling back into JavaScript.
4792   Handle<Name> name;
4793   if (key->IsName()) {
4794     name = Handle<Name>::cast(key);
4795   } else {
4796     bool has_pending_exception = false;
4797     Handle<Object> converted =
4798         Execution::ToString(key, &has_pending_exception);
4799     if (has_pending_exception) return Failure::Exception();
4800     name = Handle<Name>::cast(converted);
4801   }
4802
4803   // Check if the name is trivially convertible to an index and get
4804   // the element if so.
4805   if (name->AsArrayIndex(&index)) {
4806     return GetElementOrCharAt(isolate, object, index);
4807   } else {
4808     return object->GetProperty(*name);
4809   }
4810 }
4811
4812
4813 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4814   SealHandleScope shs(isolate);
4815   ASSERT(args.length() == 2);
4816
4817   Handle<Object> object = args.at<Object>(0);
4818   Handle<Object> key = args.at<Object>(1);
4819
4820   return Runtime::GetObjectProperty(isolate, object, key);
4821 }
4822
4823
4824 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
4825 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4826   SealHandleScope shs(isolate);
4827   ASSERT(args.length() == 2);
4828
4829   // Fast cases for getting named properties of the receiver JSObject
4830   // itself.
4831   //
4832   // The global proxy objects has to be excluded since LocalLookup on
4833   // the global proxy object can return a valid result even though the
4834   // global proxy object never has properties.  This is the case
4835   // because the global proxy object forwards everything to its hidden
4836   // prototype including local lookups.
4837   //
4838   // Additionally, we need to make sure that we do not cache results
4839   // for objects that require access checks.
4840   if (args[0]->IsJSObject()) {
4841     if (!args[0]->IsJSGlobalProxy() &&
4842         !args[0]->IsAccessCheckNeeded() &&
4843         args[1]->IsName()) {
4844       JSObject* receiver = JSObject::cast(args[0]);
4845       Name* key = Name::cast(args[1]);
4846       if (receiver->HasFastProperties()) {
4847         // Attempt to use lookup cache.
4848         Map* receiver_map = receiver->map();
4849         KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4850         int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4851         if (offset != -1) {
4852           // Doubles are not cached, so raw read the value.
4853           Object* value = receiver->RawFastPropertyAt(offset);
4854           return value->IsTheHole()
4855               ? isolate->heap()->undefined_value()
4856               : value;
4857         }
4858         // Lookup cache miss.  Perform lookup and update the cache if
4859         // appropriate.
4860         LookupResult result(isolate);
4861         receiver->LocalLookup(key, &result);
4862         if (result.IsField()) {
4863           int offset = result.GetFieldIndex().field_index();
4864           // Do not track double fields in the keyed lookup cache. Reading
4865           // double values requires boxing.
4866           if (!FLAG_track_double_fields ||
4867               !result.representation().IsDouble()) {
4868             keyed_lookup_cache->Update(receiver_map, key, offset);
4869           }
4870           return receiver->FastPropertyAt(result.representation(), offset);
4871         }
4872       } else {
4873         // Attempt dictionary lookup.
4874         NameDictionary* dictionary = receiver->property_dictionary();
4875         int entry = dictionary->FindEntry(key);
4876         if ((entry != NameDictionary::kNotFound) &&
4877             (dictionary->DetailsAt(entry).type() == NORMAL)) {
4878           Object* value = dictionary->ValueAt(entry);
4879           if (!receiver->IsGlobalObject()) return value;
4880           value = PropertyCell::cast(value)->value();
4881           if (!value->IsTheHole()) return value;
4882           // If value is the hole do the general lookup.
4883         }
4884       }
4885     } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4886       // JSObject without a name key. If the key is a Smi, check for a
4887       // definite out-of-bounds access to elements, which is a strong indicator
4888       // that subsequent accesses will also call the runtime. Proactively
4889       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
4890       // doubles for those future calls in the case that the elements would
4891       // become FAST_DOUBLE_ELEMENTS.
4892       Handle<JSObject> js_object(args.at<JSObject>(0));
4893       ElementsKind elements_kind = js_object->GetElementsKind();
4894       if (IsFastDoubleElementsKind(elements_kind)) {
4895         FixedArrayBase* elements = js_object->elements();
4896         if (args.at<Smi>(1)->value() >= elements->length()) {
4897           if (IsFastHoleyElementsKind(elements_kind)) {
4898             elements_kind = FAST_HOLEY_ELEMENTS;
4899           } else {
4900             elements_kind = FAST_ELEMENTS;
4901           }
4902           MaybeObject* maybe_object = TransitionElements(js_object,
4903                                                          elements_kind,
4904                                                          isolate);
4905           if (maybe_object->IsFailure()) return maybe_object;
4906         }
4907       } else {
4908         ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
4909                !IsFastElementsKind(elements_kind));
4910       }
4911     }
4912   } else if (args[0]->IsString() && args[1]->IsSmi()) {
4913     // Fast case for string indexing using [] with a smi index.
4914     HandleScope scope(isolate);
4915     Handle<String> str = args.at<String>(0);
4916     int index = args.smi_at(1);
4917     if (index >= 0 && index < str->length()) {
4918       Handle<Object> result = GetCharAt(str, index);
4919       return *result;
4920     }
4921   }
4922
4923   // Fall back to GetObjectProperty.
4924   return Runtime::GetObjectProperty(isolate,
4925                                     args.at<Object>(0),
4926                                     args.at<Object>(1));
4927 }
4928
4929
4930 static bool IsValidAccessor(Handle<Object> obj) {
4931   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4932 }
4933
4934
4935 // Implements part of 8.12.9 DefineOwnProperty.
4936 // There are 3 cases that lead here:
4937 // Step 4b - define a new accessor property.
4938 // Steps 9c & 12 - replace an existing data property with an accessor property.
4939 // Step 12 - update an existing accessor property with an accessor or generic
4940 //           descriptor.
4941 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4942   HandleScope scope(isolate);
4943   ASSERT(args.length() == 5);
4944   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4945   RUNTIME_ASSERT(!obj->IsNull());
4946   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
4947   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4948   RUNTIME_ASSERT(IsValidAccessor(getter));
4949   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4950   RUNTIME_ASSERT(IsValidAccessor(setter));
4951   CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4952   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4953   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4954
4955   bool fast = obj->HasFastProperties();
4956   JSObject::DefineAccessor(obj, name, getter, setter, attr);
4957   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
4958   if (fast) JSObject::TransformToFastProperties(obj, 0);
4959   return isolate->heap()->undefined_value();
4960 }
4961
4962
4963 // Implements part of 8.12.9 DefineOwnProperty.
4964 // There are 3 cases that lead here:
4965 // Step 4a - define a new data property.
4966 // Steps 9b & 12 - replace an existing accessor property with a data property.
4967 // Step 12 - update an existing data property with a data or generic
4968 //           descriptor.
4969 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4970   HandleScope scope(isolate);
4971   ASSERT(args.length() == 4);
4972   CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4973   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
4974   CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4975   CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4976   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4977   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4978
4979   LookupResult result(isolate);
4980   js_object->LocalLookupRealNamedProperty(*name, &result);
4981
4982   // Special case for callback properties.
4983   if (result.IsPropertyCallbacks()) {
4984     Object* callback = result.GetCallbackObject();
4985     // To be compatible with Safari we do not change the value on API objects
4986     // in Object.defineProperty(). Firefox disagrees here, and actually changes
4987     // the value.
4988     if (callback->IsAccessorInfo()) {
4989       return isolate->heap()->undefined_value();
4990     }
4991     // Avoid redefining foreign callback as data property, just use the stored
4992     // setter to update the value instead.
4993     // TODO(mstarzinger): So far this only works if property attributes don't
4994     // change, this should be fixed once we cleanup the underlying code.
4995     if (callback->IsForeign() && result.GetAttributes() == attr) {
4996       return js_object->SetPropertyWithCallback(callback,
4997                                                 *name,
4998                                                 *obj_value,
4999                                                 result.holder(),
5000                                                 kStrictMode);
5001     }
5002   }
5003
5004   // Take special care when attributes are different and there is already
5005   // a property. For simplicity we normalize the property which enables us
5006   // to not worry about changing the instance_descriptor and creating a new
5007   // map. The current version of SetObjectProperty does not handle attributes
5008   // correctly in the case where a property is a field and is reset with
5009   // new attributes.
5010   if (result.IsFound() &&
5011       (attr != result.GetAttributes() || result.IsPropertyCallbacks())) {
5012     // New attributes - normalize to avoid writing to instance descriptor
5013     if (js_object->IsJSGlobalProxy()) {
5014       // Since the result is a property, the prototype will exist so
5015       // we don't have to check for null.
5016       js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5017     }
5018     JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
5019     // Use IgnoreAttributes version since a readonly property may be
5020     // overridden and SetProperty does not allow this.
5021     return js_object->SetLocalPropertyIgnoreAttributes(*name,
5022                                                        *obj_value,
5023                                                        attr);
5024   }
5025
5026   return Runtime::ForceSetObjectProperty(isolate,
5027                                          js_object,
5028                                          name,
5029                                          obj_value,
5030                                          attr);
5031 }
5032
5033
5034 // Return property without being observable by accessors or interceptors.
5035 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
5036   SealHandleScope shs(isolate);
5037   ASSERT(args.length() == 2);
5038   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5039   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5040   LookupResult lookup(isolate);
5041   object->LookupRealNamedProperty(*key, &lookup);
5042   if (!lookup.IsFound()) return isolate->heap()->undefined_value();
5043   switch (lookup.type()) {
5044     case NORMAL:
5045       return lookup.holder()->GetNormalizedProperty(&lookup);
5046     case FIELD:
5047       return lookup.holder()->FastPropertyAt(
5048           lookup.representation(),
5049           lookup.GetFieldIndex().field_index());
5050     case CONSTANT:
5051       return lookup.GetConstant();
5052     case CALLBACKS:
5053     case HANDLER:
5054     case INTERCEPTOR:
5055     case TRANSITION:
5056       return isolate->heap()->undefined_value();
5057     case NONEXISTENT:
5058       UNREACHABLE();
5059   }
5060   return isolate->heap()->undefined_value();
5061 }
5062
5063
5064 MaybeObject* Runtime::SetObjectPropertyOrFail(
5065     Isolate* isolate,
5066     Handle<Object> object,
5067     Handle<Object> key,
5068     Handle<Object> value,
5069     PropertyAttributes attr,
5070     StrictModeFlag strict_mode) {
5071   CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
5072       SetObjectProperty(isolate, object, key, value, attr, strict_mode));
5073 }
5074
5075
5076 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
5077                                         Handle<Object> object,
5078                                         Handle<Object> key,
5079                                         Handle<Object> value,
5080                                         PropertyAttributes attr,
5081                                         StrictModeFlag strict_mode) {
5082   SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5083   HandleScope scope(isolate);
5084
5085   if (object->IsUndefined() || object->IsNull()) {
5086     Handle<Object> args[2] = { key, object };
5087     Handle<Object> error =
5088         isolate->factory()->NewTypeError("non_object_property_store",
5089                                          HandleVector(args, 2));
5090     return isolate->Throw(*error);
5091   }
5092
5093   if (object->IsJSProxy()) {
5094     bool has_pending_exception = false;
5095     Handle<Object> name = key->IsSymbol()
5096         ? key : Execution::ToString(key, &has_pending_exception);
5097     if (has_pending_exception) return Failure::Exception();
5098     return JSProxy::cast(*object)->SetProperty(
5099         Name::cast(*name), *value, attr, strict_mode);
5100   }
5101
5102   // If the object isn't a JavaScript object, we ignore the store.
5103   if (!object->IsJSObject()) return *value;
5104
5105   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5106
5107   // Check if the given key is an array index.
5108   uint32_t index;
5109   if (key->ToArrayIndex(&index)) {
5110     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5111     // of a string using [] notation.  We need to support this too in
5112     // JavaScript.
5113     // In the case of a String object we just need to redirect the assignment to
5114     // the underlying string if the index is in range.  Since the underlying
5115     // string does nothing with the assignment then we can ignore such
5116     // assignments.
5117     if (js_object->IsStringObjectWithCharacterAt(index)) {
5118       return *value;
5119     }
5120
5121     js_object->ValidateElements();
5122     if (js_object->HasExternalArrayElements()) {
5123       if (!value->IsNumber() && !value->IsUndefined()) {
5124         bool has_exception;
5125         Handle<Object> number = Execution::ToNumber(value, &has_exception);
5126         if (has_exception) return Failure::Exception();
5127         value = number;
5128       }
5129     }
5130     MaybeObject* result = js_object->SetElement(
5131         index, *value, attr, strict_mode, true, set_mode);
5132     js_object->ValidateElements();
5133     if (result->IsFailure()) return result;
5134     return *value;
5135   }
5136
5137   if (key->IsName()) {
5138     MaybeObject* result;
5139     Handle<Name> name = Handle<Name>::cast(key);
5140     if (name->AsArrayIndex(&index)) {
5141       if (js_object->HasExternalArrayElements()) {
5142         if (!value->IsNumber() && !value->IsUndefined()) {
5143           bool has_exception;
5144           Handle<Object> number = Execution::ToNumber(value, &has_exception);
5145           if (has_exception) return Failure::Exception();
5146           value = number;
5147         }
5148       }
5149       result = js_object->SetElement(
5150           index, *value, attr, strict_mode, true, set_mode);
5151     } else {
5152       if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5153       result = js_object->SetProperty(*name, *value, attr, strict_mode);
5154     }
5155     if (result->IsFailure()) return result;
5156     return *value;
5157   }
5158
5159   // Call-back into JavaScript to convert the key to a string.
5160   bool has_pending_exception = false;
5161   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
5162   if (has_pending_exception) return Failure::Exception();
5163   Handle<String> name = Handle<String>::cast(converted);
5164
5165   if (name->AsArrayIndex(&index)) {
5166     return js_object->SetElement(
5167         index, *value, attr, strict_mode, true, set_mode);
5168   } else {
5169     return js_object->SetProperty(*name, *value, attr, strict_mode);
5170   }
5171 }
5172
5173
5174 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
5175                                              Handle<JSObject> js_object,
5176                                              Handle<Object> key,
5177                                              Handle<Object> value,
5178                                              PropertyAttributes attr) {
5179   HandleScope scope(isolate);
5180
5181   // Check if the given key is an array index.
5182   uint32_t index;
5183   if (key->ToArrayIndex(&index)) {
5184     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5185     // of a string using [] notation.  We need to support this too in
5186     // JavaScript.
5187     // In the case of a String object we just need to redirect the assignment to
5188     // the underlying string if the index is in range.  Since the underlying
5189     // string does nothing with the assignment then we can ignore such
5190     // assignments.
5191     if (js_object->IsStringObjectWithCharacterAt(index)) {
5192       return *value;
5193     }
5194
5195     return js_object->SetElement(
5196         index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5197   }
5198
5199   if (key->IsName()) {
5200     Handle<Name> name = Handle<Name>::cast(key);
5201     if (name->AsArrayIndex(&index)) {
5202       return js_object->SetElement(
5203           index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5204     } else {
5205       if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5206       return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
5207     }
5208   }
5209
5210   // Call-back into JavaScript to convert the key to a string.
5211   bool has_pending_exception = false;
5212   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
5213   if (has_pending_exception) return Failure::Exception();
5214   Handle<String> name = Handle<String>::cast(converted);
5215
5216   if (name->AsArrayIndex(&index)) {
5217     return js_object->SetElement(
5218         index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5219   } else {
5220     return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
5221   }
5222 }
5223
5224
5225 MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
5226                                            Handle<JSReceiver> receiver,
5227                                            Handle<Object> key,
5228                                            JSReceiver::DeleteMode mode) {
5229   HandleScope scope(isolate);
5230
5231   // Check if the given key is an array index.
5232   uint32_t index;
5233   if (key->ToArrayIndex(&index)) {
5234     // In Firefox/SpiderMonkey, Safari and Opera you can access the
5235     // characters of a string using [] notation.  In the case of a
5236     // String object we just need to redirect the deletion to the
5237     // underlying string if the index is in range.  Since the
5238     // underlying string does nothing with the deletion, we can ignore
5239     // such deletions.
5240     if (receiver->IsStringObjectWithCharacterAt(index)) {
5241       return isolate->heap()->true_value();
5242     }
5243
5244     Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
5245     RETURN_IF_EMPTY_HANDLE(isolate, result);
5246     return *result;
5247   }
5248
5249   Handle<Name> name;
5250   if (key->IsName()) {
5251     name = Handle<Name>::cast(key);
5252   } else {
5253     // Call-back into JavaScript to convert the key to a string.
5254     bool has_pending_exception = false;
5255     Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
5256     if (has_pending_exception) return Failure::Exception();
5257     name = Handle<String>::cast(converted);
5258   }
5259
5260   if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5261   Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
5262   RETURN_IF_EMPTY_HANDLE(isolate, result);
5263   return *result;
5264 }
5265
5266
5267 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
5268   SealHandleScope shs(isolate);
5269   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5270
5271   Handle<Object> object = args.at<Object>(0);
5272   Handle<Object> key = args.at<Object>(1);
5273   Handle<Object> value = args.at<Object>(2);
5274   CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5275   RUNTIME_ASSERT(
5276       (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5277   // Compute attributes.
5278   PropertyAttributes attributes =
5279       static_cast<PropertyAttributes>(unchecked_attributes);
5280
5281   StrictModeFlag strict_mode = kNonStrictMode;
5282   if (args.length() == 5) {
5283     CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
5284     strict_mode = strict_mode_flag;
5285   }
5286
5287   return Runtime::SetObjectProperty(isolate,
5288                                     object,
5289                                     key,
5290                                     value,
5291                                     attributes,
5292                                     strict_mode);
5293 }
5294
5295
5296 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
5297   HandleScope scope(isolate);
5298   RUNTIME_ASSERT(args.length() == 2);
5299   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5300   CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5301   JSObject::TransitionElementsKind(array, map->elements_kind());
5302   return *array;
5303 }
5304
5305
5306 // Set the native flag on the function.
5307 // This is used to decide if we should transform null and undefined
5308 // into the global object when doing call and apply.
5309 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
5310   SealHandleScope shs(isolate);
5311   RUNTIME_ASSERT(args.length() == 1);
5312
5313   Handle<Object> object = args.at<Object>(0);
5314
5315   if (object->IsJSFunction()) {
5316     JSFunction* func = JSFunction::cast(*object);
5317     func->shared()->set_native(true);
5318   }
5319   return isolate->heap()->undefined_value();
5320 }
5321
5322
5323 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
5324   HandleScope scope(isolate);
5325   RUNTIME_ASSERT(args.length() == 5);
5326   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5327   CONVERT_SMI_ARG_CHECKED(store_index, 1);
5328   Handle<Object> value = args.at<Object>(2);
5329   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5330   CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5331
5332   Object* raw_literal_cell = literals->get(literal_index);
5333   JSArray* boilerplate = NULL;
5334   if (raw_literal_cell->IsAllocationSite()) {
5335     AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5336     boilerplate = JSArray::cast(site->transition_info());
5337   } else {
5338     boilerplate = JSArray::cast(raw_literal_cell);
5339   }
5340   Handle<JSArray> boilerplate_object(boilerplate);
5341   ElementsKind elements_kind = object->GetElementsKind();
5342   ASSERT(IsFastElementsKind(elements_kind));
5343   // Smis should never trigger transitions.
5344   ASSERT(!value->IsSmi());
5345
5346   if (value->IsNumber()) {
5347     ASSERT(IsFastSmiElementsKind(elements_kind));
5348     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5349         ? FAST_HOLEY_DOUBLE_ELEMENTS
5350         : FAST_DOUBLE_ELEMENTS;
5351     if (IsMoreGeneralElementsKindTransition(
5352             boilerplate_object->GetElementsKind(),
5353             transitioned_kind)) {
5354       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5355     }
5356     JSObject::TransitionElementsKind(object, transitioned_kind);
5357     ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
5358     FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5359     HeapNumber* number = HeapNumber::cast(*value);
5360     double_array->set(store_index, number->Number());
5361   } else {
5362     ASSERT(IsFastSmiElementsKind(elements_kind) ||
5363            IsFastDoubleElementsKind(elements_kind));
5364     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5365         ? FAST_HOLEY_ELEMENTS
5366         : FAST_ELEMENTS;
5367     JSObject::TransitionElementsKind(object, transitioned_kind);
5368     if (IsMoreGeneralElementsKindTransition(
5369             boilerplate_object->GetElementsKind(),
5370             transitioned_kind)) {
5371       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5372     }
5373     FixedArray* object_array = FixedArray::cast(object->elements());
5374     object_array->set(store_index, *value);
5375   }
5376   return *object;
5377 }
5378
5379
5380 // Check whether debugger and is about to step into the callback that is passed
5381 // to a built-in function such as Array.forEach.
5382 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
5383   SealHandleScope shs(isolate);
5384 #ifdef ENABLE_DEBUGGER_SUPPORT
5385   if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
5386     return isolate->heap()->false_value();
5387   }
5388   CONVERT_ARG_CHECKED(Object, callback, 0);
5389   // We do not step into the callback if it's a builtin or not even a function.
5390   if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
5391     return isolate->heap()->false_value();
5392   }
5393   return isolate->heap()->true_value();
5394 #else
5395   return isolate->heap()->false_value();
5396 #endif  // ENABLE_DEBUGGER_SUPPORT
5397 }
5398
5399
5400 // Set one shot breakpoints for the callback function that is passed to a
5401 // built-in function such as Array.forEach to enable stepping into the callback.
5402 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
5403   SealHandleScope shs(isolate);
5404 #ifdef ENABLE_DEBUGGER_SUPPORT
5405   Debug* debug = isolate->debug();
5406   if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5407   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
5408   HandleScope scope(isolate);
5409   // When leaving the callback, step out has been activated, but not performed
5410   // if we do not leave the builtin.  To be able to step into the callback
5411   // again, we need to clear the step out at this point.
5412   debug->ClearStepOut();
5413   debug->FloodWithOneShot(callback);
5414 #endif  // ENABLE_DEBUGGER_SUPPORT
5415   return isolate->heap()->undefined_value();
5416 }
5417
5418
5419 // Set a local property, even if it is READ_ONLY.  If the property does not
5420 // exist, it will be added with attributes NONE.
5421 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
5422   SealHandleScope shs(isolate);
5423   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
5424   CONVERT_ARG_CHECKED(JSObject, object, 0);
5425   CONVERT_ARG_CHECKED(Name, name, 1);
5426   // Compute attributes.
5427   PropertyAttributes attributes = NONE;
5428   if (args.length() == 4) {
5429     CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
5430     // Only attribute bits should be set.
5431     RUNTIME_ASSERT(
5432         (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5433     attributes = static_cast<PropertyAttributes>(unchecked_value);
5434   }
5435
5436   return object->
5437       SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
5438 }
5439
5440
5441 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
5442   HandleScope scope(isolate);
5443   ASSERT(args.length() == 3);
5444   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5445   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5446   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5447   JSReceiver::DeleteMode delete_mode = (strict_mode == kStrictMode)
5448       ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
5449   Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
5450   RETURN_IF_EMPTY_HANDLE(isolate, result);
5451   return *result;
5452 }
5453
5454
5455 static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
5456                                                    Handle<JSObject> object,
5457                                                    Handle<Name> key) {
5458   if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
5459   // Handle hidden prototypes.  If there's a hidden prototype above this thing
5460   // then we have to check it for properties, because they are supposed to
5461   // look like they are on this object.
5462   Handle<Object> proto(object->GetPrototype(), isolate);
5463   if (proto->IsJSObject() &&
5464       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
5465     return HasLocalPropertyImplementation(isolate,
5466                                           Handle<JSObject>::cast(proto),
5467                                           key);
5468   }
5469   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5470   return isolate->heap()->false_value();
5471 }
5472
5473
5474 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
5475   SealHandleScope shs(isolate);
5476   ASSERT(args.length() == 2);
5477   CONVERT_ARG_CHECKED(Name, key, 1);
5478
5479   uint32_t index;
5480   const bool key_is_array_index = key->AsArrayIndex(&index);
5481
5482   Object* obj = args[0];
5483   // Only JS objects can have properties.
5484   if (obj->IsJSObject()) {
5485     JSObject* object = JSObject::cast(obj);
5486     // Fast case: either the key is a real named property or it is not
5487     // an array index and there are no interceptors or hidden
5488     // prototypes.
5489     if (object->HasRealNamedProperty(isolate, key)) {
5490       ASSERT(!isolate->has_scheduled_exception());
5491       return isolate->heap()->true_value();
5492     } else {
5493       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5494     }
5495     Map* map = object->map();
5496     if (!key_is_array_index &&
5497         !map->has_named_interceptor() &&
5498         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5499       return isolate->heap()->false_value();
5500     }
5501     // Slow case.
5502     HandleScope scope(isolate);
5503     return HasLocalPropertyImplementation(isolate,
5504                                           Handle<JSObject>(object),
5505                                           Handle<Name>(key));
5506   } else if (obj->IsString() && key_is_array_index) {
5507     // Well, there is one exception:  Handle [] on strings.
5508     String* string = String::cast(obj);
5509     if (index < static_cast<uint32_t>(string->length())) {
5510       return isolate->heap()->true_value();
5511     }
5512   }
5513   return isolate->heap()->false_value();
5514 }
5515
5516
5517 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
5518   SealHandleScope shs(isolate);
5519   ASSERT(args.length() == 2);
5520   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
5521   CONVERT_ARG_CHECKED(Name, key, 1);
5522
5523   bool result = receiver->HasProperty(key);
5524   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5525   if (isolate->has_pending_exception()) return Failure::Exception();
5526   return isolate->heap()->ToBoolean(result);
5527 }
5528
5529
5530 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
5531   SealHandleScope shs(isolate);
5532   ASSERT(args.length() == 2);
5533   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
5534   CONVERT_SMI_ARG_CHECKED(index, 1);
5535
5536   bool result = receiver->HasElement(index);
5537   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5538   if (isolate->has_pending_exception()) return Failure::Exception();
5539   return isolate->heap()->ToBoolean(result);
5540 }
5541
5542
5543 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
5544   SealHandleScope shs(isolate);
5545   ASSERT(args.length() == 2);
5546
5547   CONVERT_ARG_CHECKED(JSObject, object, 0);
5548   CONVERT_ARG_CHECKED(Name, key, 1);
5549
5550   PropertyAttributes att = object->GetLocalPropertyAttribute(key);
5551   if (att == ABSENT || (att & DONT_ENUM) != 0) {
5552     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5553     return isolate->heap()->false_value();
5554   }
5555   ASSERT(!isolate->has_scheduled_exception());
5556   return isolate->heap()->true_value();
5557 }
5558
5559
5560 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
5561   HandleScope scope(isolate);
5562   ASSERT(args.length() == 1);
5563   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5564   bool threw = false;
5565   Handle<JSArray> result = GetKeysFor(object, &threw);
5566   if (threw) return Failure::Exception();
5567   return *result;
5568 }
5569
5570
5571 // Returns either a FixedArray as Runtime_GetPropertyNames,
5572 // or, if the given object has an enum cache that contains
5573 // all enumerable properties of the object and its prototypes
5574 // have none, the map of the object. This is used to speed up
5575 // the check for deletions during a for-in.
5576 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
5577   SealHandleScope shs(isolate);
5578   ASSERT(args.length() == 1);
5579
5580   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5581
5582   if (raw_object->IsSimpleEnum()) return raw_object->map();
5583
5584   HandleScope scope(isolate);
5585   Handle<JSReceiver> object(raw_object);
5586   bool threw = false;
5587   Handle<FixedArray> content =
5588       GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
5589   if (threw) return Failure::Exception();
5590
5591   // Test again, since cache may have been built by preceding call.
5592   if (object->IsSimpleEnum()) return object->map();
5593
5594   return *content;
5595 }
5596
5597
5598 // Find the length of the prototype chain that is to to handled as one. If a
5599 // prototype object is hidden it is to be viewed as part of the the object it
5600 // is prototype for.
5601 static int LocalPrototypeChainLength(JSObject* obj) {
5602   int count = 1;
5603   Object* proto = obj->GetPrototype();
5604   while (proto->IsJSObject() &&
5605          JSObject::cast(proto)->map()->is_hidden_prototype()) {
5606     count++;
5607     proto = JSObject::cast(proto)->GetPrototype();
5608   }
5609   return count;
5610 }
5611
5612
5613 // Return the names of the local named properties.
5614 // args[0]: object
5615 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
5616   HandleScope scope(isolate);
5617   ASSERT(args.length() == 2);
5618   if (!args[0]->IsJSObject()) {
5619     return isolate->heap()->undefined_value();
5620   }
5621   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5622   CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
5623   PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
5624
5625   // Skip the global proxy as it has no properties and always delegates to the
5626   // real global object.
5627   if (obj->IsJSGlobalProxy()) {
5628     // Only collect names if access is permitted.
5629     if (obj->IsAccessCheckNeeded() &&
5630         !isolate->MayNamedAccess(*obj,
5631                                  isolate->heap()->undefined_value(),
5632                                  v8::ACCESS_KEYS)) {
5633       isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
5634       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5635       return *isolate->factory()->NewJSArray(0);
5636     }
5637     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5638   }
5639
5640   // Find the number of objects making up this.
5641   int length = LocalPrototypeChainLength(*obj);
5642
5643   // Find the number of local properties for each of the objects.
5644   ScopedVector<int> local_property_count(length);
5645   int total_property_count = 0;
5646   Handle<JSObject> jsproto = obj;
5647   for (int i = 0; i < length; i++) {
5648     // Only collect names if access is permitted.
5649     if (jsproto->IsAccessCheckNeeded() &&
5650         !isolate->MayNamedAccess(*jsproto,
5651                                  isolate->heap()->undefined_value(),
5652                                  v8::ACCESS_KEYS)) {
5653       isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
5654       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5655       return *isolate->factory()->NewJSArray(0);
5656     }
5657     int n;
5658     n = jsproto->NumberOfLocalProperties(filter);
5659     local_property_count[i] = n;
5660     total_property_count += n;
5661     if (i < length - 1) {
5662       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5663     }
5664   }
5665
5666   // Allocate an array with storage for all the property names.
5667   Handle<FixedArray> names =
5668       isolate->factory()->NewFixedArray(total_property_count);
5669
5670   // Get the property names.
5671   jsproto = obj;
5672   int proto_with_hidden_properties = 0;
5673   int next_copy_index = 0;
5674   for (int i = 0; i < length; i++) {
5675     jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
5676     next_copy_index += local_property_count[i];
5677     if (jsproto->HasHiddenProperties()) {
5678       proto_with_hidden_properties++;
5679     }
5680     if (i < length - 1) {
5681       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5682     }
5683   }
5684
5685   // Filter out name of hidden properties object.
5686   if (proto_with_hidden_properties > 0) {
5687     Handle<FixedArray> old_names = names;
5688     names = isolate->factory()->NewFixedArray(
5689         names->length() - proto_with_hidden_properties);
5690     int dest_pos = 0;
5691     for (int i = 0; i < total_property_count; i++) {
5692       Object* name = old_names->get(i);
5693       if (name == isolate->heap()->hidden_string()) {
5694         continue;
5695       }
5696       names->set(dest_pos++, name);
5697     }
5698   }
5699
5700   return *isolate->factory()->NewJSArrayWithElements(names);
5701 }
5702
5703
5704 // Return the names of the local indexed properties.
5705 // args[0]: object
5706 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5707   HandleScope scope(isolate);
5708   ASSERT(args.length() == 1);
5709   if (!args[0]->IsJSObject()) {
5710     return isolate->heap()->undefined_value();
5711   }
5712   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5713
5714   int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5715   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5716   obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5717   return *isolate->factory()->NewJSArrayWithElements(names);
5718 }
5719
5720
5721 // Return information on whether an object has a named or indexed interceptor.
5722 // args[0]: object
5723 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5724   HandleScope scope(isolate);
5725   ASSERT(args.length() == 1);
5726   if (!args[0]->IsJSObject()) {
5727     return Smi::FromInt(0);
5728   }
5729   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5730
5731   int result = 0;
5732   if (obj->HasNamedInterceptor()) result |= 2;
5733   if (obj->HasIndexedInterceptor()) result |= 1;
5734
5735   return Smi::FromInt(result);
5736 }
5737
5738
5739 // Return property names from named interceptor.
5740 // args[0]: object
5741 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5742   HandleScope scope(isolate);
5743   ASSERT(args.length() == 1);
5744   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5745
5746   if (obj->HasNamedInterceptor()) {
5747     v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5748     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5749   }
5750   return isolate->heap()->undefined_value();
5751 }
5752
5753
5754 // Return element names from indexed interceptor.
5755 // args[0]: object
5756 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5757   HandleScope scope(isolate);
5758   ASSERT(args.length() == 1);
5759   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5760
5761   if (obj->HasIndexedInterceptor()) {
5762     v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5763     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5764   }
5765   return isolate->heap()->undefined_value();
5766 }
5767
5768
5769 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5770   HandleScope scope(isolate);
5771   ASSERT_EQ(args.length(), 1);
5772   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5773   Handle<JSObject> object(raw_object);
5774
5775   if (object->IsJSGlobalProxy()) {
5776     // Do access checks before going to the global object.
5777     if (object->IsAccessCheckNeeded() &&
5778         !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5779                              v8::ACCESS_KEYS)) {
5780       isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5781       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5782       return *isolate->factory()->NewJSArray(0);
5783     }
5784
5785     Handle<Object> proto(object->GetPrototype(), isolate);
5786     // If proxy is detached we simply return an empty array.
5787     if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5788     object = Handle<JSObject>::cast(proto);
5789   }
5790
5791   bool threw = false;
5792   Handle<FixedArray> contents =
5793       GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5794   if (threw) return Failure::Exception();
5795
5796   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5797   // property array and since the result is mutable we have to create
5798   // a fresh clone on each invocation.
5799   int length = contents->length();
5800   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5801   for (int i = 0; i < length; i++) {
5802     Object* entry = contents->get(i);
5803     if (entry->IsString()) {
5804       copy->set(i, entry);
5805     } else {
5806       ASSERT(entry->IsNumber());
5807       HandleScope scope(isolate);
5808       Handle<Object> entry_handle(entry, isolate);
5809       Handle<Object> entry_str =
5810           isolate->factory()->NumberToString(entry_handle);
5811       copy->set(i, *entry_str);
5812     }
5813   }
5814   return *isolate->factory()->NewJSArrayWithElements(copy);
5815 }
5816
5817
5818 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5819   SealHandleScope shs(isolate);
5820   ASSERT(args.length() == 1);
5821
5822   // Compute the frame holding the arguments.
5823   JavaScriptFrameIterator it(isolate);
5824   it.AdvanceToArgumentsFrame();
5825   JavaScriptFrame* frame = it.frame();
5826
5827   // Get the actual number of provided arguments.
5828   const uint32_t n = frame->ComputeParametersCount();
5829
5830   // Try to convert the key to an index. If successful and within
5831   // index return the the argument from the frame.
5832   uint32_t index;
5833   if (args[0]->ToArrayIndex(&index) && index < n) {
5834     return frame->GetParameter(index);
5835   }
5836
5837   if (args[0]->IsSymbol()) {
5838     // Lookup in the initial Object.prototype object.
5839     return isolate->initial_object_prototype()->GetProperty(
5840         Symbol::cast(args[0]));
5841   }
5842
5843   // Convert the key to a string.
5844   HandleScope scope(isolate);
5845   bool exception = false;
5846   Handle<Object> converted =
5847       Execution::ToString(args.at<Object>(0), &exception);
5848   if (exception) return Failure::Exception();
5849   Handle<String> key = Handle<String>::cast(converted);
5850
5851   // Try to convert the string key into an array index.
5852   if (key->AsArrayIndex(&index)) {
5853     if (index < n) {
5854       return frame->GetParameter(index);
5855     } else {
5856       return isolate->initial_object_prototype()->GetElement(index);
5857     }
5858   }
5859
5860   // Handle special arguments properties.
5861   if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
5862   if (key->Equals(isolate->heap()->callee_string())) {
5863     JSFunction* function = frame->function();
5864     if (!function->shared()->is_classic_mode()) {
5865       return isolate->Throw(*isolate->factory()->NewTypeError(
5866           "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5867     }
5868     return function;
5869   }
5870
5871   // Lookup in the initial Object.prototype object.
5872   return isolate->initial_object_prototype()->GetProperty(*key);
5873 }
5874
5875
5876 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5877   SealHandleScope shs(isolate);
5878   ASSERT(args.length() == 1);
5879   Object* object = args[0];
5880   return (object->IsJSObject() && !object->IsGlobalObject())
5881       ? JSObject::cast(object)->TransformToFastProperties(0)
5882       : object;
5883 }
5884
5885
5886 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5887   SealHandleScope shs(isolate);
5888   ASSERT(args.length() == 1);
5889
5890   return isolate->heap()->ToBoolean(args[0]->BooleanValue());
5891 }
5892
5893
5894 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
5895 // Possible optimizations: put the type string into the oddballs.
5896 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
5897   SealHandleScope shs(isolate);
5898
5899   Object* obj = args[0];
5900   if (obj->IsNumber()) return isolate->heap()->number_string();
5901   HeapObject* heap_obj = HeapObject::cast(obj);
5902
5903   // typeof an undetectable object is 'undefined'
5904   if (heap_obj->map()->is_undetectable()) {
5905     return isolate->heap()->undefined_string();
5906   }
5907
5908   InstanceType instance_type = heap_obj->map()->instance_type();
5909   if (instance_type < FIRST_NONSTRING_TYPE) {
5910     return isolate->heap()->string_string();
5911   }
5912
5913   switch (instance_type) {
5914     case ODDBALL_TYPE:
5915       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
5916         return isolate->heap()->boolean_string();
5917       }
5918       if (heap_obj->IsNull()) {
5919         return FLAG_harmony_typeof
5920             ? isolate->heap()->null_string()
5921             : isolate->heap()->object_string();
5922       }
5923       ASSERT(heap_obj->IsUndefined());
5924       return isolate->heap()->undefined_string();
5925     case SYMBOL_TYPE:
5926       return isolate->heap()->symbol_string();
5927     case JS_FUNCTION_TYPE:
5928     case JS_FUNCTION_PROXY_TYPE:
5929       return isolate->heap()->function_string();
5930     default:
5931       // For any kind of object not handled above, the spec rule for
5932       // host objects gives that it is okay to return "object"
5933       return isolate->heap()->object_string();
5934   }
5935 }
5936
5937
5938 static bool AreDigits(const uint8_t*s, int from, int to) {
5939   for (int i = from; i < to; i++) {
5940     if (s[i] < '0' || s[i] > '9') return false;
5941   }
5942
5943   return true;
5944 }
5945
5946
5947 static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
5948   ASSERT(to - from < 10);  // Overflow is not possible.
5949   ASSERT(from < to);
5950   int d = s[from] - '0';
5951
5952   for (int i = from + 1; i < to; i++) {
5953     d = 10 * d + (s[i] - '0');
5954   }
5955
5956   return d;
5957 }
5958
5959
5960 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
5961   SealHandleScope shs(isolate);
5962   ASSERT(args.length() == 1);
5963   CONVERT_ARG_CHECKED(String, subject, 0);
5964   subject->TryFlatten();
5965
5966   // Fast case: short integer or some sorts of junk values.
5967   int len = subject->length();
5968   if (subject->IsSeqOneByteString()) {
5969     if (len == 0) return Smi::FromInt(0);
5970
5971     uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
5972     bool minus = (data[0] == '-');
5973     int start_pos = (minus ? 1 : 0);
5974
5975     if (start_pos == len) {
5976       return isolate->heap()->nan_value();
5977     } else if (data[start_pos] > '9') {
5978       // Fast check for a junk value. A valid string may start from a
5979       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
5980       // the 'I' character ('Infinity'). All of that have codes not greater than
5981       // '9' except 'I' and &nbsp;.
5982       if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
5983         return isolate->heap()->nan_value();
5984       }
5985     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
5986       // The maximal/minimal smi has 10 digits. If the string has less digits we
5987       // know it will fit into the smi-data type.
5988       int d = ParseDecimalInteger(data, start_pos, len);
5989       if (minus) {
5990         if (d == 0) return isolate->heap()->minus_zero_value();
5991         d = -d;
5992       } else if (!subject->HasHashCode() &&
5993                  len <= String::kMaxArrayIndexSize &&
5994                  (len == 1 || data[0] != '0')) {
5995         // String hash is not calculated yet but all the data are present.
5996         // Update the hash field to speed up sequential convertions.
5997         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
5998 #ifdef DEBUG
5999         subject->Hash();  // Force hash calculation.
6000         ASSERT_EQ(static_cast<int>(subject->hash_field()),
6001                   static_cast<int>(hash));
6002 #endif
6003         subject->set_hash_field(hash);
6004       }
6005       return Smi::FromInt(d);
6006     }
6007   }
6008
6009   // Slower case.
6010   int flags = ALLOW_HEX;
6011   if (FLAG_harmony_numeric_literals) {
6012     // The current spec draft has not updated "ToNumber Applied to the String
6013     // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6014     flags |= ALLOW_OCTAL | ALLOW_BINARY;
6015   }
6016   return isolate->heap()->NumberFromDouble(
6017       StringToDouble(isolate->unicode_cache(), subject, flags));
6018 }
6019
6020
6021 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
6022   SealHandleScope shs(isolate);
6023   CONVERT_SMI_ARG_CHECKED(length, 0);
6024   CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6025   if (length == 0) return isolate->heap()->empty_string();
6026   if (is_one_byte) {
6027     return isolate->heap()->AllocateRawOneByteString(length);
6028   } else {
6029     return isolate->heap()->AllocateRawTwoByteString(length);
6030   }
6031 }
6032
6033
6034 RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
6035   HandleScope scope(isolate);
6036   CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
6037   CONVERT_SMI_ARG_CHECKED(new_length, 1);
6038   return *SeqString::Truncate(string, new_length);
6039 }
6040
6041
6042 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
6043   HandleScope scope(isolate);
6044   ASSERT(args.length() == 1);
6045   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6046   Handle<String> string = FlattenGetString(source);
6047   ASSERT(string->IsFlat());
6048   Handle<String> result = string->IsOneByteRepresentationUnderneath()
6049       ? URIEscape::Escape<uint8_t>(isolate, source)
6050       : URIEscape::Escape<uc16>(isolate, source);
6051   if (result.is_null()) return Failure::OutOfMemoryException(0x12);
6052   return *result;
6053 }
6054
6055
6056 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
6057   HandleScope scope(isolate);
6058   ASSERT(args.length() == 1);
6059   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6060   Handle<String> string = FlattenGetString(source);
6061   ASSERT(string->IsFlat());
6062   return string->IsOneByteRepresentationUnderneath()
6063       ? *URIUnescape::Unescape<uint8_t>(isolate, source)
6064       : *URIUnescape::Unescape<uc16>(isolate, source);
6065 }
6066
6067
6068 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
6069   HandleScope scope(isolate);
6070   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6071   ASSERT(args.length() == 1);
6072   return BasicJsonStringifier::StringifyString(isolate, string);
6073 }
6074
6075
6076 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
6077   HandleScope scope(isolate);
6078   ASSERT(args.length() == 1);
6079   BasicJsonStringifier stringifier(isolate);
6080   return stringifier.Stringify(Handle<Object>(args[0], isolate));
6081 }
6082
6083
6084 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
6085   SealHandleScope shs(isolate);
6086
6087   CONVERT_ARG_CHECKED(String, s, 0);
6088   CONVERT_SMI_ARG_CHECKED(radix, 1);
6089
6090   s->TryFlatten();
6091
6092   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6093   double value = StringToInt(isolate->unicode_cache(), s, radix);
6094   return isolate->heap()->NumberFromDouble(value);
6095 }
6096
6097
6098 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6099   SealHandleScope shs(isolate);
6100   CONVERT_ARG_CHECKED(String, str, 0);
6101
6102   // ECMA-262 section 15.1.2.3, empty string is NaN
6103   double value = StringToDouble(isolate->unicode_cache(),
6104                                 str, ALLOW_TRAILING_JUNK, OS::nan_value());
6105
6106   // Create a number object from the value.
6107   return isolate->heap()->NumberFromDouble(value);
6108 }
6109
6110
6111 template <class Converter>
6112 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6113     Isolate* isolate,
6114     String* s,
6115     int length,
6116     int input_string_length,
6117     unibrow::Mapping<Converter, 128>* mapping) {
6118   // We try this twice, once with the assumption that the result is no longer
6119   // than the input and, if that assumption breaks, again with the exact
6120   // length.  This may not be pretty, but it is nicer than what was here before
6121   // and I hereby claim my vaffel-is.
6122   //
6123   // Allocate the resulting string.
6124   //
6125   // NOTE: This assumes that the upper/lower case of an ASCII
6126   // character is also ASCII.  This is currently the case, but it
6127   // might break in the future if we implement more context and locale
6128   // dependent upper/lower conversions.
6129   Object* o;
6130   { MaybeObject* maybe_o = s->IsOneByteRepresentation()
6131         ? isolate->heap()->AllocateRawOneByteString(length)
6132         : isolate->heap()->AllocateRawTwoByteString(length);
6133     if (!maybe_o->ToObject(&o)) return maybe_o;
6134   }
6135   String* result = String::cast(o);
6136   bool has_changed_character = false;
6137
6138   // Convert all characters to upper case, assuming that they will fit
6139   // in the buffer
6140   Access<ConsStringIteratorOp> op(
6141       isolate->runtime_state()->string_iterator());
6142   StringCharacterStream stream(s, op.value());
6143   unibrow::uchar chars[Converter::kMaxWidth];
6144   // We can assume that the string is not empty
6145   uc32 current = stream.GetNext();
6146   for (int i = 0; i < length;) {
6147     bool has_next = stream.HasMore();
6148     uc32 next = has_next ? stream.GetNext() : 0;
6149     int char_length = mapping->get(current, next, chars);
6150     if (char_length == 0) {
6151       // The case conversion of this character is the character itself.
6152       result->Set(i, current);
6153       i++;
6154     } else if (char_length == 1) {
6155       // Common case: converting the letter resulted in one character.
6156       ASSERT(static_cast<uc32>(chars[0]) != current);
6157       result->Set(i, chars[0]);
6158       has_changed_character = true;
6159       i++;
6160     } else if (length == input_string_length) {
6161       // We've assumed that the result would be as long as the
6162       // input but here is a character that converts to several
6163       // characters.  No matter, we calculate the exact length
6164       // of the result and try the whole thing again.
6165       //
6166       // Note that this leaves room for optimization.  We could just
6167       // memcpy what we already have to the result string.  Also,
6168       // the result string is the last object allocated we could
6169       // "realloc" it and probably, in the vast majority of cases,
6170       // extend the existing string to be able to hold the full
6171       // result.
6172       int next_length = 0;
6173       if (has_next) {
6174         next_length = mapping->get(next, 0, chars);
6175         if (next_length == 0) next_length = 1;
6176       }
6177       int current_length = i + char_length + next_length;
6178       while (stream.HasMore()) {
6179         current = stream.GetNext();
6180         // NOTE: we use 0 as the next character here because, while
6181         // the next character may affect what a character converts to,
6182         // it does not in any case affect the length of what it convert
6183         // to.
6184         int char_length = mapping->get(current, 0, chars);
6185         if (char_length == 0) char_length = 1;
6186         current_length += char_length;
6187         if (current_length > Smi::kMaxValue) {
6188           isolate->context()->mark_out_of_memory();
6189           return Failure::OutOfMemoryException(0x13);
6190         }
6191       }
6192       // Try again with the real length.
6193       return Smi::FromInt(current_length);
6194     } else {
6195       for (int j = 0; j < char_length; j++) {
6196         result->Set(i, chars[j]);
6197         i++;
6198       }
6199       has_changed_character = true;
6200     }
6201     current = next;
6202   }
6203   if (has_changed_character) {
6204     return result;
6205   } else {
6206     // If we didn't actually change anything in doing the conversion
6207     // we simple return the result and let the converted string
6208     // become garbage; there is no reason to keep two identical strings
6209     // alive.
6210     return s;
6211   }
6212 }
6213
6214
6215 namespace {
6216
6217 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6218 static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6219
6220 // Given a word and two range boundaries returns a word with high bit
6221 // set in every byte iff the corresponding input byte was strictly in
6222 // the range (m, n). All the other bits in the result are cleared.
6223 // This function is only useful when it can be inlined and the
6224 // boundaries are statically known.
6225 // Requires: all bytes in the input word and the boundaries must be
6226 // ASCII (less than 0x7F).
6227 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6228   // Use strict inequalities since in edge cases the function could be
6229   // further simplified.
6230   ASSERT(0 < m && m < n);
6231   // Has high bit set in every w byte less than n.
6232   uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6233   // Has high bit set in every w byte greater than m.
6234   uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6235   return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6236 }
6237
6238
6239 enum AsciiCaseConversion {
6240   ASCII_TO_LOWER,
6241   ASCII_TO_UPPER
6242 };
6243
6244
6245 template <AsciiCaseConversion dir>
6246 struct FastAsciiConverter {
6247   static bool Convert(char* dst, char* src, int length, bool* changed_out) {
6248 #ifdef DEBUG
6249     char* saved_dst = dst;
6250     char* saved_src = src;
6251 #endif
6252     // We rely on the distance between upper and lower case letters
6253     // being a known power of 2.
6254     ASSERT('a' - 'A' == (1 << 5));
6255     // Boundaries for the range of input characters than require conversion.
6256     const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
6257     const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
6258     bool changed = false;
6259     uintptr_t or_acc = 0;
6260     char* const limit = src + length;
6261 #ifdef V8_HOST_CAN_READ_UNALIGNED
6262     // Process the prefix of the input that requires no conversion one
6263     // (machine) word at a time.
6264     while (src <= limit - sizeof(uintptr_t)) {
6265       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6266       or_acc |= w;
6267       if (AsciiRangeMask(w, lo, hi) != 0) {
6268         changed = true;
6269         break;
6270       }
6271       *reinterpret_cast<uintptr_t*>(dst) = w;
6272       src += sizeof(uintptr_t);
6273       dst += sizeof(uintptr_t);
6274     }
6275     // Process the remainder of the input performing conversion when
6276     // required one word at a time.
6277     while (src <= limit - sizeof(uintptr_t)) {
6278       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6279       or_acc |= w;
6280       uintptr_t m = AsciiRangeMask(w, lo, hi);
6281       // The mask has high (7th) bit set in every byte that needs
6282       // conversion and we know that the distance between cases is
6283       // 1 << 5.
6284       *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6285       src += sizeof(uintptr_t);
6286       dst += sizeof(uintptr_t);
6287     }
6288 #endif
6289     // Process the last few bytes of the input (or the whole input if
6290     // unaligned access is not supported).
6291     while (src < limit) {
6292       char c = *src;
6293       or_acc |= c;
6294       if (lo < c && c < hi) {
6295         c ^= (1 << 5);
6296         changed = true;
6297       }
6298       *dst = c;
6299       ++src;
6300       ++dst;
6301     }
6302     if ((or_acc & kAsciiMask) != 0) {
6303       return false;
6304     }
6305 #ifdef DEBUG
6306     CheckConvert(saved_dst, saved_src, length, changed);
6307 #endif
6308     *changed_out = changed;
6309     return true;
6310   }
6311
6312 #ifdef DEBUG
6313   static void CheckConvert(char* dst, char* src, int length, bool changed) {
6314     bool expected_changed = false;
6315     for (int i = 0; i < length; i++) {
6316       if (dst[i] == src[i]) continue;
6317       expected_changed = true;
6318       if (dir == ASCII_TO_LOWER) {
6319         ASSERT('A' <= src[i] && src[i] <= 'Z');
6320         ASSERT(dst[i] == src[i] + ('a' - 'A'));
6321       } else {
6322         ASSERT(dir == ASCII_TO_UPPER);
6323         ASSERT('a' <= src[i] && src[i] <= 'z');
6324         ASSERT(dst[i] == src[i] - ('a' - 'A'));
6325       }
6326     }
6327     ASSERT(expected_changed == changed);
6328   }
6329 #endif
6330 };
6331
6332
6333 struct ToLowerTraits {
6334   typedef unibrow::ToLowercase UnibrowConverter;
6335
6336   typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6337 };
6338
6339
6340 struct ToUpperTraits {
6341   typedef unibrow::ToUppercase UnibrowConverter;
6342
6343   typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6344 };
6345
6346 }  // namespace
6347
6348
6349 template <typename ConvertTraits>
6350 MUST_USE_RESULT static MaybeObject* ConvertCase(
6351     Arguments args,
6352     Isolate* isolate,
6353     unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
6354   SealHandleScope shs(isolate);
6355   CONVERT_ARG_CHECKED(String, s, 0);
6356   s = s->TryFlattenGetString();
6357
6358   const int length = s->length();
6359   // Assume that the string is not empty; we need this assumption later
6360   if (length == 0) return s;
6361
6362   // Simpler handling of ASCII strings.
6363   //
6364   // NOTE: This assumes that the upper/lower case of an ASCII
6365   // character is also ASCII.  This is currently the case, but it
6366   // might break in the future if we implement more context and locale
6367   // dependent upper/lower conversions.
6368   if (s->IsSeqOneByteString()) {
6369     Object* o;
6370     { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length);
6371       if (!maybe_o->ToObject(&o)) return maybe_o;
6372     }
6373     SeqOneByteString* result = SeqOneByteString::cast(o);
6374     bool has_changed_character;
6375     bool is_ascii = ConvertTraits::AsciiConverter::Convert(
6376         reinterpret_cast<char*>(result->GetChars()),
6377         reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
6378         length,
6379         &has_changed_character);
6380     // If not ASCII, we discard the result and take the 2 byte path.
6381     if (is_ascii) {
6382       return has_changed_character ? result : s;
6383     }
6384   }
6385
6386   Object* answer;
6387   { MaybeObject* maybe_answer =
6388         ConvertCaseHelper(isolate, s, length, length, mapping);
6389     if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6390   }
6391   if (answer->IsSmi()) {
6392     // Retry with correct length.
6393     { MaybeObject* maybe_answer =
6394           ConvertCaseHelper(isolate,
6395                             s, Smi::cast(answer)->value(), length, mapping);
6396       if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6397     }
6398   }
6399   return answer;
6400 }
6401
6402
6403 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6404   return ConvertCase<ToLowerTraits>(
6405       args, isolate, isolate->runtime_state()->to_lower_mapping());
6406 }
6407
6408
6409 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6410   return ConvertCase<ToUpperTraits>(
6411       args, isolate, isolate->runtime_state()->to_upper_mapping());
6412 }
6413
6414
6415 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6416   return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6417 }
6418
6419
6420 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6421   SealHandleScope shs(isolate);
6422   ASSERT(args.length() == 3);
6423
6424   CONVERT_ARG_CHECKED(String, s, 0);
6425   CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6426   CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6427
6428   s->TryFlatten();
6429   int length = s->length();
6430
6431   int left = 0;
6432   if (trimLeft) {
6433     while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6434       left++;
6435     }
6436   }
6437
6438   int right = length;
6439   if (trimRight) {
6440     while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6441       right--;
6442     }
6443   }
6444   return s->SubString(left, right);
6445 }
6446
6447
6448 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6449   HandleScope handle_scope(isolate);
6450   ASSERT(args.length() == 3);
6451   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6452   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6453   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6454
6455   int subject_length = subject->length();
6456   int pattern_length = pattern->length();
6457   RUNTIME_ASSERT(pattern_length > 0);
6458
6459   if (limit == 0xffffffffu) {
6460     Handle<Object> cached_answer(
6461         RegExpResultsCache::Lookup(isolate->heap(),
6462                                    *subject,
6463                                    *pattern,
6464                                    RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
6465         isolate);
6466     if (*cached_answer != Smi::FromInt(0)) {
6467       // The cache FixedArray is a COW-array and can therefore be reused.
6468       Handle<JSArray> result =
6469           isolate->factory()->NewJSArrayWithElements(
6470               Handle<FixedArray>::cast(cached_answer));
6471       return *result;
6472     }
6473   }
6474
6475   // The limit can be very large (0xffffffffu), but since the pattern
6476   // isn't empty, we can never create more parts than ~half the length
6477   // of the subject.
6478
6479   if (!subject->IsFlat()) FlattenString(subject);
6480
6481   static const int kMaxInitialListCapacity = 16;
6482
6483   ZoneScope zone_scope(isolate->runtime_zone());
6484
6485   // Find (up to limit) indices of separator and end-of-string in subject
6486   int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6487   ZoneList<int> indices(initial_capacity, zone_scope.zone());
6488   if (!pattern->IsFlat()) FlattenString(pattern);
6489
6490   FindStringIndicesDispatch(isolate, *subject, *pattern,
6491                             &indices, limit, zone_scope.zone());
6492
6493   if (static_cast<uint32_t>(indices.length()) < limit) {
6494     indices.Add(subject_length, zone_scope.zone());
6495   }
6496
6497   // The list indices now contains the end of each part to create.
6498
6499   // Create JSArray of substrings separated by separator.
6500   int part_count = indices.length();
6501
6502   Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6503   MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
6504   if (maybe_result->IsFailure()) return maybe_result;
6505   result->set_length(Smi::FromInt(part_count));
6506
6507   ASSERT(result->HasFastObjectElements());
6508
6509   if (part_count == 1 && indices.at(0) == subject_length) {
6510     FixedArray::cast(result->elements())->set(0, *subject);
6511     return *result;
6512   }
6513
6514   Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6515   int part_start = 0;
6516   for (int i = 0; i < part_count; i++) {
6517     HandleScope local_loop_handle(isolate);
6518     int part_end = indices.at(i);
6519     Handle<String> substring =
6520         isolate->factory()->NewProperSubString(subject, part_start, part_end);
6521     elements->set(i, *substring);
6522     part_start = part_end + pattern_length;
6523   }
6524
6525   if (limit == 0xffffffffu) {
6526     if (result->HasFastObjectElements()) {
6527       RegExpResultsCache::Enter(isolate->heap(),
6528                                 *subject,
6529                                 *pattern,
6530                                 *elements,
6531                                 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
6532     }
6533   }
6534
6535   return *result;
6536 }
6537
6538
6539 // Copies ASCII characters to the given fixed array looking up
6540 // one-char strings in the cache. Gives up on the first char that is
6541 // not in the cache and fills the remainder with smi zeros. Returns
6542 // the length of the successfully copied prefix.
6543 static int CopyCachedAsciiCharsToArray(Heap* heap,
6544                                        const uint8_t* chars,
6545                                        FixedArray* elements,
6546                                        int length) {
6547   DisallowHeapAllocation no_gc;
6548   FixedArray* ascii_cache = heap->single_character_string_cache();
6549   Object* undefined = heap->undefined_value();
6550   int i;
6551   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6552   for (i = 0; i < length; ++i) {
6553     Object* value = ascii_cache->get(chars[i]);
6554     if (value == undefined) break;
6555     elements->set(i, value, mode);
6556   }
6557   if (i < length) {
6558     ASSERT(Smi::FromInt(0) == 0);
6559     memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6560   }
6561 #ifdef DEBUG
6562   for (int j = 0; j < length; ++j) {
6563     Object* element = elements->get(j);
6564     ASSERT(element == Smi::FromInt(0) ||
6565            (element->IsString() && String::cast(element)->LooksValid()));
6566   }
6567 #endif
6568   return i;
6569 }
6570
6571
6572 // Converts a String to JSArray.
6573 // For example, "foo" => ["f", "o", "o"].
6574 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6575   HandleScope scope(isolate);
6576   ASSERT(args.length() == 2);
6577   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6578   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6579
6580   s = FlattenGetString(s);
6581   const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6582
6583   Handle<FixedArray> elements;
6584   int position = 0;
6585   if (s->IsFlat() && s->IsOneByteRepresentation()) {
6586     // Try using cached chars where possible.
6587     Object* obj;
6588     { MaybeObject* maybe_obj =
6589           isolate->heap()->AllocateUninitializedFixedArray(length);
6590       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6591     }
6592     elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6593     DisallowHeapAllocation no_gc;
6594     String::FlatContent content = s->GetFlatContent();
6595     if (content.IsAscii()) {
6596       Vector<const uint8_t> chars = content.ToOneByteVector();
6597       // Note, this will initialize all elements (not only the prefix)
6598       // to prevent GC from seeing partially initialized array.
6599       position = CopyCachedAsciiCharsToArray(isolate->heap(),
6600                                              chars.start(),
6601                                              *elements,
6602                                              length);
6603     } else {
6604       MemsetPointer(elements->data_start(),
6605                     isolate->heap()->undefined_value(),
6606                     length);
6607     }
6608   } else {
6609     elements = isolate->factory()->NewFixedArray(length);
6610   }
6611   for (int i = position; i < length; ++i) {
6612     Handle<Object> str =
6613         LookupSingleCharacterStringFromCode(isolate, s->Get(i));
6614     elements->set(i, *str);
6615   }
6616
6617 #ifdef DEBUG
6618   for (int i = 0; i < length; ++i) {
6619     ASSERT(String::cast(elements->get(i))->length() == 1);
6620   }
6621 #endif
6622
6623   return *isolate->factory()->NewJSArrayWithElements(elements);
6624 }
6625
6626
6627 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6628   SealHandleScope shs(isolate);
6629   ASSERT(args.length() == 1);
6630   CONVERT_ARG_CHECKED(String, value, 0);
6631   return value->ToObject();
6632 }
6633
6634
6635 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6636   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6637   int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6638   return char_length == 0;
6639 }
6640
6641
6642 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6643   SealHandleScope shs(isolate);
6644   ASSERT(args.length() == 1);
6645
6646   Object* number = args[0];
6647   RUNTIME_ASSERT(number->IsNumber());
6648
6649   return isolate->heap()->NumberToString(number);
6650 }
6651
6652
6653 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6654   SealHandleScope shs(isolate);
6655   ASSERT(args.length() == 1);
6656
6657   Object* number = args[0];
6658   RUNTIME_ASSERT(number->IsNumber());
6659
6660   return isolate->heap()->NumberToString(
6661       number, false, isolate->heap()->GetPretenureMode());
6662 }
6663
6664
6665 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6666   SealHandleScope shs(isolate);
6667   ASSERT(args.length() == 1);
6668
6669   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6670
6671   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6672   if (number > 0 && number <= Smi::kMaxValue) {
6673     return Smi::FromInt(static_cast<int>(number));
6674   }
6675   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6676 }
6677
6678
6679 // ES6 draft 9.1.11
6680 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) {
6681   SealHandleScope shs(isolate);
6682   ASSERT(args.length() == 1);
6683
6684   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6685
6686   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6687   if (number > 0 && number <= Smi::kMaxValue) {
6688     return Smi::FromInt(static_cast<int>(number));
6689   }
6690   if (number <= 0) {
6691     return Smi::FromInt(0);
6692   }
6693   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6694 }
6695
6696
6697 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6698   SealHandleScope shs(isolate);
6699   ASSERT(args.length() == 1);
6700
6701   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6702
6703   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6704   if (number > 0 && number <= Smi::kMaxValue) {
6705     return Smi::FromInt(static_cast<int>(number));
6706   }
6707
6708   double double_value = DoubleToInteger(number);
6709   // Map both -0 and +0 to +0.
6710   if (double_value == 0) double_value = 0;
6711
6712   return isolate->heap()->NumberFromDouble(double_value);
6713 }
6714
6715
6716 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6717   SealHandleScope shs(isolate);
6718   ASSERT(args.length() == 1);
6719
6720   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6721   return isolate->heap()->NumberFromUint32(number);
6722 }
6723
6724
6725 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6726   SealHandleScope shs(isolate);
6727   ASSERT(args.length() == 1);
6728
6729   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6730
6731   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6732   if (number > 0 && number <= Smi::kMaxValue) {
6733     return Smi::FromInt(static_cast<int>(number));
6734   }
6735   return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6736 }
6737
6738
6739 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
6740 // a small integer.
6741 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6742   SealHandleScope shs(isolate);
6743   ASSERT(args.length() == 1);
6744
6745   Object* obj = args[0];
6746   if (obj->IsSmi()) {
6747     return obj;
6748   }
6749   if (obj->IsHeapNumber()) {
6750     double value = HeapNumber::cast(obj)->value();
6751     int int_value = FastD2I(value);
6752     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6753       return Smi::FromInt(int_value);
6754     }
6755   }
6756   return isolate->heap()->nan_value();
6757 }
6758
6759
6760 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6761   SealHandleScope shs(isolate);
6762   ASSERT(args.length() == 0);
6763   return isolate->heap()->AllocateHeapNumber(0);
6764 }
6765
6766
6767 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6768   SealHandleScope shs(isolate);
6769   ASSERT(args.length() == 2);
6770
6771   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6772   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6773   return isolate->heap()->NumberFromDouble(x + y);
6774 }
6775
6776
6777 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6778   SealHandleScope shs(isolate);
6779   ASSERT(args.length() == 2);
6780
6781   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6782   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6783   return isolate->heap()->NumberFromDouble(x - y);
6784 }
6785
6786
6787 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6788   SealHandleScope shs(isolate);
6789   ASSERT(args.length() == 2);
6790
6791   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6792   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6793   return isolate->heap()->NumberFromDouble(x * y);
6794 }
6795
6796
6797 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6798   SealHandleScope shs(isolate);
6799   ASSERT(args.length() == 1);
6800
6801   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6802   return isolate->heap()->NumberFromDouble(-x);
6803 }
6804
6805
6806 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6807   SealHandleScope shs(isolate);
6808   ASSERT(args.length() == 0);
6809
6810   return isolate->heap()->NumberFromDouble(9876543210.0);
6811 }
6812
6813
6814 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6815   SealHandleScope shs(isolate);
6816   ASSERT(args.length() == 2);
6817
6818   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6819   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6820   return isolate->heap()->NumberFromDouble(x / y);
6821 }
6822
6823
6824 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6825   SealHandleScope shs(isolate);
6826   ASSERT(args.length() == 2);
6827
6828   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6829   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6830
6831   x = modulo(x, y);
6832   // NumberFromDouble may return a Smi instead of a Number object
6833   return isolate->heap()->NumberFromDouble(x);
6834 }
6835
6836
6837 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
6838   SealHandleScope shs(isolate);
6839   ASSERT(args.length() == 2);
6840
6841   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6842   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6843   return isolate->heap()->NumberFromInt32(x * y);
6844 }
6845
6846
6847 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6848   SealHandleScope shs(isolate);
6849   ASSERT(args.length() == 2);
6850   CONVERT_ARG_CHECKED(String, str1, 0);
6851   CONVERT_ARG_CHECKED(String, str2, 1);
6852   isolate->counters()->string_add_runtime()->Increment();
6853   return isolate->heap()->AllocateConsString(str1, str2);
6854 }
6855
6856
6857 template <typename sinkchar>
6858 static inline void StringBuilderConcatHelper(String* special,
6859                                              sinkchar* sink,
6860                                              FixedArray* fixed_array,
6861                                              int array_length) {
6862   int position = 0;
6863   for (int i = 0; i < array_length; i++) {
6864     Object* element = fixed_array->get(i);
6865     if (element->IsSmi()) {
6866       // Smi encoding of position and length.
6867       int encoded_slice = Smi::cast(element)->value();
6868       int pos;
6869       int len;
6870       if (encoded_slice > 0) {
6871         // Position and length encoded in one smi.
6872         pos = StringBuilderSubstringPosition::decode(encoded_slice);
6873         len = StringBuilderSubstringLength::decode(encoded_slice);
6874       } else {
6875         // Position and length encoded in two smis.
6876         Object* obj = fixed_array->get(++i);
6877         ASSERT(obj->IsSmi());
6878         pos = Smi::cast(obj)->value();
6879         len = -encoded_slice;
6880       }
6881       String::WriteToFlat(special,
6882                           sink + position,
6883                           pos,
6884                           pos + len);
6885       position += len;
6886     } else {
6887       String* string = String::cast(element);
6888       int element_length = string->length();
6889       String::WriteToFlat(string, sink + position, 0, element_length);
6890       position += element_length;
6891     }
6892   }
6893 }
6894
6895
6896 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
6897   SealHandleScope shs(isolate);
6898   ASSERT(args.length() == 3);
6899   CONVERT_ARG_CHECKED(JSArray, array, 0);
6900   if (!args[1]->IsSmi()) {
6901     isolate->context()->mark_out_of_memory();
6902     return Failure::OutOfMemoryException(0x14);
6903   }
6904   int array_length = args.smi_at(1);
6905   CONVERT_ARG_CHECKED(String, special, 2);
6906
6907   // This assumption is used by the slice encoding in one or two smis.
6908   ASSERT(Smi::kMaxValue >= String::kMaxLength);
6909
6910   MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
6911   if (maybe_result->IsFailure()) return maybe_result;
6912
6913   int special_length = special->length();
6914   if (!array->HasFastObjectElements()) {
6915     return isolate->Throw(isolate->heap()->illegal_argument_string());
6916   }
6917   FixedArray* fixed_array = FixedArray::cast(array->elements());
6918   if (fixed_array->length() < array_length) {
6919     array_length = fixed_array->length();
6920   }
6921
6922   if (array_length == 0) {
6923     return isolate->heap()->empty_string();
6924   } else if (array_length == 1) {
6925     Object* first = fixed_array->get(0);
6926     if (first->IsString()) return first;
6927   }
6928
6929   bool one_byte = special->HasOnlyOneByteChars();
6930   int position = 0;
6931   for (int i = 0; i < array_length; i++) {
6932     int increment = 0;
6933     Object* elt = fixed_array->get(i);
6934     if (elt->IsSmi()) {
6935       // Smi encoding of position and length.
6936       int smi_value = Smi::cast(elt)->value();
6937       int pos;
6938       int len;
6939       if (smi_value > 0) {
6940         // Position and length encoded in one smi.
6941         pos = StringBuilderSubstringPosition::decode(smi_value);
6942         len = StringBuilderSubstringLength::decode(smi_value);
6943       } else {
6944         // Position and length encoded in two smis.
6945         len = -smi_value;
6946         // Get the position and check that it is a positive smi.
6947         i++;
6948         if (i >= array_length) {
6949           return isolate->Throw(isolate->heap()->illegal_argument_string());
6950         }
6951         Object* next_smi = fixed_array->get(i);
6952         if (!next_smi->IsSmi()) {
6953           return isolate->Throw(isolate->heap()->illegal_argument_string());
6954         }
6955         pos = Smi::cast(next_smi)->value();
6956         if (pos < 0) {
6957           return isolate->Throw(isolate->heap()->illegal_argument_string());
6958         }
6959       }
6960       ASSERT(pos >= 0);
6961       ASSERT(len >= 0);
6962       if (pos > special_length || len > special_length - pos) {
6963         return isolate->Throw(isolate->heap()->illegal_argument_string());
6964       }
6965       increment = len;
6966     } else if (elt->IsString()) {
6967       String* element = String::cast(elt);
6968       int element_length = element->length();
6969       increment = element_length;
6970       if (one_byte && !element->HasOnlyOneByteChars()) {
6971         one_byte = false;
6972       }
6973     } else {
6974       ASSERT(!elt->IsTheHole());
6975       return isolate->Throw(isolate->heap()->illegal_argument_string());
6976     }
6977     if (increment > String::kMaxLength - position) {
6978       isolate->context()->mark_out_of_memory();
6979       return Failure::OutOfMemoryException(0x15);
6980     }
6981     position += increment;
6982   }
6983
6984   int length = position;
6985   Object* object;
6986
6987   if (one_byte) {
6988     { MaybeObject* maybe_object =
6989           isolate->heap()->AllocateRawOneByteString(length);
6990       if (!maybe_object->ToObject(&object)) return maybe_object;
6991     }
6992     SeqOneByteString* answer = SeqOneByteString::cast(object);
6993     StringBuilderConcatHelper(special,
6994                               answer->GetChars(),
6995                               fixed_array,
6996                               array_length);
6997     return answer;
6998   } else {
6999     { MaybeObject* maybe_object =
7000           isolate->heap()->AllocateRawTwoByteString(length);
7001       if (!maybe_object->ToObject(&object)) return maybe_object;
7002     }
7003     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7004     StringBuilderConcatHelper(special,
7005                               answer->GetChars(),
7006                               fixed_array,
7007                               array_length);
7008     return answer;
7009   }
7010 }
7011
7012
7013 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
7014   SealHandleScope shs(isolate);
7015   ASSERT(args.length() == 3);
7016   CONVERT_ARG_CHECKED(JSArray, array, 0);
7017   if (!args[1]->IsSmi()) {
7018     isolate->context()->mark_out_of_memory();
7019     return Failure::OutOfMemoryException(0x16);
7020   }
7021   int array_length = args.smi_at(1);
7022   CONVERT_ARG_CHECKED(String, separator, 2);
7023
7024   if (!array->HasFastObjectElements()) {
7025     return isolate->Throw(isolate->heap()->illegal_argument_string());
7026   }
7027   FixedArray* fixed_array = FixedArray::cast(array->elements());
7028   if (fixed_array->length() < array_length) {
7029     array_length = fixed_array->length();
7030   }
7031
7032   if (array_length == 0) {
7033     return isolate->heap()->empty_string();
7034   } else if (array_length == 1) {
7035     Object* first = fixed_array->get(0);
7036     if (first->IsString()) return first;
7037   }
7038
7039   int separator_length = separator->length();
7040   int max_nof_separators =
7041       (String::kMaxLength + separator_length - 1) / separator_length;
7042   if (max_nof_separators < (array_length - 1)) {
7043       isolate->context()->mark_out_of_memory();
7044       return Failure::OutOfMemoryException(0x17);
7045   }
7046   int length = (array_length - 1) * separator_length;
7047   for (int i = 0; i < array_length; i++) {
7048     Object* element_obj = fixed_array->get(i);
7049     if (!element_obj->IsString()) {
7050       // TODO(1161): handle this case.
7051       return isolate->Throw(isolate->heap()->illegal_argument_string());
7052     }
7053     String* element = String::cast(element_obj);
7054     int increment = element->length();
7055     if (increment > String::kMaxLength - length) {
7056       isolate->context()->mark_out_of_memory();
7057       return Failure::OutOfMemoryException(0x18);
7058     }
7059     length += increment;
7060   }
7061
7062   Object* object;
7063   { MaybeObject* maybe_object =
7064         isolate->heap()->AllocateRawTwoByteString(length);
7065     if (!maybe_object->ToObject(&object)) return maybe_object;
7066   }
7067   SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7068
7069   uc16* sink = answer->GetChars();
7070 #ifdef DEBUG
7071   uc16* end = sink + length;
7072 #endif
7073
7074   String* first = String::cast(fixed_array->get(0));
7075   int first_length = first->length();
7076   String::WriteToFlat(first, sink, 0, first_length);
7077   sink += first_length;
7078
7079   for (int i = 1; i < array_length; i++) {
7080     ASSERT(sink + separator_length <= end);
7081     String::WriteToFlat(separator, sink, 0, separator_length);
7082     sink += separator_length;
7083
7084     String* element = String::cast(fixed_array->get(i));
7085     int element_length = element->length();
7086     ASSERT(sink + element_length <= end);
7087     String::WriteToFlat(element, sink, 0, element_length);
7088     sink += element_length;
7089   }
7090   ASSERT(sink == end);
7091
7092   // Use %_FastAsciiArrayJoin instead.
7093   ASSERT(!answer->IsOneByteRepresentation());
7094   return answer;
7095 }
7096
7097 template <typename Char>
7098 static void JoinSparseArrayWithSeparator(FixedArray* elements,
7099                                          int elements_length,
7100                                          uint32_t array_length,
7101                                          String* separator,
7102                                          Vector<Char> buffer) {
7103   int previous_separator_position = 0;
7104   int separator_length = separator->length();
7105   int cursor = 0;
7106   for (int i = 0; i < elements_length; i += 2) {
7107     int position = NumberToInt32(elements->get(i));
7108     String* string = String::cast(elements->get(i + 1));
7109     int string_length = string->length();
7110     if (string->length() > 0) {
7111       while (previous_separator_position < position) {
7112         String::WriteToFlat<Char>(separator, &buffer[cursor],
7113                                   0, separator_length);
7114         cursor += separator_length;
7115         previous_separator_position++;
7116       }
7117       String::WriteToFlat<Char>(string, &buffer[cursor],
7118                                 0, string_length);
7119       cursor += string->length();
7120     }
7121   }
7122   if (separator_length > 0) {
7123     // Array length must be representable as a signed 32-bit number,
7124     // otherwise the total string length would have been too large.
7125     ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
7126     int last_array_index = static_cast<int>(array_length - 1);
7127     while (previous_separator_position < last_array_index) {
7128       String::WriteToFlat<Char>(separator, &buffer[cursor],
7129                                 0, separator_length);
7130       cursor += separator_length;
7131       previous_separator_position++;
7132     }
7133   }
7134   ASSERT(cursor <= buffer.length());
7135 }
7136
7137
7138 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
7139   SealHandleScope shs(isolate);
7140   ASSERT(args.length() == 3);
7141   CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
7142   RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7143   CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7144   CONVERT_ARG_CHECKED(String, separator, 2);
7145   // elements_array is fast-mode JSarray of alternating positions
7146   // (increasing order) and strings.
7147   // array_length is length of original array (used to add separators);
7148   // separator is string to put between elements. Assumed to be non-empty.
7149
7150   // Find total length of join result.
7151   int string_length = 0;
7152   bool is_ascii = separator->IsOneByteRepresentation();
7153   int max_string_length;
7154   if (is_ascii) {
7155     max_string_length = SeqOneByteString::kMaxLength;
7156   } else {
7157     max_string_length = SeqTwoByteString::kMaxLength;
7158   }
7159   bool overflow = false;
7160   CONVERT_NUMBER_CHECKED(int, elements_length,
7161                          Int32, elements_array->length());
7162   RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7163   FixedArray* elements = FixedArray::cast(elements_array->elements());
7164   for (int i = 0; i < elements_length; i += 2) {
7165     RUNTIME_ASSERT(elements->get(i)->IsNumber());
7166     RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7167     String* string = String::cast(elements->get(i + 1));
7168     int length = string->length();
7169     if (is_ascii && !string->IsOneByteRepresentation()) {
7170       is_ascii = false;
7171       max_string_length = SeqTwoByteString::kMaxLength;
7172     }
7173     if (length > max_string_length ||
7174         max_string_length - length < string_length) {
7175       overflow = true;
7176       break;
7177     }
7178     string_length += length;
7179   }
7180   int separator_length = separator->length();
7181   if (!overflow && separator_length > 0) {
7182     if (array_length <= 0x7fffffffu) {
7183       int separator_count = static_cast<int>(array_length) - 1;
7184       int remaining_length = max_string_length - string_length;
7185       if ((remaining_length / separator_length) >= separator_count) {
7186         string_length += separator_length * (array_length - 1);
7187       } else {
7188         // Not room for the separators within the maximal string length.
7189         overflow = true;
7190       }
7191     } else {
7192       // Nonempty separator and at least 2^31-1 separators necessary
7193       // means that the string is too large to create.
7194       STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7195       overflow = true;
7196     }
7197   }
7198   if (overflow) {
7199     // Throw OutOfMemory exception for creating too large a string.
7200     V8::FatalProcessOutOfMemory("Array join result too large.");
7201   }
7202
7203   if (is_ascii) {
7204     MaybeObject* result_allocation =
7205         isolate->heap()->AllocateRawOneByteString(string_length);
7206     if (result_allocation->IsFailure()) return result_allocation;
7207     SeqOneByteString* result_string =
7208         SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
7209     JoinSparseArrayWithSeparator<uint8_t>(elements,
7210                                           elements_length,
7211                                           array_length,
7212                                           separator,
7213                                           Vector<uint8_t>(
7214                                               result_string->GetChars(),
7215                                               string_length));
7216     return result_string;
7217   } else {
7218     MaybeObject* result_allocation =
7219         isolate->heap()->AllocateRawTwoByteString(string_length);
7220     if (result_allocation->IsFailure()) return result_allocation;
7221     SeqTwoByteString* result_string =
7222         SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7223     JoinSparseArrayWithSeparator<uc16>(elements,
7224                                        elements_length,
7225                                        array_length,
7226                                        separator,
7227                                        Vector<uc16>(result_string->GetChars(),
7228                                                     string_length));
7229     return result_string;
7230   }
7231 }
7232
7233
7234 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7235   SealHandleScope shs(isolate);
7236   ASSERT(args.length() == 2);
7237
7238   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7239   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7240   return isolate->heap()->NumberFromInt32(x | y);
7241 }
7242
7243
7244 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7245   SealHandleScope shs(isolate);
7246   ASSERT(args.length() == 2);
7247
7248   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7249   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7250   return isolate->heap()->NumberFromInt32(x & y);
7251 }
7252
7253
7254 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7255   SealHandleScope shs(isolate);
7256   ASSERT(args.length() == 2);
7257
7258   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7259   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7260   return isolate->heap()->NumberFromInt32(x ^ y);
7261 }
7262
7263
7264 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7265   SealHandleScope shs(isolate);
7266   ASSERT(args.length() == 2);
7267
7268   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7269   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7270   return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7271 }
7272
7273
7274 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7275   SealHandleScope shs(isolate);
7276   ASSERT(args.length() == 2);
7277
7278   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7279   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7280   return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7281 }
7282
7283
7284 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7285   SealHandleScope shs(isolate);
7286   ASSERT(args.length() == 2);
7287
7288   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7289   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7290   return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7291 }
7292
7293
7294 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7295   SealHandleScope shs(isolate);
7296   ASSERT(args.length() == 2);
7297
7298   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7299   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7300   if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7301   if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7302   if (x == y) return Smi::FromInt(EQUAL);
7303   Object* result;
7304   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7305     result = Smi::FromInt(EQUAL);
7306   } else {
7307     result = Smi::FromInt(NOT_EQUAL);
7308   }
7309   return result;
7310 }
7311
7312
7313 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7314   SealHandleScope shs(isolate);
7315   ASSERT(args.length() == 2);
7316
7317   CONVERT_ARG_CHECKED(String, x, 0);
7318   CONVERT_ARG_CHECKED(String, y, 1);
7319
7320   bool not_equal = !x->Equals(y);
7321   // This is slightly convoluted because the value that signifies
7322   // equality is 0 and inequality is 1 so we have to negate the result
7323   // from String::Equals.
7324   ASSERT(not_equal == 0 || not_equal == 1);
7325   STATIC_CHECK(EQUAL == 0);
7326   STATIC_CHECK(NOT_EQUAL == 1);
7327   return Smi::FromInt(not_equal);
7328 }
7329
7330
7331 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7332   SealHandleScope shs(isolate);
7333   ASSERT(args.length() == 3);
7334
7335   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7336   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7337   if (std::isnan(x) || std::isnan(y)) return args[2];
7338   if (x == y) return Smi::FromInt(EQUAL);
7339   if (isless(x, y)) return Smi::FromInt(LESS);
7340   return Smi::FromInt(GREATER);
7341 }
7342
7343
7344 // Compare two Smis as if they were converted to strings and then
7345 // compared lexicographically.
7346 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7347   SealHandleScope shs(isolate);
7348   ASSERT(args.length() == 2);
7349   CONVERT_SMI_ARG_CHECKED(x_value, 0);
7350   CONVERT_SMI_ARG_CHECKED(y_value, 1);
7351
7352   // If the integers are equal so are the string representations.
7353   if (x_value == y_value) return Smi::FromInt(EQUAL);
7354
7355   // If one of the integers is zero the normal integer order is the
7356   // same as the lexicographic order of the string representations.
7357   if (x_value == 0 || y_value == 0)
7358     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7359
7360   // If only one of the integers is negative the negative number is
7361   // smallest because the char code of '-' is less than the char code
7362   // of any digit.  Otherwise, we make both values positive.
7363
7364   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7365   // architectures using 32-bit Smis.
7366   uint32_t x_scaled = x_value;
7367   uint32_t y_scaled = y_value;
7368   if (x_value < 0 || y_value < 0) {
7369     if (y_value >= 0) return Smi::FromInt(LESS);
7370     if (x_value >= 0) return Smi::FromInt(GREATER);
7371     x_scaled = -x_value;
7372     y_scaled = -y_value;
7373   }
7374
7375   static const uint32_t kPowersOf10[] = {
7376     1, 10, 100, 1000, 10*1000, 100*1000,
7377     1000*1000, 10*1000*1000, 100*1000*1000,
7378     1000*1000*1000
7379   };
7380
7381   // If the integers have the same number of decimal digits they can be
7382   // compared directly as the numeric order is the same as the
7383   // lexicographic order.  If one integer has fewer digits, it is scaled
7384   // by some power of 10 to have the same number of digits as the longer
7385   // integer.  If the scaled integers are equal it means the shorter
7386   // integer comes first in the lexicographic order.
7387
7388   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7389   int x_log2 = IntegerLog2(x_scaled);
7390   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7391   x_log10 -= x_scaled < kPowersOf10[x_log10];
7392
7393   int y_log2 = IntegerLog2(y_scaled);
7394   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7395   y_log10 -= y_scaled < kPowersOf10[y_log10];
7396
7397   int tie = EQUAL;
7398
7399   if (x_log10 < y_log10) {
7400     // X has fewer digits.  We would like to simply scale up X but that
7401     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7402     // be scaled up to 9_000_000_000. So we scale up by the next
7403     // smallest power and scale down Y to drop one digit. It is OK to
7404     // drop one digit from the longer integer since the final digit is
7405     // past the length of the shorter integer.
7406     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7407     y_scaled /= 10;
7408     tie = LESS;
7409   } else if (y_log10 < x_log10) {
7410     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7411     x_scaled /= 10;
7412     tie = GREATER;
7413   }
7414
7415   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7416   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7417   return Smi::FromInt(tie);
7418 }
7419
7420
7421 static Object* StringCharacterStreamCompare(RuntimeState* state,
7422                                         String* x,
7423                                         String* y) {
7424   StringCharacterStream stream_x(x, state->string_iterator_compare_x());
7425   StringCharacterStream stream_y(y, state->string_iterator_compare_y());
7426   while (stream_x.HasMore() && stream_y.HasMore()) {
7427     int d = stream_x.GetNext() - stream_y.GetNext();
7428     if (d < 0) return Smi::FromInt(LESS);
7429     else if (d > 0) return Smi::FromInt(GREATER);
7430   }
7431
7432   // x is (non-trivial) prefix of y:
7433   if (stream_y.HasMore()) return Smi::FromInt(LESS);
7434   // y is prefix of x:
7435   return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
7436 }
7437
7438
7439 static Object* FlatStringCompare(String* x, String* y) {
7440   ASSERT(x->IsFlat());
7441   ASSERT(y->IsFlat());
7442   Object* equal_prefix_result = Smi::FromInt(EQUAL);
7443   int prefix_length = x->length();
7444   if (y->length() < prefix_length) {
7445     prefix_length = y->length();
7446     equal_prefix_result = Smi::FromInt(GREATER);
7447   } else if (y->length() > prefix_length) {
7448     equal_prefix_result = Smi::FromInt(LESS);
7449   }
7450   int r;
7451   DisallowHeapAllocation no_gc;
7452   String::FlatContent x_content = x->GetFlatContent();
7453   String::FlatContent y_content = y->GetFlatContent();
7454   if (x_content.IsAscii()) {
7455     Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7456     if (y_content.IsAscii()) {
7457       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7458       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7459     } else {
7460       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7461       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7462     }
7463   } else {
7464     Vector<const uc16> x_chars = x_content.ToUC16Vector();
7465     if (y_content.IsAscii()) {
7466       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7467       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7468     } else {
7469       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7470       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7471     }
7472   }
7473   Object* result;
7474   if (r == 0) {
7475     result = equal_prefix_result;
7476   } else {
7477     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7478   }
7479   ASSERT(result ==
7480       StringCharacterStreamCompare(Isolate::Current()->runtime_state(), x, y));
7481   return result;
7482 }
7483
7484
7485 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7486   SealHandleScope shs(isolate);
7487   ASSERT(args.length() == 2);
7488
7489   CONVERT_ARG_CHECKED(String, x, 0);
7490   CONVERT_ARG_CHECKED(String, y, 1);
7491
7492   isolate->counters()->string_compare_runtime()->Increment();
7493
7494   // A few fast case tests before we flatten.
7495   if (x == y) return Smi::FromInt(EQUAL);
7496   if (y->length() == 0) {
7497     if (x->length() == 0) return Smi::FromInt(EQUAL);
7498     return Smi::FromInt(GREATER);
7499   } else if (x->length() == 0) {
7500     return Smi::FromInt(LESS);
7501   }
7502
7503   int d = x->Get(0) - y->Get(0);
7504   if (d < 0) return Smi::FromInt(LESS);
7505   else if (d > 0) return Smi::FromInt(GREATER);
7506
7507   Object* obj;
7508   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7509     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7510   }
7511   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7512     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7513   }
7514
7515   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7516       : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
7517 }
7518
7519
7520 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7521   SealHandleScope shs(isolate);
7522   ASSERT(args.length() == 1);
7523   isolate->counters()->math_acos()->Increment();
7524
7525   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7526   return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7527 }
7528
7529
7530 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7531   SealHandleScope shs(isolate);
7532   ASSERT(args.length() == 1);
7533   isolate->counters()->math_asin()->Increment();
7534
7535   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7536   return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7537 }
7538
7539
7540 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7541   SealHandleScope shs(isolate);
7542   ASSERT(args.length() == 1);
7543   isolate->counters()->math_atan()->Increment();
7544
7545   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7546   return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7547 }
7548
7549
7550 static const double kPiDividedBy4 = 0.78539816339744830962;
7551
7552
7553 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7554   SealHandleScope shs(isolate);
7555   ASSERT(args.length() == 2);
7556   isolate->counters()->math_atan2()->Increment();
7557
7558   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7559   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7560   double result;
7561   if (std::isinf(x) && std::isinf(y)) {
7562     // Make sure that the result in case of two infinite arguments
7563     // is a multiple of Pi / 4. The sign of the result is determined
7564     // by the first argument (x) and the sign of the second argument
7565     // determines the multiplier: one or three.
7566     int multiplier = (x < 0) ? -1 : 1;
7567     if (y < 0) multiplier *= 3;
7568     result = multiplier * kPiDividedBy4;
7569   } else {
7570     result = atan2(x, y);
7571   }
7572   return isolate->heap()->AllocateHeapNumber(result);
7573 }
7574
7575
7576 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7577   SealHandleScope shs(isolate);
7578   ASSERT(args.length() == 1);
7579   isolate->counters()->math_ceil()->Increment();
7580
7581   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7582   return isolate->heap()->NumberFromDouble(ceiling(x));
7583 }
7584
7585
7586 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7587   SealHandleScope shs(isolate);
7588   ASSERT(args.length() == 1);
7589   isolate->counters()->math_cos()->Increment();
7590
7591   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7592   return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7593 }
7594
7595
7596 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7597   SealHandleScope shs(isolate);
7598   ASSERT(args.length() == 1);
7599   isolate->counters()->math_exp()->Increment();
7600
7601   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7602   lazily_initialize_fast_exp();
7603   return isolate->heap()->NumberFromDouble(fast_exp(x));
7604 }
7605
7606
7607 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7608   SealHandleScope shs(isolate);
7609   ASSERT(args.length() == 1);
7610   isolate->counters()->math_floor()->Increment();
7611
7612   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7613   return isolate->heap()->NumberFromDouble(floor(x));
7614 }
7615
7616
7617 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7618   SealHandleScope shs(isolate);
7619   ASSERT(args.length() == 1);
7620   isolate->counters()->math_log()->Increment();
7621
7622   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7623   return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7624 }
7625
7626
7627 // Slow version of Math.pow.  We check for fast paths for special cases.
7628 // Used if SSE2/VFP3 is not available.
7629 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7630   SealHandleScope shs(isolate);
7631   ASSERT(args.length() == 2);
7632   isolate->counters()->math_pow()->Increment();
7633
7634   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7635
7636   // If the second argument is a smi, it is much faster to call the
7637   // custom powi() function than the generic pow().
7638   if (args[1]->IsSmi()) {
7639     int y = args.smi_at(1);
7640     return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7641   }
7642
7643   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7644   double result = power_helper(x, y);
7645   if (std::isnan(result)) return isolate->heap()->nan_value();
7646   return isolate->heap()->AllocateHeapNumber(result);
7647 }
7648
7649
7650 // Fast version of Math.pow if we know that y is not an integer and y is not
7651 // -0.5 or 0.5.  Used as slow case from full codegen.
7652 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7653   SealHandleScope shs(isolate);
7654   ASSERT(args.length() == 2);
7655   isolate->counters()->math_pow()->Increment();
7656
7657   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7658   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7659   if (y == 0) {
7660     return Smi::FromInt(1);
7661   } else {
7662     double result = power_double_double(x, y);
7663     if (std::isnan(result)) return isolate->heap()->nan_value();
7664     return isolate->heap()->AllocateHeapNumber(result);
7665   }
7666 }
7667
7668
7669 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7670   SealHandleScope shs(isolate);
7671   ASSERT(args.length() == 1);
7672   isolate->counters()->math_round()->Increment();
7673
7674   if (!args[0]->IsHeapNumber()) {
7675     // Must be smi. Return the argument unchanged for all the other types
7676     // to make fuzz-natives test happy.
7677     return args[0];
7678   }
7679
7680   HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7681
7682   double value = number->value();
7683   int exponent = number->get_exponent();
7684   int sign = number->get_sign();
7685
7686   if (exponent < -1) {
7687     // Number in range ]-0.5..0.5[. These always round to +/-zero.
7688     if (sign) return isolate->heap()->minus_zero_value();
7689     return Smi::FromInt(0);
7690   }
7691
7692   // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7693   // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7694   // argument holds for 32-bit smis).
7695   if (!sign && exponent < kSmiValueSize - 2) {
7696     return Smi::FromInt(static_cast<int>(value + 0.5));
7697   }
7698
7699   // If the magnitude is big enough, there's no place for fraction part. If we
7700   // try to add 0.5 to this number, 1.0 will be added instead.
7701   if (exponent >= 52) {
7702     return number;
7703   }
7704
7705   if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7706
7707   // Do not call NumberFromDouble() to avoid extra checks.
7708   return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7709 }
7710
7711
7712 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7713   SealHandleScope shs(isolate);
7714   ASSERT(args.length() == 1);
7715   isolate->counters()->math_sin()->Increment();
7716
7717   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7718   return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7719 }
7720
7721
7722 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7723   SealHandleScope shs(isolate);
7724   ASSERT(args.length() == 1);
7725   isolate->counters()->math_sqrt()->Increment();
7726
7727   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7728   return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7729 }
7730
7731
7732 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7733   SealHandleScope shs(isolate);
7734   ASSERT(args.length() == 1);
7735   isolate->counters()->math_tan()->Increment();
7736
7737   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7738   return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7739 }
7740
7741
7742 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7743   SealHandleScope shs(isolate);
7744   ASSERT(args.length() == 2);
7745
7746   CONVERT_SMI_ARG_CHECKED(year, 0);
7747   CONVERT_SMI_ARG_CHECKED(month, 1);
7748
7749   return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7750 }
7751
7752
7753 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7754   HandleScope scope(isolate);
7755   ASSERT(args.length() == 3);
7756
7757   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7758   CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7759   CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7760
7761   DateCache* date_cache = isolate->date_cache();
7762
7763   Object* value = NULL;
7764   bool is_value_nan = false;
7765   if (std::isnan(time)) {
7766     value = isolate->heap()->nan_value();
7767     is_value_nan = true;
7768   } else if (!is_utc &&
7769              (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7770               time > DateCache::kMaxTimeBeforeUTCInMs)) {
7771     value = isolate->heap()->nan_value();
7772     is_value_nan = true;
7773   } else {
7774     time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7775     if (time < -DateCache::kMaxTimeInMs ||
7776         time > DateCache::kMaxTimeInMs) {
7777       value = isolate->heap()->nan_value();
7778       is_value_nan = true;
7779     } else  {
7780       MaybeObject* maybe_result =
7781           isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7782       if (!maybe_result->ToObject(&value)) return maybe_result;
7783     }
7784   }
7785   date->SetValue(value, is_value_nan);
7786   return value;
7787 }
7788
7789
7790 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7791   HandleScope scope(isolate);
7792   ASSERT(args.length() == 3);
7793
7794   Handle<JSFunction> callee = args.at<JSFunction>(0);
7795   Object** parameters = reinterpret_cast<Object**>(args[1]);
7796   const int argument_count = Smi::cast(args[2])->value();
7797
7798   Handle<JSObject> result =
7799       isolate->factory()->NewArgumentsObject(callee, argument_count);
7800   // Allocate the elements if needed.
7801   int parameter_count = callee->shared()->formal_parameter_count();
7802   if (argument_count > 0) {
7803     if (parameter_count > 0) {
7804       int mapped_count = Min(argument_count, parameter_count);
7805       Handle<FixedArray> parameter_map =
7806           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7807       parameter_map->set_map(
7808           isolate->heap()->non_strict_arguments_elements_map());
7809
7810       Handle<Map> old_map(result->map());
7811       Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
7812       new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7813
7814       result->set_map(*new_map);
7815       result->set_elements(*parameter_map);
7816
7817       // Store the context and the arguments array at the beginning of the
7818       // parameter map.
7819       Handle<Context> context(isolate->context());
7820       Handle<FixedArray> arguments =
7821           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7822       parameter_map->set(0, *context);
7823       parameter_map->set(1, *arguments);
7824
7825       // Loop over the actual parameters backwards.
7826       int index = argument_count - 1;
7827       while (index >= mapped_count) {
7828         // These go directly in the arguments array and have no
7829         // corresponding slot in the parameter map.
7830         arguments->set(index, *(parameters - index - 1));
7831         --index;
7832       }
7833
7834       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7835       while (index >= 0) {
7836         // Detect duplicate names to the right in the parameter list.
7837         Handle<String> name(scope_info->ParameterName(index));
7838         int context_local_count = scope_info->ContextLocalCount();
7839         bool duplicate = false;
7840         for (int j = index + 1; j < parameter_count; ++j) {
7841           if (scope_info->ParameterName(j) == *name) {
7842             duplicate = true;
7843             break;
7844           }
7845         }
7846
7847         if (duplicate) {
7848           // This goes directly in the arguments array with a hole in the
7849           // parameter map.
7850           arguments->set(index, *(parameters - index - 1));
7851           parameter_map->set_the_hole(index + 2);
7852         } else {
7853           // The context index goes in the parameter map with a hole in the
7854           // arguments array.
7855           int context_index = -1;
7856           for (int j = 0; j < context_local_count; ++j) {
7857             if (scope_info->ContextLocalName(j) == *name) {
7858               context_index = j;
7859               break;
7860             }
7861           }
7862           ASSERT(context_index >= 0);
7863           arguments->set_the_hole(index);
7864           parameter_map->set(index + 2, Smi::FromInt(
7865               Context::MIN_CONTEXT_SLOTS + context_index));
7866         }
7867
7868         --index;
7869       }
7870     } else {
7871       // If there is no aliasing, the arguments object elements are not
7872       // special in any way.
7873       Handle<FixedArray> elements =
7874           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7875       result->set_elements(*elements);
7876       for (int i = 0; i < argument_count; ++i) {
7877         elements->set(i, *(parameters - i - 1));
7878       }
7879     }
7880   }
7881   return *result;
7882 }
7883
7884
7885 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7886   SealHandleScope shs(isolate);
7887   ASSERT(args.length() == 3);
7888
7889   JSFunction* callee = JSFunction::cast(args[0]);
7890   Object** parameters = reinterpret_cast<Object**>(args[1]);
7891   const int length = args.smi_at(2);
7892
7893   Object* result;
7894   { MaybeObject* maybe_result =
7895         isolate->heap()->AllocateArgumentsObject(callee, length);
7896     if (!maybe_result->ToObject(&result)) return maybe_result;
7897   }
7898   // Allocate the elements if needed.
7899   if (length > 0) {
7900     // Allocate the fixed array.
7901     Object* obj;
7902     { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7903       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7904     }
7905
7906     DisallowHeapAllocation no_gc;
7907     FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7908     array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
7909     array->set_length(length);
7910
7911     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7912     for (int i = 0; i < length; i++) {
7913       array->set(i, *--parameters, mode);
7914     }
7915     JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7916   }
7917   return result;
7918 }
7919
7920
7921 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7922   HandleScope scope(isolate);
7923   ASSERT(args.length() == 3);
7924   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
7925   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
7926   CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
7927
7928   // The caller ensures that we pretenure closures that are assigned
7929   // directly to properties.
7930   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7931   Handle<JSFunction> result =
7932       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7933                                                             context,
7934                                                             pretenure_flag);
7935   return *result;
7936 }
7937
7938
7939 // Find the arguments of the JavaScript function invocation that called
7940 // into C++ code. Collect these in a newly allocated array of handles (possibly
7941 // prefixed by a number of empty handles).
7942 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
7943     Isolate* isolate,
7944     int prefix_argc,
7945     int* total_argc) {
7946   // Find frame containing arguments passed to the caller.
7947   JavaScriptFrameIterator it(isolate);
7948   JavaScriptFrame* frame = it.frame();
7949   List<JSFunction*> functions(2);
7950   frame->GetFunctions(&functions);
7951   if (functions.length() > 1) {
7952     int inlined_jsframe_index = functions.length() - 1;
7953     JSFunction* inlined_function = functions[inlined_jsframe_index];
7954     Vector<SlotRef> args_slots =
7955         SlotRef::ComputeSlotMappingForArguments(
7956             frame,
7957             inlined_jsframe_index,
7958             inlined_function->shared()->formal_parameter_count());
7959
7960     int args_count = args_slots.length();
7961
7962     *total_argc = prefix_argc + args_count;
7963     SmartArrayPointer<Handle<Object> > param_data(
7964         NewArray<Handle<Object> >(*total_argc));
7965     for (int i = 0; i < args_count; i++) {
7966       Handle<Object> val = args_slots[i].GetValue(isolate);
7967       param_data[prefix_argc + i] = val;
7968     }
7969
7970     args_slots.Dispose();
7971
7972     return param_data;
7973   } else {
7974     it.AdvanceToArgumentsFrame();
7975     frame = it.frame();
7976     int args_count = frame->ComputeParametersCount();
7977
7978     *total_argc = prefix_argc + args_count;
7979     SmartArrayPointer<Handle<Object> > param_data(
7980         NewArray<Handle<Object> >(*total_argc));
7981     for (int i = 0; i < args_count; i++) {
7982       Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
7983       param_data[prefix_argc + i] = val;
7984     }
7985     return param_data;
7986   }
7987 }
7988
7989
7990 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
7991   HandleScope scope(isolate);
7992   ASSERT(args.length() == 4);
7993   CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
7994   RUNTIME_ASSERT(args[3]->IsNumber());
7995   Handle<Object> bindee = args.at<Object>(1);
7996
7997   // TODO(lrn): Create bound function in C++ code from premade shared info.
7998   bound_function->shared()->set_bound(true);
7999   // Get all arguments of calling function (Function.prototype.bind).
8000   int argc = 0;
8001   SmartArrayPointer<Handle<Object> > arguments =
8002       GetCallerArguments(isolate, 0, &argc);
8003   // Don't count the this-arg.
8004   if (argc > 0) {
8005     ASSERT(*arguments[0] == args[2]);
8006     argc--;
8007   } else {
8008     ASSERT(args[2]->IsUndefined());
8009   }
8010   // Initialize array of bindings (function, this, and any existing arguments
8011   // if the function was already bound).
8012   Handle<FixedArray> new_bindings;
8013   int i;
8014   if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8015     Handle<FixedArray> old_bindings(
8016         JSFunction::cast(*bindee)->function_bindings());
8017     new_bindings =
8018         isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8019     bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8020                             isolate);
8021     i = 0;
8022     for (int n = old_bindings->length(); i < n; i++) {
8023       new_bindings->set(i, old_bindings->get(i));
8024     }
8025   } else {
8026     int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8027     new_bindings = isolate->factory()->NewFixedArray(array_size);
8028     new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8029     new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
8030     i = 2;
8031   }
8032   // Copy arguments, skipping the first which is "this_arg".
8033   for (int j = 0; j < argc; j++, i++) {
8034     new_bindings->set(i, *arguments[j + 1]);
8035   }
8036   new_bindings->set_map_no_write_barrier(
8037       isolate->heap()->fixed_cow_array_map());
8038   bound_function->set_function_bindings(*new_bindings);
8039
8040   // Update length.
8041   Handle<String> length_string = isolate->factory()->length_string();
8042   Handle<Object> new_length(args.at<Object>(3));
8043   PropertyAttributes attr =
8044       static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8045   ForceSetProperty(bound_function, length_string, new_length, attr);
8046   return *bound_function;
8047 }
8048
8049
8050 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
8051   HandleScope handles(isolate);
8052   ASSERT(args.length() == 1);
8053   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8054   if (callable->IsJSFunction()) {
8055     Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8056     if (function->shared()->bound()) {
8057       Handle<FixedArray> bindings(function->function_bindings());
8058       ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8059       return *isolate->factory()->NewJSArrayWithElements(bindings);
8060     }
8061   }
8062   return isolate->heap()->undefined_value();
8063 }
8064
8065
8066 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
8067   HandleScope scope(isolate);
8068   ASSERT(args.length() == 1);
8069   // First argument is a function to use as a constructor.
8070   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8071   RUNTIME_ASSERT(function->shared()->bound());
8072
8073   // The argument is a bound function. Extract its bound arguments
8074   // and callable.
8075   Handle<FixedArray> bound_args =
8076       Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8077   int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8078   Handle<Object> bound_function(
8079       JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
8080       isolate);
8081   ASSERT(!bound_function->IsJSFunction() ||
8082          !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8083
8084   int total_argc = 0;
8085   SmartArrayPointer<Handle<Object> > param_data =
8086       GetCallerArguments(isolate, bound_argc, &total_argc);
8087   for (int i = 0; i < bound_argc; i++) {
8088     param_data[i] = Handle<Object>(bound_args->get(
8089         JSFunction::kBoundArgumentsStartIndex + i), isolate);
8090   }
8091
8092   if (!bound_function->IsJSFunction()) {
8093     bool exception_thrown;
8094     bound_function = Execution::TryGetConstructorDelegate(bound_function,
8095                                                           &exception_thrown);
8096     if (exception_thrown) return Failure::Exception();
8097   }
8098   ASSERT(bound_function->IsJSFunction());
8099
8100   bool exception = false;
8101   Handle<Object> result =
8102       Execution::New(Handle<JSFunction>::cast(bound_function),
8103                      total_argc, *param_data, &exception);
8104   if (exception) {
8105     return Failure::Exception();
8106   }
8107   ASSERT(!result.is_null());
8108   return *result;
8109 }
8110
8111
8112 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
8113   HandleScope scope(isolate);
8114   ASSERT(args.length() == 1);
8115
8116   Handle<Object> constructor = args.at<Object>(0);
8117
8118   // If the constructor isn't a proper function we throw a type error.
8119   if (!constructor->IsJSFunction()) {
8120     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8121     Handle<Object> type_error =
8122         isolate->factory()->NewTypeError("not_constructor", arguments);
8123     return isolate->Throw(*type_error);
8124   }
8125
8126   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8127
8128   // If function should not have prototype, construction is not allowed. In this
8129   // case generated code bailouts here, since function has no initial_map.
8130   if (!function->should_have_prototype() && !function->shared()->bound()) {
8131     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8132     Handle<Object> type_error =
8133         isolate->factory()->NewTypeError("not_constructor", arguments);
8134     return isolate->Throw(*type_error);
8135   }
8136
8137 #ifdef ENABLE_DEBUGGER_SUPPORT
8138   Debug* debug = isolate->debug();
8139   // Handle stepping into constructors if step into is active.
8140   if (debug->StepInActive()) {
8141     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8142   }
8143 #endif
8144
8145   if (function->has_initial_map()) {
8146     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8147       // The 'Function' function ignores the receiver object when
8148       // called using 'new' and creates a new JSFunction object that
8149       // is returned.  The receiver object is only used for error
8150       // reporting if an error occurs when constructing the new
8151       // JSFunction. Factory::NewJSObject() should not be used to
8152       // allocate JSFunctions since it does not properly initialize
8153       // the shared part of the function. Since the receiver is
8154       // ignored anyway, we use the global object as the receiver
8155       // instead of a new JSFunction object. This way, errors are
8156       // reported the same way whether or not 'Function' is called
8157       // using 'new'.
8158       return isolate->context()->global_object();
8159     }
8160   }
8161
8162   // The function should be compiled for the optimization hints to be
8163   // available.
8164   JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
8165
8166   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8167   if (!function->has_initial_map() &&
8168       shared->IsInobjectSlackTrackingInProgress()) {
8169     // The tracking is already in progress for another function. We can only
8170     // track one initial_map at a time, so we force the completion before the
8171     // function is called as a constructor for the first time.
8172     shared->CompleteInobjectSlackTracking();
8173   }
8174
8175   Handle<JSObject> result = isolate->factory()->NewJSObject(function);
8176   RETURN_IF_EMPTY_HANDLE(isolate, result);
8177
8178   isolate->counters()->constructed_objects()->Increment();
8179   isolate->counters()->constructed_objects_runtime()->Increment();
8180
8181   return *result;
8182 }
8183
8184
8185 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8186   HandleScope scope(isolate);
8187   ASSERT(args.length() == 1);
8188
8189   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8190   function->shared()->CompleteInobjectSlackTracking();
8191
8192   return isolate->heap()->undefined_value();
8193 }
8194
8195
8196 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8197   HandleScope scope(isolate);
8198   ASSERT(args.length() == 1);
8199
8200   Handle<JSFunction> function = args.at<JSFunction>(0);
8201 #ifdef DEBUG
8202   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8203     PrintF("[lazy: ");
8204     function->PrintName();
8205     PrintF("]\n");
8206   }
8207 #endif
8208
8209   // Compile the target function.
8210   ASSERT(!function->is_compiled());
8211   if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8212     return Failure::Exception();
8213   }
8214
8215   // All done. Return the compiled code.
8216   ASSERT(function->is_compiled());
8217   return function->code();
8218 }
8219
8220
8221 bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
8222   // If the function is not compiled ignore the lazy
8223   // recompilation. This can happen if the debugger is activated and
8224   // the function is returned to the not compiled state.
8225   if (!function->shared()->is_compiled()) return false;
8226
8227   // If the function is not optimizable or debugger is active continue using the
8228   // code from the full compiler.
8229   if (!FLAG_crankshaft ||
8230       function->shared()->optimization_disabled() ||
8231       isolate->DebuggerHasBreakPoints()) {
8232     if (FLAG_trace_opt) {
8233       PrintF("[failed to optimize ");
8234       function->PrintName();
8235       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8236           function->shared()->optimization_disabled() ? "F" : "T",
8237           isolate->DebuggerHasBreakPoints() ? "T" : "F");
8238     }
8239     return false;
8240   }
8241   return true;
8242 }
8243
8244
8245 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8246   HandleScope scope(isolate);
8247   ASSERT(args.length() == 1);
8248   Handle<JSFunction> function = args.at<JSFunction>(0);
8249
8250   if (!AllowOptimization(isolate, function)) {
8251     function->ReplaceCode(function->shared()->code());
8252     return function->code();
8253   }
8254   function->shared()->code()->set_profiler_ticks(0);
8255   if (JSFunction::CompileOptimized(function,
8256                                    BailoutId::None(),
8257                                    CLEAR_EXCEPTION)) {
8258     return function->code();
8259   }
8260   if (FLAG_trace_opt) {
8261     PrintF("[failed to optimize ");
8262     function->PrintName();
8263     PrintF(": optimized compilation failed]\n");
8264   }
8265   function->ReplaceCode(function->shared()->code());
8266   return function->code();
8267 }
8268
8269
8270 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) {
8271   HandleScope handle_scope(isolate);
8272   ASSERT(args.length() == 1);
8273   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8274   if (!AllowOptimization(isolate, function)) {
8275     function->ReplaceCode(function->shared()->code());
8276     return isolate->heap()->undefined_value();
8277   }
8278   function->shared()->code()->set_profiler_ticks(0);
8279   ASSERT(FLAG_parallel_recompilation);
8280   Compiler::RecompileParallel(function);
8281   return isolate->heap()->undefined_value();
8282 }
8283
8284
8285 RUNTIME_FUNCTION(MaybeObject*, Runtime_InstallRecompiledCode) {
8286   HandleScope handle_scope(isolate);
8287   ASSERT(args.length() == 1);
8288   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8289   ASSERT(V8::UseCrankshaft() && FLAG_parallel_recompilation);
8290   isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8291   return function->code();
8292 }
8293
8294
8295 class ActivationsFinder : public ThreadVisitor {
8296  public:
8297   explicit ActivationsFinder(JSFunction* function)
8298       : function_(function), has_activations_(false) {}
8299
8300   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8301     if (has_activations_) return;
8302
8303     for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
8304       JavaScriptFrame* frame = it.frame();
8305       if (frame->is_optimized() && frame->function() == function_) {
8306         has_activations_ = true;
8307         return;
8308       }
8309     }
8310   }
8311
8312   bool has_activations() { return has_activations_; }
8313
8314  private:
8315   JSFunction* function_;
8316   bool has_activations_;
8317 };
8318
8319
8320 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyStubFailure) {
8321   HandleScope scope(isolate);
8322   ASSERT(args.length() == 0);
8323   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8324   ASSERT(AllowHeapAllocation::IsAllowed());
8325   delete deoptimizer;
8326   return isolate->heap()->undefined_value();
8327 }
8328
8329
8330 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8331   HandleScope scope(isolate);
8332   ASSERT(args.length() == 1);
8333   RUNTIME_ASSERT(args[0]->IsSmi());
8334   Deoptimizer::BailoutType type =
8335       static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8336   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8337   ASSERT(AllowHeapAllocation::IsAllowed());
8338
8339   ASSERT(deoptimizer->compiled_code_kind() == Code::OPTIMIZED_FUNCTION);
8340
8341   // Make sure to materialize objects before causing any allocation.
8342   JavaScriptFrameIterator it(isolate);
8343   deoptimizer->MaterializeHeapObjects(&it);
8344   delete deoptimizer;
8345
8346   JavaScriptFrame* frame = it.frame();
8347   RUNTIME_ASSERT(frame->function()->IsJSFunction());
8348   Handle<JSFunction> function(frame->function(), isolate);
8349   Handle<Code> optimized_code(function->code());
8350   RUNTIME_ASSERT((type != Deoptimizer::EAGER &&
8351                   type != Deoptimizer::SOFT) || function->IsOptimized());
8352
8353   // Avoid doing too much work when running with --always-opt and keep
8354   // the optimized code around.
8355   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8356     return isolate->heap()->undefined_value();
8357   }
8358
8359   // Find other optimized activations of the function or functions that
8360   // share the same optimized code.
8361   bool has_other_activations = false;
8362   while (!it.done()) {
8363     JavaScriptFrame* frame = it.frame();
8364     JSFunction* other_function = frame->function();
8365     if (frame->is_optimized() && other_function->code() == function->code()) {
8366       has_other_activations = true;
8367       break;
8368     }
8369     it.Advance();
8370   }
8371
8372   if (!has_other_activations) {
8373     ActivationsFinder activations_finder(*function);
8374     isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8375     has_other_activations = activations_finder.has_activations();
8376   }
8377
8378   if (!has_other_activations) {
8379     if (FLAG_trace_deopt) {
8380       PrintF("[removing optimized code for: ");
8381       function->PrintName();
8382       PrintF("]\n");
8383     }
8384     function->ReplaceCode(function->shared()->code());
8385   } else {
8386     Deoptimizer::DeoptimizeFunction(*function);
8387   }
8388   // Evict optimized code for this function from the cache so that it doesn't
8389   // get used for new closures.
8390   function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8391                                                 "notify deoptimized");
8392
8393   return isolate->heap()->undefined_value();
8394 }
8395
8396
8397 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
8398   SealHandleScope shs(isolate);
8399   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8400   delete deoptimizer;
8401   return isolate->heap()->undefined_value();
8402 }
8403
8404
8405 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8406   HandleScope scope(isolate);
8407   ASSERT(args.length() == 1);
8408   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8409   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8410
8411   Deoptimizer::DeoptimizeFunction(*function);
8412
8413   return isolate->heap()->undefined_value();
8414 }
8415
8416
8417 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8418   HandleScope scope(isolate);
8419   ASSERT(args.length() == 1);
8420   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8421   Code* unoptimized = function->shared()->code();
8422   if (unoptimized->kind() == Code::FUNCTION) {
8423     unoptimized->ClearInlineCaches();
8424     unoptimized->ClearTypeFeedbackCells(isolate->heap());
8425   }
8426   return isolate->heap()->undefined_value();
8427 }
8428
8429
8430 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8431   SealHandleScope shs(isolate);
8432 #if defined(USE_SIMULATOR)
8433   return isolate->heap()->true_value();
8434 #else
8435   return isolate->heap()->false_value();
8436 #endif
8437 }
8438
8439
8440 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsParallelRecompilationSupported) {
8441   HandleScope scope(isolate);
8442   return FLAG_parallel_recompilation
8443       ? isolate->heap()->true_value() : isolate->heap()->false_value();
8444 }
8445
8446
8447 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8448   HandleScope scope(isolate);
8449   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8450   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8451
8452   if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8453   function->MarkForLazyRecompilation();
8454
8455   Code* unoptimized = function->shared()->code();
8456   if (args.length() == 2 &&
8457       unoptimized->kind() == Code::FUNCTION) {
8458     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8459     if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
8460       for (int i = 0; i <= Code::kMaxLoopNestingMarker; i++) {
8461         unoptimized->set_allow_osr_at_loop_nesting_level(i);
8462         isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8463       }
8464     } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("parallel"))) {
8465       function->MarkForParallelRecompilation();
8466     }
8467   }
8468
8469   return isolate->heap()->undefined_value();
8470 }
8471
8472
8473 RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
8474   HandleScope scope(isolate);
8475   ASSERT(args.length() == 1);
8476   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8477   ASSERT(!function->IsOptimized());
8478   function->shared()->set_optimization_disabled(true);
8479   return isolate->heap()->undefined_value();
8480 }
8481
8482
8483 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8484   HandleScope scope(isolate);
8485   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8486   if (!V8::UseCrankshaft()) {
8487     return Smi::FromInt(4);  // 4 == "never".
8488   }
8489   bool sync_with_compiler_thread = true;
8490   if (args.length() == 2) {
8491     CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
8492     if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
8493       sync_with_compiler_thread = false;
8494     }
8495   }
8496   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8497   if (FLAG_parallel_recompilation && sync_with_compiler_thread) {
8498     while (function->IsInRecompileQueue() ||
8499            function->IsMarkedForInstallingRecompiledCode()) {
8500       isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8501       OS::Sleep(50);
8502     }
8503   }
8504   if (FLAG_always_opt) {
8505     // We may have always opt, but that is more best-effort than a real
8506     // promise, so we still say "no" if it is not optimized.
8507     return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8508                                    : Smi::FromInt(2);  // 2 == "no".
8509   }
8510   if (FLAG_deopt_every_n_times) {
8511     return Smi::FromInt(6);  // 6 == "maybe deopted".
8512   }
8513   return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8514                                  : Smi::FromInt(2);  // 2 == "no".
8515 }
8516
8517
8518 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8519   HandleScope scope(isolate);
8520   ASSERT(args.length() == 1);
8521   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8522   return Smi::FromInt(function->shared()->opt_count());
8523 }
8524
8525
8526 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8527   HandleScope scope(isolate);
8528   ASSERT(args.length() == 1);
8529   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8530
8531   // We're not prepared to handle a function with arguments object.
8532   ASSERT(!function->shared()->uses_arguments());
8533
8534   // We have hit a back edge in an unoptimized frame for a function that was
8535   // selected for on-stack replacement.  Find the unoptimized code object.
8536   Handle<Code> unoptimized(function->shared()->code(), isolate);
8537   // Keep track of whether we've succeeded in optimizing.
8538   bool succeeded = unoptimized->optimizable();
8539   if (succeeded) {
8540     // If we are trying to do OSR when there are already optimized
8541     // activations of the function, it means (a) the function is directly or
8542     // indirectly recursive and (b) an optimized invocation has been
8543     // deoptimized so that we are currently in an unoptimized activation.
8544     // Check for optimized activations of this function.
8545     JavaScriptFrameIterator it(isolate);
8546     while (succeeded && !it.done()) {
8547       JavaScriptFrame* frame = it.frame();
8548       succeeded = !frame->is_optimized() || frame->function() != *function;
8549       it.Advance();
8550     }
8551   }
8552
8553   BailoutId ast_id = BailoutId::None();
8554   if (succeeded) {
8555     // The top JS function is this one, the PC is somewhere in the
8556     // unoptimized code.
8557     JavaScriptFrameIterator it(isolate);
8558     JavaScriptFrame* frame = it.frame();
8559     ASSERT(frame->function() == *function);
8560     ASSERT(frame->LookupCode() == *unoptimized);
8561     ASSERT(unoptimized->contains(frame->pc()));
8562
8563     // Use linear search of the unoptimized code's back edge table to find
8564     // the AST id matching the PC.
8565     uint32_t target_pc_offset =
8566       static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
8567     uint32_t loop_depth = 0;
8568
8569     for (FullCodeGenerator::BackEdgeTableIterator back_edges(*unoptimized);
8570          !back_edges.Done();
8571          back_edges.Next()) {
8572       if (back_edges.pc_offset() == target_pc_offset) {
8573         ast_id = back_edges.ast_id();
8574         loop_depth = back_edges.loop_depth();
8575         break;
8576       }
8577     }
8578     ASSERT(!ast_id.IsNone());
8579
8580     if (FLAG_trace_osr) {
8581       PrintF("[replacing on-stack at AST id %d, loop depth %d in ",
8582               ast_id.ToInt(), loop_depth);
8583       function->PrintName();
8584       PrintF("]\n");
8585     }
8586
8587     // Try to compile the optimized code.  A true return value from
8588     // CompileOptimized means that compilation succeeded, not necessarily
8589     // that optimization succeeded.
8590     if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
8591         function->IsOptimized()) {
8592       DeoptimizationInputData* data = DeoptimizationInputData::cast(
8593           function->code()->deoptimization_data());
8594       if (data->OsrPcOffset()->value() >= 0) {
8595         if (FLAG_trace_osr) {
8596           PrintF("[on-stack replacement offset %d in optimized code]\n",
8597                data->OsrPcOffset()->value());
8598         }
8599         ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8600       } else {
8601         // We may never generate the desired OSR entry if we emit an
8602         // early deoptimize.
8603         succeeded = false;
8604       }
8605     } else {
8606       succeeded = false;
8607     }
8608   }
8609
8610   // Revert to the original interrupt calls in the original unoptimized code.
8611   if (FLAG_trace_osr) {
8612     PrintF("[restoring original interrupt calls in ");
8613     function->PrintName();
8614     PrintF("]\n");
8615   }
8616   InterruptStub interrupt_stub;
8617   Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate);
8618   Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
8619   Deoptimizer::RevertInterruptCode(*unoptimized,
8620                                    *interrupt_code,
8621                                    *replacement_code);
8622
8623   // If the optimization attempt succeeded, return the AST id tagged as a
8624   // smi. This tells the builtin that we need to translate the unoptimized
8625   // frame to an optimized one.
8626   if (succeeded) {
8627     ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
8628     return Smi::FromInt(ast_id.ToInt());
8629   } else {
8630     if (function->IsMarkedForLazyRecompilation()) {
8631       function->ReplaceCode(function->shared()->code());
8632     }
8633     return Smi::FromInt(-1);
8634   }
8635 }
8636
8637
8638 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8639   SealHandleScope shs(isolate);
8640   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8641   return isolate->heap()->undefined_value();
8642 }
8643
8644
8645 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8646   SealHandleScope shs(isolate);
8647   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8648   return isolate->heap()->nan_value();
8649 }
8650
8651
8652 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8653   HandleScope scope(isolate);
8654   ASSERT(args.length() >= 2);
8655   int argc = args.length() - 2;
8656   CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8657   Object* receiver = args[0];
8658
8659   // If there are too many arguments, allocate argv via malloc.
8660   const int argv_small_size = 10;
8661   Handle<Object> argv_small_buffer[argv_small_size];
8662   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8663   Handle<Object>* argv = argv_small_buffer;
8664   if (argc > argv_small_size) {
8665     argv = new Handle<Object>[argc];
8666     if (argv == NULL) return isolate->StackOverflow();
8667     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8668   }
8669
8670   for (int i = 0; i < argc; ++i) {
8671      MaybeObject* maybe = args[1 + i];
8672      Object* object;
8673      if (!maybe->To<Object>(&object)) return maybe;
8674      argv[i] = Handle<Object>(object, isolate);
8675   }
8676
8677   bool threw;
8678   Handle<JSReceiver> hfun(fun);
8679   Handle<Object> hreceiver(receiver, isolate);
8680   Handle<Object> result =
8681       Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
8682
8683   if (threw) return Failure::Exception();
8684   return *result;
8685 }
8686
8687
8688 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8689   HandleScope scope(isolate);
8690   ASSERT(args.length() == 5);
8691   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8692   Handle<Object> receiver = args.at<Object>(1);
8693   CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8694   CONVERT_SMI_ARG_CHECKED(offset, 3);
8695   CONVERT_SMI_ARG_CHECKED(argc, 4);
8696   RUNTIME_ASSERT(offset >= 0);
8697   RUNTIME_ASSERT(argc >= 0);
8698
8699   // If there are too many arguments, allocate argv via malloc.
8700   const int argv_small_size = 10;
8701   Handle<Object> argv_small_buffer[argv_small_size];
8702   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8703   Handle<Object>* argv = argv_small_buffer;
8704   if (argc > argv_small_size) {
8705     argv = new Handle<Object>[argc];
8706     if (argv == NULL) return isolate->StackOverflow();
8707     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8708   }
8709
8710   for (int i = 0; i < argc; ++i) {
8711     argv[i] = Object::GetElement(arguments, offset + i);
8712   }
8713
8714   bool threw;
8715   Handle<Object> result =
8716       Execution::Call(fun, receiver, argc, argv, &threw, true);
8717
8718   if (threw) return Failure::Exception();
8719   return *result;
8720 }
8721
8722
8723 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8724   HandleScope scope(isolate);
8725   ASSERT(args.length() == 1);
8726   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8727   return *Execution::GetFunctionDelegate(args.at<Object>(0));
8728 }
8729
8730
8731 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8732   HandleScope scope(isolate);
8733   ASSERT(args.length() == 1);
8734   RUNTIME_ASSERT(!args[0]->IsJSFunction());
8735   return *Execution::GetConstructorDelegate(args.at<Object>(0));
8736 }
8737
8738
8739 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
8740   SealHandleScope shs(isolate);
8741   ASSERT(args.length() == 2);
8742
8743   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8744   CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
8745   Context* result;
8746   MaybeObject* maybe_result =
8747       isolate->heap()->AllocateGlobalContext(function, scope_info);
8748   if (!maybe_result->To(&result)) return maybe_result;
8749
8750   ASSERT(function->context() == isolate->context());
8751   ASSERT(function->context()->global_object() == result->global_object());
8752   isolate->set_context(result);
8753   result->global_object()->set_global_context(result);
8754
8755   return result;  // non-failure
8756 }
8757
8758
8759 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8760   SealHandleScope shs(isolate);
8761   ASSERT(args.length() == 1);
8762
8763   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8764   int length = function->shared()->scope_info()->ContextLength();
8765   Context* result;
8766   MaybeObject* maybe_result =
8767       isolate->heap()->AllocateFunctionContext(length, function);
8768   if (!maybe_result->To(&result)) return maybe_result;
8769
8770   isolate->set_context(result);
8771
8772   return result;  // non-failure
8773 }
8774
8775
8776 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8777   SealHandleScope shs(isolate);
8778   ASSERT(args.length() == 2);
8779   JSReceiver* extension_object;
8780   if (args[0]->IsJSReceiver()) {
8781     extension_object = JSReceiver::cast(args[0]);
8782   } else {
8783     // Convert the object to a proper JavaScript object.
8784     MaybeObject* maybe_js_object = args[0]->ToObject();
8785     if (!maybe_js_object->To(&extension_object)) {
8786       if (Failure::cast(maybe_js_object)->IsInternalError()) {
8787         HandleScope scope(isolate);
8788         Handle<Object> handle = args.at<Object>(0);
8789         Handle<Object> result =
8790             isolate->factory()->NewTypeError("with_expression",
8791                                              HandleVector(&handle, 1));
8792         return isolate->Throw(*result);
8793       } else {
8794         return maybe_js_object;
8795       }
8796     }
8797   }
8798
8799   JSFunction* function;
8800   if (args[1]->IsSmi()) {
8801     // A smi sentinel indicates a context nested inside global code rather
8802     // than some function.  There is a canonical empty function that can be
8803     // gotten from the native context.
8804     function = isolate->context()->native_context()->closure();
8805   } else {
8806     function = JSFunction::cast(args[1]);
8807   }
8808
8809   Context* context;
8810   MaybeObject* maybe_context =
8811       isolate->heap()->AllocateWithContext(function,
8812                                            isolate->context(),
8813                                            extension_object);
8814   if (!maybe_context->To(&context)) return maybe_context;
8815   isolate->set_context(context);
8816   return context;
8817 }
8818
8819
8820 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8821   SealHandleScope shs(isolate);
8822   ASSERT(args.length() == 3);
8823   String* name = String::cast(args[0]);
8824   Object* thrown_object = args[1];
8825   JSFunction* function;
8826   if (args[2]->IsSmi()) {
8827     // A smi sentinel indicates a context nested inside global code rather
8828     // than some function.  There is a canonical empty function that can be
8829     // gotten from the native context.
8830     function = isolate->context()->native_context()->closure();
8831   } else {
8832     function = JSFunction::cast(args[2]);
8833   }
8834   Context* context;
8835   MaybeObject* maybe_context =
8836       isolate->heap()->AllocateCatchContext(function,
8837                                             isolate->context(),
8838                                             name,
8839                                             thrown_object);
8840   if (!maybe_context->To(&context)) return maybe_context;
8841   isolate->set_context(context);
8842   return context;
8843 }
8844
8845
8846 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8847   SealHandleScope shs(isolate);
8848   ASSERT(args.length() == 2);
8849   ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8850   JSFunction* function;
8851   if (args[1]->IsSmi()) {
8852     // A smi sentinel indicates a context nested inside global code rather
8853     // than some function.  There is a canonical empty function that can be
8854     // gotten from the native context.
8855     function = isolate->context()->native_context()->closure();
8856   } else {
8857     function = JSFunction::cast(args[1]);
8858   }
8859   Context* context;
8860   MaybeObject* maybe_context =
8861       isolate->heap()->AllocateBlockContext(function,
8862                                             isolate->context(),
8863                                             scope_info);
8864   if (!maybe_context->To(&context)) return maybe_context;
8865   isolate->set_context(context);
8866   return context;
8867 }
8868
8869
8870 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
8871   SealHandleScope shs(isolate);
8872   ASSERT(args.length() == 1);
8873   Object* obj = args[0];
8874   return isolate->heap()->ToBoolean(obj->IsJSModule());
8875 }
8876
8877
8878 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
8879   SealHandleScope shs(isolate);
8880   ASSERT(args.length() == 2);
8881   CONVERT_SMI_ARG_CHECKED(index, 0);
8882
8883   if (!args[1]->IsScopeInfo()) {
8884     // Module already initialized. Find hosting context and retrieve context.
8885     Context* host = Context::cast(isolate->context())->global_context();
8886     Context* context = Context::cast(host->get(index));
8887     ASSERT(context->previous() == isolate->context());
8888     isolate->set_context(context);
8889     return context;
8890   }
8891
8892   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
8893
8894   // Allocate module context.
8895   HandleScope scope(isolate);
8896   Factory* factory = isolate->factory();
8897   Handle<Context> context = factory->NewModuleContext(scope_info);
8898   Handle<JSModule> module = factory->NewJSModule(context, scope_info);
8899   context->set_module(*module);
8900   Context* previous = isolate->context();
8901   context->set_previous(previous);
8902   context->set_closure(previous->closure());
8903   context->set_global_object(previous->global_object());
8904   isolate->set_context(*context);
8905
8906   // Find hosting scope and initialize internal variable holding module there.
8907   previous->global_context()->set(index, *context);
8908
8909   return *context;
8910 }
8911
8912
8913 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
8914   HandleScope scope(isolate);
8915   ASSERT(args.length() == 1);
8916   CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
8917   Context* host_context = isolate->context();
8918
8919   for (int i = 0; i < descriptions->length(); ++i) {
8920     Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
8921     int host_index = description->host_index();
8922     Handle<Context> context(Context::cast(host_context->get(host_index)));
8923     Handle<JSModule> module(context->module());
8924
8925     for (int j = 0; j < description->length(); ++j) {
8926       Handle<String> name(description->name(j));
8927       VariableMode mode = description->mode(j);
8928       int index = description->index(j);
8929       switch (mode) {
8930         case VAR:
8931         case LET:
8932         case CONST:
8933         case CONST_HARMONY: {
8934           PropertyAttributes attr =
8935               IsImmutableVariableMode(mode) ? FROZEN : SEALED;
8936           Handle<AccessorInfo> info =
8937               Accessors::MakeModuleExport(name, index, attr);
8938           Handle<Object> result = SetAccessor(module, info);
8939           ASSERT(!(result.is_null() || result->IsUndefined()));
8940           USE(result);
8941           break;
8942         }
8943         case MODULE: {
8944           Object* referenced_context = Context::cast(host_context)->get(index);
8945           Handle<JSModule> value(Context::cast(referenced_context)->module());
8946           JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode);
8947           break;
8948         }
8949         case INTERNAL:
8950         case TEMPORARY:
8951         case DYNAMIC:
8952         case DYNAMIC_GLOBAL:
8953         case DYNAMIC_LOCAL:
8954           UNREACHABLE();
8955       }
8956     }
8957
8958     JSObject::PreventExtensions(module);
8959   }
8960
8961   ASSERT(!isolate->has_pending_exception());
8962   return isolate->heap()->undefined_value();
8963 }
8964
8965
8966 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8967   HandleScope scope(isolate);
8968   ASSERT(args.length() == 2);
8969
8970   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8971   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
8972
8973   int index;
8974   PropertyAttributes attributes;
8975   ContextLookupFlags flags = FOLLOW_CHAINS;
8976   BindingFlags binding_flags;
8977   Handle<Object> holder = context->Lookup(name,
8978                                           flags,
8979                                           &index,
8980                                           &attributes,
8981                                           &binding_flags);
8982
8983   // If the slot was not found the result is true.
8984   if (holder.is_null()) {
8985     return isolate->heap()->true_value();
8986   }
8987
8988   // If the slot was found in a context, it should be DONT_DELETE.
8989   if (holder->IsContext()) {
8990     return isolate->heap()->false_value();
8991   }
8992
8993   // The slot was found in a JSObject, either a context extension object,
8994   // the global object, or the subject of a with.  Try to delete it
8995   // (respecting DONT_DELETE).
8996   Handle<JSObject> object = Handle<JSObject>::cast(holder);
8997   Handle<Object> result = JSReceiver::DeleteProperty(object, name);
8998   RETURN_IF_EMPTY_HANDLE(isolate, result);
8999   return *result;
9000 }
9001
9002
9003 // A mechanism to return a pair of Object pointers in registers (if possible).
9004 // How this is achieved is calling convention-dependent.
9005 // All currently supported x86 compiles uses calling conventions that are cdecl
9006 // variants where a 64-bit value is returned in two 32-bit registers
9007 // (edx:eax on ia32, r1:r0 on ARM).
9008 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9009 // In Win64 calling convention, a struct of two pointers is returned in memory,
9010 // allocated by the caller, and passed as a pointer in a hidden first parameter.
9011 #ifdef V8_HOST_ARCH_64_BIT
9012 struct ObjectPair {
9013   MaybeObject* x;
9014   MaybeObject* y;
9015 };
9016
9017
9018 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9019   ObjectPair result = {x, y};
9020   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9021   // In Win64 they are assigned to a hidden first argument.
9022   return result;
9023 }
9024 #else
9025 typedef uint64_t ObjectPair;
9026 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9027   return reinterpret_cast<uint32_t>(x) |
9028       (reinterpret_cast<ObjectPair>(y) << 32);
9029 }
9030 #endif
9031
9032
9033 static inline MaybeObject* Unhole(Heap* heap,
9034                                   MaybeObject* x,
9035                                   PropertyAttributes attributes) {
9036   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
9037   USE(attributes);
9038   return x->IsTheHole() ? heap->undefined_value() : x;
9039 }
9040
9041
9042 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9043                                            JSObject* holder) {
9044   ASSERT(!holder->IsGlobalObject());
9045   Context* top = isolate->context();
9046   // Get the context extension function.
9047   JSFunction* context_extension_function =
9048       top->native_context()->context_extension_function();
9049   // If the holder isn't a context extension object, we just return it
9050   // as the receiver. This allows arguments objects to be used as
9051   // receivers, but only if they are put in the context scope chain
9052   // explicitly via a with-statement.
9053   Object* constructor = holder->map()->constructor();
9054   if (constructor != context_extension_function) return holder;
9055   // Fall back to using the global object as the implicit receiver if
9056   // the property turns out to be a local variable allocated in a
9057   // context extension object - introduced via eval. Implicit global
9058   // receivers are indicated with the hole value.
9059   return isolate->heap()->the_hole_value();
9060 }
9061
9062
9063 static ObjectPair LoadContextSlotHelper(Arguments args,
9064                                         Isolate* isolate,
9065                                         bool throw_error) {
9066   HandleScope scope(isolate);
9067   ASSERT_EQ(2, args.length());
9068
9069   if (!args[0]->IsContext() || !args[1]->IsString()) {
9070     return MakePair(isolate->ThrowIllegalOperation(), NULL);
9071   }
9072   Handle<Context> context = args.at<Context>(0);
9073   Handle<String> name = args.at<String>(1);
9074
9075   int index;
9076   PropertyAttributes attributes;
9077   ContextLookupFlags flags = FOLLOW_CHAINS;
9078   BindingFlags binding_flags;
9079   Handle<Object> holder = context->Lookup(name,
9080                                           flags,
9081                                           &index,
9082                                           &attributes,
9083                                           &binding_flags);
9084   if (isolate->has_pending_exception()) {
9085     return MakePair(Failure::Exception(), NULL);
9086   }
9087
9088   // If the index is non-negative, the slot has been found in a context.
9089   if (index >= 0) {
9090     ASSERT(holder->IsContext());
9091     // If the "property" we were looking for is a local variable, the
9092     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9093     //
9094     // Use the hole as the receiver to signal that the receiver is implicit
9095     // and that the global receiver should be used (as distinguished from an
9096     // explicit receiver that happens to be a global object).
9097     Handle<Object> receiver = isolate->factory()->the_hole_value();
9098     Object* value = Context::cast(*holder)->get(index);
9099     // Check for uninitialized bindings.
9100     switch (binding_flags) {
9101       case MUTABLE_CHECK_INITIALIZED:
9102       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
9103         if (value->IsTheHole()) {
9104           Handle<Object> reference_error =
9105               isolate->factory()->NewReferenceError("not_defined",
9106                                                     HandleVector(&name, 1));
9107           return MakePair(isolate->Throw(*reference_error), NULL);
9108         }
9109         // FALLTHROUGH
9110       case MUTABLE_IS_INITIALIZED:
9111       case IMMUTABLE_IS_INITIALIZED:
9112       case IMMUTABLE_IS_INITIALIZED_HARMONY:
9113         ASSERT(!value->IsTheHole());
9114         return MakePair(value, *receiver);
9115       case IMMUTABLE_CHECK_INITIALIZED:
9116         return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
9117       case MISSING_BINDING:
9118         UNREACHABLE();
9119         return MakePair(NULL, NULL);
9120     }
9121   }
9122
9123   // Otherwise, if the slot was found the holder is a context extension
9124   // object, subject of a with, or a global object.  We read the named
9125   // property from it.
9126   if (!holder.is_null()) {
9127     Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9128     ASSERT(object->IsJSProxy() || object->HasProperty(*name));
9129     // GetProperty below can cause GC.
9130     Handle<Object> receiver_handle(
9131         object->IsGlobalObject()
9132             ? GlobalObject::cast(*object)->global_receiver()
9133             : object->IsJSProxy() ? static_cast<Object*>(*object)
9134                 : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9135         isolate);
9136
9137     // No need to unhole the value here.  This is taken care of by the
9138     // GetProperty function.
9139     MaybeObject* value = object->GetProperty(*name);
9140     return MakePair(value, *receiver_handle);
9141   }
9142
9143   if (throw_error) {
9144     // The property doesn't exist - throw exception.
9145     Handle<Object> reference_error =
9146         isolate->factory()->NewReferenceError("not_defined",
9147                                               HandleVector(&name, 1));
9148     return MakePair(isolate->Throw(*reference_error), NULL);
9149   } else {
9150     // The property doesn't exist - return undefined.
9151     return MakePair(isolate->heap()->undefined_value(),
9152                     isolate->heap()->undefined_value());
9153   }
9154 }
9155
9156
9157 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
9158   return LoadContextSlotHelper(args, isolate, true);
9159 }
9160
9161
9162 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
9163   return LoadContextSlotHelper(args, isolate, false);
9164 }
9165
9166
9167 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
9168   HandleScope scope(isolate);
9169   ASSERT(args.length() == 4);
9170
9171   Handle<Object> value(args[0], isolate);
9172   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9173   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9174   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9175   StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
9176       ? kNonStrictMode : kStrictMode;
9177
9178   int index;
9179   PropertyAttributes attributes;
9180   ContextLookupFlags flags = FOLLOW_CHAINS;
9181   BindingFlags binding_flags;
9182   Handle<Object> holder = context->Lookup(name,
9183                                           flags,
9184                                           &index,
9185                                           &attributes,
9186                                           &binding_flags);
9187   if (isolate->has_pending_exception()) return Failure::Exception();
9188
9189   if (index >= 0) {
9190     // The property was found in a context slot.
9191     Handle<Context> context = Handle<Context>::cast(holder);
9192     if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9193         context->get(index)->IsTheHole()) {
9194       Handle<Object> error =
9195           isolate->factory()->NewReferenceError("not_defined",
9196                                                 HandleVector(&name, 1));
9197       return isolate->Throw(*error);
9198     }
9199     // Ignore if read_only variable.
9200     if ((attributes & READ_ONLY) == 0) {
9201       // Context is a fixed array and set cannot fail.
9202       context->set(index, *value);
9203     } else if (strict_mode == kStrictMode) {
9204       // Setting read only property in strict mode.
9205       Handle<Object> error =
9206           isolate->factory()->NewTypeError("strict_cannot_assign",
9207                                            HandleVector(&name, 1));
9208       return isolate->Throw(*error);
9209     }
9210     return *value;
9211   }
9212
9213   // Slow case: The property is not in a context slot.  It is either in a
9214   // context extension object, a property of the subject of a with, or a
9215   // property of the global object.
9216   Handle<JSReceiver> object;
9217
9218   if (!holder.is_null()) {
9219     // The property exists on the holder.
9220     object = Handle<JSReceiver>::cast(holder);
9221   } else {
9222     // The property was not found.
9223     ASSERT(attributes == ABSENT);
9224
9225     if (strict_mode == kStrictMode) {
9226       // Throw in strict mode (assignment to undefined variable).
9227       Handle<Object> error =
9228           isolate->factory()->NewReferenceError(
9229               "not_defined", HandleVector(&name, 1));
9230       return isolate->Throw(*error);
9231     }
9232     // In non-strict mode, the property is added to the global object.
9233     attributes = NONE;
9234     object = Handle<JSReceiver>(isolate->context()->global_object());
9235   }
9236
9237   // Set the property if it's not read only or doesn't yet exist.
9238   if ((attributes & READ_ONLY) == 0 ||
9239       (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
9240     RETURN_IF_EMPTY_HANDLE(
9241         isolate,
9242         JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9243   } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
9244     // Setting read only property in strict mode.
9245     Handle<Object> error =
9246       isolate->factory()->NewTypeError(
9247           "strict_cannot_assign", HandleVector(&name, 1));
9248     return isolate->Throw(*error);
9249   }
9250   return *value;
9251 }
9252
9253
9254 RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
9255   HandleScope scope(isolate);
9256   ASSERT(args.length() == 1);
9257
9258   return isolate->Throw(args[0]);
9259 }
9260
9261
9262 RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
9263   HandleScope scope(isolate);
9264   ASSERT(args.length() == 1);
9265
9266   return isolate->ReThrow(args[0]);
9267 }
9268
9269
9270 RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
9271   SealHandleScope shs(isolate);
9272   ASSERT_EQ(0, args.length());
9273   return isolate->PromoteScheduledException();
9274 }
9275
9276
9277 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
9278   HandleScope scope(isolate);
9279   ASSERT(args.length() == 1);
9280
9281   Handle<Object> name(args[0], isolate);
9282   Handle<Object> reference_error =
9283     isolate->factory()->NewReferenceError("not_defined",
9284                                           HandleVector(&name, 1));
9285   return isolate->Throw(*reference_error);
9286 }
9287
9288
9289 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
9290   HandleScope scope(isolate);
9291   ASSERT(args.length() == 0);
9292   return isolate->Throw(*isolate->factory()->NewTypeError(
9293       "not_date_object", HandleVector<Object>(NULL, 0)));
9294 }
9295
9296
9297
9298 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9299   SealHandleScope shs(isolate);
9300   ASSERT(args.length() == 0);
9301
9302   // First check if this is a real stack overflow.
9303   if (isolate->stack_guard()->IsStackOverflow()) {
9304     SealHandleScope shs(isolate);
9305     return isolate->StackOverflow();
9306   }
9307
9308   return Execution::HandleStackGuardInterrupt(isolate);
9309 }
9310
9311
9312 RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
9313   SealHandleScope shs(isolate);
9314   ASSERT(args.length() == 0);
9315   return Execution::HandleStackGuardInterrupt(isolate);
9316 }
9317
9318
9319 static int StackSize(Isolate* isolate) {
9320   int n = 0;
9321   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9322   return n;
9323 }
9324
9325
9326 static void PrintTransition(Isolate* isolate, Object* result) {
9327   // indentation
9328   { const int nmax = 80;
9329     int n = StackSize(isolate);
9330     if (n <= nmax)
9331       PrintF("%4d:%*s", n, n, "");
9332     else
9333       PrintF("%4d:%*s", n, nmax, "...");
9334   }
9335
9336   if (result == NULL) {
9337     JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9338     PrintF(" {\n");
9339   } else {
9340     // function result
9341     PrintF("} -> ");
9342     result->ShortPrint();
9343     PrintF("\n");
9344   }
9345 }
9346
9347
9348 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9349   SealHandleScope shs(isolate);
9350   ASSERT(args.length() == 0);
9351   PrintTransition(isolate, NULL);
9352   return isolate->heap()->undefined_value();
9353 }
9354
9355
9356 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9357   SealHandleScope shs(isolate);
9358   PrintTransition(isolate, args[0]);
9359   return args[0];  // return TOS
9360 }
9361
9362
9363 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9364   SealHandleScope shs(isolate);
9365   ASSERT(args.length() == 1);
9366
9367 #ifdef DEBUG
9368   if (args[0]->IsString()) {
9369     // If we have a string, assume it's a code "marker"
9370     // and print some interesting cpu debugging info.
9371     JavaScriptFrameIterator it(isolate);
9372     JavaScriptFrame* frame = it.frame();
9373     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9374            frame->fp(), frame->sp(), frame->caller_sp());
9375   } else {
9376     PrintF("DebugPrint: ");
9377   }
9378   args[0]->Print();
9379   if (args[0]->IsHeapObject()) {
9380     PrintF("\n");
9381     HeapObject::cast(args[0])->map()->Print();
9382   }
9383 #else
9384   // ShortPrint is available in release mode. Print is not.
9385   args[0]->ShortPrint();
9386 #endif
9387   PrintF("\n");
9388   Flush();
9389
9390   return args[0];  // return TOS
9391 }
9392
9393
9394 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9395   SealHandleScope shs(isolate);
9396   ASSERT(args.length() == 0);
9397   isolate->PrintStack(stdout);
9398   return isolate->heap()->undefined_value();
9399 }
9400
9401
9402 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9403   SealHandleScope shs(isolate);
9404   ASSERT(args.length() == 0);
9405
9406   // According to ECMA-262, section 15.9.1, page 117, the precision of
9407   // the number in a Date object representing a particular instant in
9408   // time is milliseconds. Therefore, we floor the result of getting
9409   // the OS time.
9410   double millis = floor(OS::TimeCurrentMillis());
9411   return isolate->heap()->NumberFromDouble(millis);
9412 }
9413
9414
9415 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9416   HandleScope scope(isolate);
9417   ASSERT(args.length() == 2);
9418
9419   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9420   FlattenString(str);
9421
9422   CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9423
9424   MaybeObject* maybe_result_array =
9425       output->EnsureCanContainHeapObjectElements();
9426   if (maybe_result_array->IsFailure()) return maybe_result_array;
9427   RUNTIME_ASSERT(output->HasFastObjectElements());
9428
9429   DisallowHeapAllocation no_gc;
9430
9431   FixedArray* output_array = FixedArray::cast(output->elements());
9432   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9433   bool result;
9434   String::FlatContent str_content = str->GetFlatContent();
9435   if (str_content.IsAscii()) {
9436     result = DateParser::Parse(str_content.ToOneByteVector(),
9437                                output_array,
9438                                isolate->unicode_cache());
9439   } else {
9440     ASSERT(str_content.IsTwoByte());
9441     result = DateParser::Parse(str_content.ToUC16Vector(),
9442                                output_array,
9443                                isolate->unicode_cache());
9444   }
9445
9446   if (result) {
9447     return *output;
9448   } else {
9449     return isolate->heap()->null_value();
9450   }
9451 }
9452
9453
9454 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9455   SealHandleScope shs(isolate);
9456   ASSERT(args.length() == 1);
9457
9458   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9459   int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9460   const char* zone = OS::LocalTimezone(static_cast<double>(time));
9461   return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9462 }
9463
9464
9465 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9466   SealHandleScope shs(isolate);
9467   ASSERT(args.length() == 1);
9468
9469   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9470   int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9471
9472   return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9473 }
9474
9475
9476 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9477   SealHandleScope shs(isolate);
9478   ASSERT(args.length() == 1);
9479   Object* global = args[0];
9480   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9481   return JSGlobalObject::cast(global)->global_receiver();
9482 }
9483
9484
9485 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9486   HandleScope scope(isolate);
9487   ASSERT_EQ(1, args.length());
9488   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9489
9490   source = Handle<String>(FlattenGetString(source));
9491   // Optimized fast case where we only have ASCII characters.
9492   Handle<Object> result;
9493   if (source->IsSeqOneByteString()) {
9494     result = JsonParser<true>::Parse(source);
9495   } else {
9496     result = JsonParser<false>::Parse(source);
9497   }
9498   if (result.is_null()) {
9499     // Syntax error or stack overflow in scanner.
9500     ASSERT(isolate->has_pending_exception());
9501     return Failure::Exception();
9502   }
9503   return *result;
9504 }
9505
9506
9507 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9508                                       Handle<Context> context) {
9509   ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9510   // Check with callback if set.
9511   AllowCodeGenerationFromStringsCallback callback =
9512       isolate->allow_code_gen_callback();
9513   if (callback == NULL) {
9514     // No callback set and code generation disallowed.
9515     return false;
9516   } else {
9517     // Callback set. Let it decide if code generation is allowed.
9518     VMState<EXTERNAL> state(isolate);
9519     return callback(v8::Utils::ToLocal(context));
9520   }
9521 }
9522
9523
9524 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9525   HandleScope scope(isolate);
9526   ASSERT_EQ(2, args.length());
9527   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9528   CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9529
9530   // Extract native context.
9531   Handle<Context> context(isolate->context()->native_context());
9532
9533   // Check if native context allows code generation from
9534   // strings. Throw an exception if it doesn't.
9535   if (context->allow_code_gen_from_strings()->IsFalse() &&
9536       !CodeGenerationFromStringsAllowed(isolate, context)) {
9537     Handle<Object> error_message =
9538         context->ErrorMessageForCodeGenerationFromStrings();
9539     return isolate->Throw(*isolate->factory()->NewEvalError(
9540         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9541   }
9542
9543   // Compile source string in the native context.
9544   ParseRestriction restriction = function_literal_only
9545       ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
9546   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9547       source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
9548   RETURN_IF_EMPTY_HANDLE(isolate, shared);
9549   Handle<JSFunction> fun =
9550       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9551                                                             context,
9552                                                             NOT_TENURED);
9553   return *fun;
9554 }
9555
9556
9557 static ObjectPair CompileGlobalEval(Isolate* isolate,
9558                                     Handle<String> source,
9559                                     Handle<Object> receiver,
9560                                     LanguageMode language_mode,
9561                                     int scope_position) {
9562   Handle<Context> context = Handle<Context>(isolate->context());
9563   Handle<Context> native_context = Handle<Context>(context->native_context());
9564
9565   // Check if native context allows code generation from
9566   // strings. Throw an exception if it doesn't.
9567   if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9568       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9569     Handle<Object> error_message =
9570         native_context->ErrorMessageForCodeGenerationFromStrings();
9571     isolate->Throw(*isolate->factory()->NewEvalError(
9572         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9573     return MakePair(Failure::Exception(), NULL);
9574   }
9575
9576   // Deal with a normal eval call with a string argument. Compile it
9577   // and return the compiled function bound in the local context.
9578   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9579       source,
9580       context,
9581       context->IsNativeContext(),
9582       language_mode,
9583       NO_PARSE_RESTRICTION,
9584       scope_position);
9585   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
9586                                MakePair(Failure::Exception(), NULL));
9587   Handle<JSFunction> compiled =
9588       isolate->factory()->NewFunctionFromSharedFunctionInfo(
9589           shared, context, NOT_TENURED);
9590   return MakePair(*compiled, *receiver);
9591 }
9592
9593
9594 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9595   HandleScope scope(isolate);
9596   ASSERT(args.length() == 5);
9597
9598   Handle<Object> callee = args.at<Object>(0);
9599
9600   // If "eval" didn't refer to the original GlobalEval, it's not a
9601   // direct call to eval.
9602   // (And even if it is, but the first argument isn't a string, just let
9603   // execution default to an indirect call to eval, which will also return
9604   // the first argument without doing anything).
9605   if (*callee != isolate->native_context()->global_eval_fun() ||
9606       !args[1]->IsString()) {
9607     return MakePair(*callee, isolate->heap()->the_hole_value());
9608   }
9609
9610   CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9611   ASSERT(args[4]->IsSmi());
9612   return CompileGlobalEval(isolate,
9613                            args.at<String>(1),
9614                            args.at<Object>(2),
9615                            language_mode,
9616                            args.smi_at(4));
9617 }
9618
9619
9620 static MaybeObject* Allocate(Isolate* isolate,
9621                              int size,
9622                              AllocationSpace space) {
9623   // Allocate a block of memory in the given space (filled with a filler).
9624   // Use as fallback for allocation in generated code when the space
9625   // is full.
9626   SealHandleScope shs(isolate);
9627   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9628   RUNTIME_ASSERT(size > 0);
9629   Heap* heap = isolate->heap();
9630   RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize());
9631   Object* allocation;
9632   { MaybeObject* maybe_allocation;
9633     if (space == NEW_SPACE) {
9634       maybe_allocation = heap->new_space()->AllocateRaw(size);
9635     } else {
9636       ASSERT(space == OLD_POINTER_SPACE || space == OLD_DATA_SPACE);
9637       maybe_allocation = heap->paged_space(space)->AllocateRaw(size);
9638     }
9639     if (maybe_allocation->ToObject(&allocation)) {
9640       heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9641     }
9642     return maybe_allocation;
9643   }
9644 }
9645
9646
9647 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9648   SealHandleScope shs(isolate);
9649   ASSERT(args.length() == 1);
9650   CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9651   return Allocate(isolate, size_smi->value(), NEW_SPACE);
9652 }
9653
9654
9655 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldPointerSpace) {
9656   SealHandleScope shs(isolate);
9657   ASSERT(args.length() == 1);
9658   CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9659   return Allocate(isolate, size_smi->value(), OLD_POINTER_SPACE);
9660 }
9661
9662
9663 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldDataSpace) {
9664   SealHandleScope shs(isolate);
9665   ASSERT(args.length() == 1);
9666   CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9667   return Allocate(isolate, size_smi->value(), OLD_DATA_SPACE);
9668 }
9669
9670
9671 // Push an object unto an array of objects if it is not already in the
9672 // array.  Returns true if the element was pushed on the stack and
9673 // false otherwise.
9674 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9675   SealHandleScope shs(isolate);
9676   ASSERT(args.length() == 2);
9677   CONVERT_ARG_CHECKED(JSArray, array, 0);
9678   CONVERT_ARG_CHECKED(JSReceiver, element, 1);
9679   RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9680   int length = Smi::cast(array->length())->value();
9681   FixedArray* elements = FixedArray::cast(array->elements());
9682   for (int i = 0; i < length; i++) {
9683     if (elements->get(i) == element) return isolate->heap()->false_value();
9684   }
9685   Object* obj;
9686   // Strict not needed. Used for cycle detection in Array join implementation.
9687   { MaybeObject* maybe_obj =
9688         array->SetFastElement(length, element, kNonStrictMode, true);
9689     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9690   }
9691   return isolate->heap()->true_value();
9692 }
9693
9694
9695 /**
9696  * A simple visitor visits every element of Array's.
9697  * The backend storage can be a fixed array for fast elements case,
9698  * or a dictionary for sparse array. Since Dictionary is a subtype
9699  * of FixedArray, the class can be used by both fast and slow cases.
9700  * The second parameter of the constructor, fast_elements, specifies
9701  * whether the storage is a FixedArray or Dictionary.
9702  *
9703  * An index limit is used to deal with the situation that a result array
9704  * length overflows 32-bit non-negative integer.
9705  */
9706 class ArrayConcatVisitor {
9707  public:
9708   ArrayConcatVisitor(Isolate* isolate,
9709                      Handle<FixedArray> storage,
9710                      bool fast_elements) :
9711       isolate_(isolate),
9712       storage_(Handle<FixedArray>::cast(
9713           isolate->global_handles()->Create(*storage))),
9714       index_offset_(0u),
9715       fast_elements_(fast_elements),
9716       exceeds_array_limit_(false) { }
9717
9718   ~ArrayConcatVisitor() {
9719     clear_storage();
9720   }
9721
9722   void visit(uint32_t i, Handle<Object> elm) {
9723     if (i > JSObject::kMaxElementCount - index_offset_) {
9724       exceeds_array_limit_ = true;
9725       return;
9726     }
9727     uint32_t index = index_offset_ + i;
9728
9729     if (fast_elements_) {
9730       if (index < static_cast<uint32_t>(storage_->length())) {
9731         storage_->set(index, *elm);
9732         return;
9733       }
9734       // Our initial estimate of length was foiled, possibly by
9735       // getters on the arrays increasing the length of later arrays
9736       // during iteration.
9737       // This shouldn't happen in anything but pathological cases.
9738       SetDictionaryMode(index);
9739       // Fall-through to dictionary mode.
9740     }
9741     ASSERT(!fast_elements_);
9742     Handle<SeededNumberDictionary> dict(
9743         SeededNumberDictionary::cast(*storage_));
9744     Handle<SeededNumberDictionary> result =
9745         isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9746     if (!result.is_identical_to(dict)) {
9747       // Dictionary needed to grow.
9748       clear_storage();
9749       set_storage(*result);
9750     }
9751   }
9752
9753   void increase_index_offset(uint32_t delta) {
9754     if (JSObject::kMaxElementCount - index_offset_ < delta) {
9755       index_offset_ = JSObject::kMaxElementCount;
9756     } else {
9757       index_offset_ += delta;
9758     }
9759   }
9760
9761   bool exceeds_array_limit() {
9762     return exceeds_array_limit_;
9763   }
9764
9765   Handle<JSArray> ToArray() {
9766     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9767     Handle<Object> length =
9768         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9769     Handle<Map> map;
9770     if (fast_elements_) {
9771       map = isolate_->factory()->GetElementsTransitionMap(array,
9772                                                           FAST_HOLEY_ELEMENTS);
9773     } else {
9774       map = isolate_->factory()->GetElementsTransitionMap(array,
9775                                                           DICTIONARY_ELEMENTS);
9776     }
9777     array->set_map(*map);
9778     array->set_length(*length);
9779     array->set_elements(*storage_);
9780     return array;
9781   }
9782
9783  private:
9784   // Convert storage to dictionary mode.
9785   void SetDictionaryMode(uint32_t index) {
9786     ASSERT(fast_elements_);
9787     Handle<FixedArray> current_storage(*storage_);
9788     Handle<SeededNumberDictionary> slow_storage(
9789         isolate_->factory()->NewSeededNumberDictionary(
9790             current_storage->length()));
9791     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9792     for (uint32_t i = 0; i < current_length; i++) {
9793       HandleScope loop_scope(isolate_);
9794       Handle<Object> element(current_storage->get(i), isolate_);
9795       if (!element->IsTheHole()) {
9796         Handle<SeededNumberDictionary> new_storage =
9797           isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9798         if (!new_storage.is_identical_to(slow_storage)) {
9799           slow_storage = loop_scope.CloseAndEscape(new_storage);
9800         }
9801       }
9802     }
9803     clear_storage();
9804     set_storage(*slow_storage);
9805     fast_elements_ = false;
9806   }
9807
9808   inline void clear_storage() {
9809     isolate_->global_handles()->Destroy(
9810         Handle<Object>::cast(storage_).location());
9811   }
9812
9813   inline void set_storage(FixedArray* storage) {
9814     storage_ = Handle<FixedArray>::cast(
9815         isolate_->global_handles()->Create(storage));
9816   }
9817
9818   Isolate* isolate_;
9819   Handle<FixedArray> storage_;  // Always a global handle.
9820   // Index after last seen index. Always less than or equal to
9821   // JSObject::kMaxElementCount.
9822   uint32_t index_offset_;
9823   bool fast_elements_ : 1;
9824   bool exceeds_array_limit_ : 1;
9825 };
9826
9827
9828 static uint32_t EstimateElementCount(Handle<JSArray> array) {
9829   uint32_t length = static_cast<uint32_t>(array->length()->Number());
9830   int element_count = 0;
9831   switch (array->GetElementsKind()) {
9832     case FAST_SMI_ELEMENTS:
9833     case FAST_HOLEY_SMI_ELEMENTS:
9834     case FAST_ELEMENTS:
9835     case FAST_HOLEY_ELEMENTS: {
9836       // Fast elements can't have lengths that are not representable by
9837       // a 32-bit signed integer.
9838       ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9839       int fast_length = static_cast<int>(length);
9840       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9841       for (int i = 0; i < fast_length; i++) {
9842         if (!elements->get(i)->IsTheHole()) element_count++;
9843       }
9844       break;
9845     }
9846     case FAST_DOUBLE_ELEMENTS:
9847     case FAST_HOLEY_DOUBLE_ELEMENTS: {
9848       // Fast elements can't have lengths that are not representable by
9849       // a 32-bit signed integer.
9850       ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
9851       int fast_length = static_cast<int>(length);
9852       if (array->elements()->IsFixedArray()) {
9853         ASSERT(FixedArray::cast(array->elements())->length() == 0);
9854         break;
9855       }
9856       Handle<FixedDoubleArray> elements(
9857           FixedDoubleArray::cast(array->elements()));
9858       for (int i = 0; i < fast_length; i++) {
9859         if (!elements->is_the_hole(i)) element_count++;
9860       }
9861       break;
9862     }
9863     case DICTIONARY_ELEMENTS: {
9864       Handle<SeededNumberDictionary> dictionary(
9865           SeededNumberDictionary::cast(array->elements()));
9866       int capacity = dictionary->Capacity();
9867       for (int i = 0; i < capacity; i++) {
9868         Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
9869         if (dictionary->IsKey(*key)) {
9870           element_count++;
9871         }
9872       }
9873       break;
9874     }
9875     case NON_STRICT_ARGUMENTS_ELEMENTS:
9876     case EXTERNAL_BYTE_ELEMENTS:
9877     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9878     case EXTERNAL_SHORT_ELEMENTS:
9879     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9880     case EXTERNAL_INT_ELEMENTS:
9881     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9882     case EXTERNAL_FLOAT_ELEMENTS:
9883     case EXTERNAL_DOUBLE_ELEMENTS:
9884     case EXTERNAL_PIXEL_ELEMENTS:
9885       // External arrays are always dense.
9886       return length;
9887   }
9888   // As an estimate, we assume that the prototype doesn't contain any
9889   // inherited elements.
9890   return element_count;
9891 }
9892
9893
9894
9895 template<class ExternalArrayClass, class ElementType>
9896 static void IterateExternalArrayElements(Isolate* isolate,
9897                                          Handle<JSObject> receiver,
9898                                          bool elements_are_ints,
9899                                          bool elements_are_guaranteed_smis,
9900                                          ArrayConcatVisitor* visitor) {
9901   Handle<ExternalArrayClass> array(
9902       ExternalArrayClass::cast(receiver->elements()));
9903   uint32_t len = static_cast<uint32_t>(array->length());
9904
9905   ASSERT(visitor != NULL);
9906   if (elements_are_ints) {
9907     if (elements_are_guaranteed_smis) {
9908       for (uint32_t j = 0; j < len; j++) {
9909         HandleScope loop_scope(isolate);
9910         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
9911                       isolate);
9912         visitor->visit(j, e);
9913       }
9914     } else {
9915       for (uint32_t j = 0; j < len; j++) {
9916         HandleScope loop_scope(isolate);
9917         int64_t val = static_cast<int64_t>(array->get_scalar(j));
9918         if (Smi::IsValid(static_cast<intptr_t>(val))) {
9919           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
9920           visitor->visit(j, e);
9921         } else {
9922           Handle<Object> e =
9923               isolate->factory()->NewNumber(static_cast<ElementType>(val));
9924           visitor->visit(j, e);
9925         }
9926       }
9927     }
9928   } else {
9929     for (uint32_t j = 0; j < len; j++) {
9930       HandleScope loop_scope(isolate);
9931       Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
9932       visitor->visit(j, e);
9933     }
9934   }
9935 }
9936
9937
9938 // Used for sorting indices in a List<uint32_t>.
9939 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
9940   uint32_t a = *ap;
9941   uint32_t b = *bp;
9942   return (a == b) ? 0 : (a < b) ? -1 : 1;
9943 }
9944
9945
9946 static void CollectElementIndices(Handle<JSObject> object,
9947                                   uint32_t range,
9948                                   List<uint32_t>* indices) {
9949   Isolate* isolate = object->GetIsolate();
9950   ElementsKind kind = object->GetElementsKind();
9951   switch (kind) {
9952     case FAST_SMI_ELEMENTS:
9953     case FAST_ELEMENTS:
9954     case FAST_HOLEY_SMI_ELEMENTS:
9955     case FAST_HOLEY_ELEMENTS: {
9956       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
9957       uint32_t length = static_cast<uint32_t>(elements->length());
9958       if (range < length) length = range;
9959       for (uint32_t i = 0; i < length; i++) {
9960         if (!elements->get(i)->IsTheHole()) {
9961           indices->Add(i);
9962         }
9963       }
9964       break;
9965     }
9966     case FAST_HOLEY_DOUBLE_ELEMENTS:
9967     case FAST_DOUBLE_ELEMENTS: {
9968       // TODO(1810): Decide if it's worthwhile to implement this.
9969       UNREACHABLE();
9970       break;
9971     }
9972     case DICTIONARY_ELEMENTS: {
9973       Handle<SeededNumberDictionary> dict(
9974           SeededNumberDictionary::cast(object->elements()));
9975       uint32_t capacity = dict->Capacity();
9976       for (uint32_t j = 0; j < capacity; j++) {
9977         HandleScope loop_scope(isolate);
9978         Handle<Object> k(dict->KeyAt(j), isolate);
9979         if (dict->IsKey(*k)) {
9980           ASSERT(k->IsNumber());
9981           uint32_t index = static_cast<uint32_t>(k->Number());
9982           if (index < range) {
9983             indices->Add(index);
9984           }
9985         }
9986       }
9987       break;
9988     }
9989     default: {
9990       int dense_elements_length;
9991       switch (kind) {
9992         case EXTERNAL_PIXEL_ELEMENTS: {
9993           dense_elements_length =
9994               ExternalPixelArray::cast(object->elements())->length();
9995           break;
9996         }
9997         case EXTERNAL_BYTE_ELEMENTS: {
9998           dense_elements_length =
9999               ExternalByteArray::cast(object->elements())->length();
10000           break;
10001         }
10002         case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10003           dense_elements_length =
10004               ExternalUnsignedByteArray::cast(object->elements())->length();
10005           break;
10006         }
10007         case EXTERNAL_SHORT_ELEMENTS: {
10008           dense_elements_length =
10009               ExternalShortArray::cast(object->elements())->length();
10010           break;
10011         }
10012         case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10013           dense_elements_length =
10014               ExternalUnsignedShortArray::cast(object->elements())->length();
10015           break;
10016         }
10017         case EXTERNAL_INT_ELEMENTS: {
10018           dense_elements_length =
10019               ExternalIntArray::cast(object->elements())->length();
10020           break;
10021         }
10022         case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10023           dense_elements_length =
10024               ExternalUnsignedIntArray::cast(object->elements())->length();
10025           break;
10026         }
10027         case EXTERNAL_FLOAT_ELEMENTS: {
10028           dense_elements_length =
10029               ExternalFloatArray::cast(object->elements())->length();
10030           break;
10031         }
10032         case EXTERNAL_DOUBLE_ELEMENTS: {
10033           dense_elements_length =
10034               ExternalDoubleArray::cast(object->elements())->length();
10035           break;
10036         }
10037         default:
10038           UNREACHABLE();
10039           dense_elements_length = 0;
10040           break;
10041       }
10042       uint32_t length = static_cast<uint32_t>(dense_elements_length);
10043       if (range <= length) {
10044         length = range;
10045         // We will add all indices, so we might as well clear it first
10046         // and avoid duplicates.
10047         indices->Clear();
10048       }
10049       for (uint32_t i = 0; i < length; i++) {
10050         indices->Add(i);
10051       }
10052       if (length == range) return;  // All indices accounted for already.
10053       break;
10054     }
10055   }
10056
10057   Handle<Object> prototype(object->GetPrototype(), isolate);
10058   if (prototype->IsJSObject()) {
10059     // The prototype will usually have no inherited element indices,
10060     // but we have to check.
10061     CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
10062   }
10063 }
10064
10065
10066 /**
10067  * A helper function that visits elements of a JSArray in numerical
10068  * order.
10069  *
10070  * The visitor argument called for each existing element in the array
10071  * with the element index and the element's value.
10072  * Afterwards it increments the base-index of the visitor by the array
10073  * length.
10074  * Returns false if any access threw an exception, otherwise true.
10075  */
10076 static bool IterateElements(Isolate* isolate,
10077                             Handle<JSArray> receiver,
10078                             ArrayConcatVisitor* visitor) {
10079   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10080   switch (receiver->GetElementsKind()) {
10081     case FAST_SMI_ELEMENTS:
10082     case FAST_ELEMENTS:
10083     case FAST_HOLEY_SMI_ELEMENTS:
10084     case FAST_HOLEY_ELEMENTS: {
10085       // Run through the elements FixedArray and use HasElement and GetElement
10086       // to check the prototype for missing elements.
10087       Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10088       int fast_length = static_cast<int>(length);
10089       ASSERT(fast_length <= elements->length());
10090       for (int j = 0; j < fast_length; j++) {
10091         HandleScope loop_scope(isolate);
10092         Handle<Object> element_value(elements->get(j), isolate);
10093         if (!element_value->IsTheHole()) {
10094           visitor->visit(j, element_value);
10095         } else if (receiver->HasElement(j)) {
10096           // Call GetElement on receiver, not its prototype, or getters won't
10097           // have the correct receiver.
10098           element_value = Object::GetElement(receiver, j);
10099           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10100           visitor->visit(j, element_value);
10101         }
10102       }
10103       break;
10104     }
10105     case FAST_HOLEY_DOUBLE_ELEMENTS:
10106     case FAST_DOUBLE_ELEMENTS: {
10107       // Run through the elements FixedArray and use HasElement and GetElement
10108       // to check the prototype for missing elements.
10109       Handle<FixedDoubleArray> elements(
10110           FixedDoubleArray::cast(receiver->elements()));
10111       int fast_length = static_cast<int>(length);
10112       ASSERT(fast_length <= elements->length());
10113       for (int j = 0; j < fast_length; j++) {
10114         HandleScope loop_scope(isolate);
10115         if (!elements->is_the_hole(j)) {
10116           double double_value = elements->get_scalar(j);
10117           Handle<Object> element_value =
10118               isolate->factory()->NewNumber(double_value);
10119           visitor->visit(j, element_value);
10120         } else if (receiver->HasElement(j)) {
10121           // Call GetElement on receiver, not its prototype, or getters won't
10122           // have the correct receiver.
10123           Handle<Object> element_value = Object::GetElement(receiver, j);
10124           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10125           visitor->visit(j, element_value);
10126         }
10127       }
10128       break;
10129     }
10130     case DICTIONARY_ELEMENTS: {
10131       Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10132       List<uint32_t> indices(dict->Capacity() / 2);
10133       // Collect all indices in the object and the prototypes less
10134       // than length. This might introduce duplicates in the indices list.
10135       CollectElementIndices(receiver, length, &indices);
10136       indices.Sort(&compareUInt32);
10137       int j = 0;
10138       int n = indices.length();
10139       while (j < n) {
10140         HandleScope loop_scope(isolate);
10141         uint32_t index = indices[j];
10142         Handle<Object> element = Object::GetElement(receiver, index);
10143         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
10144         visitor->visit(index, element);
10145         // Skip to next different index (i.e., omit duplicates).
10146         do {
10147           j++;
10148         } while (j < n && indices[j] == index);
10149       }
10150       break;
10151     }
10152     case EXTERNAL_PIXEL_ELEMENTS: {
10153       Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
10154           receiver->elements()));
10155       for (uint32_t j = 0; j < length; j++) {
10156         Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10157         visitor->visit(j, e);
10158       }
10159       break;
10160     }
10161     case EXTERNAL_BYTE_ELEMENTS: {
10162       IterateExternalArrayElements<ExternalByteArray, int8_t>(
10163           isolate, receiver, true, true, visitor);
10164       break;
10165     }
10166     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10167       IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
10168           isolate, receiver, true, true, visitor);
10169       break;
10170     }
10171     case EXTERNAL_SHORT_ELEMENTS: {
10172       IterateExternalArrayElements<ExternalShortArray, int16_t>(
10173           isolate, receiver, true, true, visitor);
10174       break;
10175     }
10176     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10177       IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
10178           isolate, receiver, true, true, visitor);
10179       break;
10180     }
10181     case EXTERNAL_INT_ELEMENTS: {
10182       IterateExternalArrayElements<ExternalIntArray, int32_t>(
10183           isolate, receiver, true, false, visitor);
10184       break;
10185     }
10186     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10187       IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
10188           isolate, receiver, true, false, visitor);
10189       break;
10190     }
10191     case EXTERNAL_FLOAT_ELEMENTS: {
10192       IterateExternalArrayElements<ExternalFloatArray, float>(
10193           isolate, receiver, false, false, visitor);
10194       break;
10195     }
10196     case EXTERNAL_DOUBLE_ELEMENTS: {
10197       IterateExternalArrayElements<ExternalDoubleArray, double>(
10198           isolate, receiver, false, false, visitor);
10199       break;
10200     }
10201     default:
10202       UNREACHABLE();
10203       break;
10204   }
10205   visitor->increase_index_offset(length);
10206   return true;
10207 }
10208
10209
10210 /**
10211  * Array::concat implementation.
10212  * See ECMAScript 262, 15.4.4.4.
10213  * TODO(581): Fix non-compliance for very large concatenations and update to
10214  * following the ECMAScript 5 specification.
10215  */
10216 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
10217   HandleScope handle_scope(isolate);
10218   ASSERT(args.length() == 1);
10219
10220   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10221   int argument_count = static_cast<int>(arguments->length()->Number());
10222   RUNTIME_ASSERT(arguments->HasFastObjectElements());
10223   Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10224
10225   // Pass 1: estimate the length and number of elements of the result.
10226   // The actual length can be larger if any of the arguments have getters
10227   // that mutate other arguments (but will otherwise be precise).
10228   // The number of elements is precise if there are no inherited elements.
10229
10230   ElementsKind kind = FAST_SMI_ELEMENTS;
10231
10232   uint32_t estimate_result_length = 0;
10233   uint32_t estimate_nof_elements = 0;
10234   for (int i = 0; i < argument_count; i++) {
10235     HandleScope loop_scope(isolate);
10236     Handle<Object> obj(elements->get(i), isolate);
10237     uint32_t length_estimate;
10238     uint32_t element_estimate;
10239     if (obj->IsJSArray()) {
10240       Handle<JSArray> array(Handle<JSArray>::cast(obj));
10241       length_estimate = static_cast<uint32_t>(array->length()->Number());
10242       if (length_estimate != 0) {
10243         ElementsKind array_kind =
10244             GetPackedElementsKind(array->map()->elements_kind());
10245         if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10246           kind = array_kind;
10247         }
10248       }
10249       element_estimate = EstimateElementCount(array);
10250     } else {
10251       if (obj->IsHeapObject()) {
10252         if (obj->IsNumber()) {
10253           if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
10254             kind = FAST_DOUBLE_ELEMENTS;
10255           }
10256         } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
10257           kind = FAST_ELEMENTS;
10258         }
10259       }
10260       length_estimate = 1;
10261       element_estimate = 1;
10262     }
10263     // Avoid overflows by capping at kMaxElementCount.
10264     if (JSObject::kMaxElementCount - estimate_result_length <
10265         length_estimate) {
10266       estimate_result_length = JSObject::kMaxElementCount;
10267     } else {
10268       estimate_result_length += length_estimate;
10269     }
10270     if (JSObject::kMaxElementCount - estimate_nof_elements <
10271         element_estimate) {
10272       estimate_nof_elements = JSObject::kMaxElementCount;
10273     } else {
10274       estimate_nof_elements += element_estimate;
10275     }
10276   }
10277
10278   // If estimated number of elements is more than half of length, a
10279   // fixed array (fast case) is more time and space-efficient than a
10280   // dictionary.
10281   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10282
10283   Handle<FixedArray> storage;
10284   if (fast_case) {
10285     if (kind == FAST_DOUBLE_ELEMENTS) {
10286       Handle<FixedDoubleArray> double_storage =
10287           isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10288       int j = 0;
10289       bool failure = false;
10290       for (int i = 0; i < argument_count; i++) {
10291         Handle<Object> obj(elements->get(i), isolate);
10292         if (obj->IsSmi()) {
10293           double_storage->set(j, Smi::cast(*obj)->value());
10294           j++;
10295         } else if (obj->IsNumber()) {
10296           double_storage->set(j, obj->Number());
10297           j++;
10298         } else {
10299           JSArray* array = JSArray::cast(*obj);
10300           uint32_t length = static_cast<uint32_t>(array->length()->Number());
10301           switch (array->map()->elements_kind()) {
10302             case FAST_HOLEY_DOUBLE_ELEMENTS:
10303             case FAST_DOUBLE_ELEMENTS: {
10304               // Empty fixed array indicates that there are no elements.
10305               if (array->elements()->IsFixedArray()) break;
10306               FixedDoubleArray* elements =
10307                   FixedDoubleArray::cast(array->elements());
10308               for (uint32_t i = 0; i < length; i++) {
10309                 if (elements->is_the_hole(i)) {
10310                   failure = true;
10311                   break;
10312                 }
10313                 double double_value = elements->get_scalar(i);
10314                 double_storage->set(j, double_value);
10315                 j++;
10316               }
10317               break;
10318             }
10319             case FAST_HOLEY_SMI_ELEMENTS:
10320             case FAST_SMI_ELEMENTS: {
10321               FixedArray* elements(
10322                   FixedArray::cast(array->elements()));
10323               for (uint32_t i = 0; i < length; i++) {
10324                 Object* element = elements->get(i);
10325                 if (element->IsTheHole()) {
10326                   failure = true;
10327                   break;
10328                 }
10329                 int32_t int_value = Smi::cast(element)->value();
10330                 double_storage->set(j, int_value);
10331                 j++;
10332               }
10333               break;
10334             }
10335             case FAST_HOLEY_ELEMENTS:
10336               ASSERT_EQ(0, length);
10337               break;
10338             default:
10339               UNREACHABLE();
10340           }
10341         }
10342         if (failure) break;
10343       }
10344       Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10345       Smi* length = Smi::FromInt(j);
10346       Handle<Map> map;
10347       map = isolate->factory()->GetElementsTransitionMap(array, kind);
10348       array->set_map(*map);
10349       array->set_length(length);
10350       array->set_elements(*double_storage);
10351       return *array;
10352     }
10353     // The backing storage array must have non-existing elements to preserve
10354     // holes across concat operations.
10355     storage = isolate->factory()->NewFixedArrayWithHoles(
10356         estimate_result_length);
10357   } else {
10358     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10359     uint32_t at_least_space_for = estimate_nof_elements +
10360                                   (estimate_nof_elements >> 2);
10361     storage = Handle<FixedArray>::cast(
10362         isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
10363   }
10364
10365   ArrayConcatVisitor visitor(isolate, storage, fast_case);
10366
10367   for (int i = 0; i < argument_count; i++) {
10368     Handle<Object> obj(elements->get(i), isolate);
10369     if (obj->IsJSArray()) {
10370       Handle<JSArray> array = Handle<JSArray>::cast(obj);
10371       if (!IterateElements(isolate, array, &visitor)) {
10372         return Failure::Exception();
10373       }
10374     } else {
10375       visitor.visit(0, obj);
10376       visitor.increase_index_offset(1);
10377     }
10378   }
10379
10380   if (visitor.exceeds_array_limit()) {
10381     return isolate->Throw(
10382         *isolate->factory()->NewRangeError("invalid_array_length",
10383                                            HandleVector<Object>(NULL, 0)));
10384   }
10385   return *visitor.ToArray();
10386 }
10387
10388
10389 // This will not allocate (flatten the string), but it may run
10390 // very slowly for very deeply nested ConsStrings.  For debugging use only.
10391 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10392   SealHandleScope shs(isolate);
10393   ASSERT(args.length() == 1);
10394
10395   CONVERT_ARG_CHECKED(String, string, 0);
10396   ConsStringIteratorOp op;
10397   StringCharacterStream stream(string, &op);
10398   while (stream.HasMore()) {
10399     uint16_t character = stream.GetNext();
10400     PrintF("%c", character);
10401   }
10402   return string;
10403 }
10404
10405
10406 // Moves all own elements of an object, that are below a limit, to positions
10407 // starting at zero. All undefined values are placed after non-undefined values,
10408 // and are followed by non-existing element. Does not change the length
10409 // property.
10410 // Returns the number of non-undefined elements collected.
10411 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10412   SealHandleScope shs(isolate);
10413   ASSERT(args.length() == 2);
10414   CONVERT_ARG_CHECKED(JSObject, object, 0);
10415   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10416   return object->PrepareElementsForSort(limit);
10417 }
10418
10419
10420 // Move contents of argument 0 (an array) to argument 1 (an array)
10421 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10422   SealHandleScope shs(isolate);
10423   ASSERT(args.length() == 2);
10424   CONVERT_ARG_CHECKED(JSArray, from, 0);
10425   CONVERT_ARG_CHECKED(JSArray, to, 1);
10426   from->ValidateElements();
10427   to->ValidateElements();
10428   FixedArrayBase* new_elements = from->elements();
10429   ElementsKind from_kind = from->GetElementsKind();
10430   MaybeObject* maybe_new_map;
10431   maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
10432   Object* new_map;
10433   if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10434   to->set_map_and_elements(Map::cast(new_map), new_elements);
10435   to->set_length(from->length());
10436   Object* obj;
10437   { MaybeObject* maybe_obj = from->ResetElements();
10438     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10439   }
10440   from->set_length(Smi::FromInt(0));
10441   to->ValidateElements();
10442   return to;
10443 }
10444
10445
10446 // How many elements does this object/array have?
10447 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10448   SealHandleScope shs(isolate);
10449   ASSERT(args.length() == 1);
10450   CONVERT_ARG_CHECKED(JSObject, object, 0);
10451   HeapObject* elements = object->elements();
10452   if (elements->IsDictionary()) {
10453     int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10454     return Smi::FromInt(result);
10455   } else if (object->IsJSArray()) {
10456     return JSArray::cast(object)->length();
10457   } else {
10458     return Smi::FromInt(FixedArray::cast(elements)->length());
10459   }
10460 }
10461
10462
10463 // Returns an array that tells you where in the [0, length) interval an array
10464 // might have elements.  Can either return an array of keys (positive integers
10465 // or undefined) or a number representing the positive length of an interval
10466 // starting at index 0.
10467 // Intervals can span over some keys that are not in the object.
10468 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10469   HandleScope scope(isolate);
10470   ASSERT(args.length() == 2);
10471   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10472   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10473   if (array->elements()->IsDictionary()) {
10474     Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10475     for (Handle<Object> p = array;
10476          !p->IsNull();
10477          p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
10478       if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
10479         // Bail out if we find a proxy or interceptor, likely not worth
10480         // collecting keys in that case.
10481         return *isolate->factory()->NewNumberFromUint(length);
10482       }
10483       Handle<JSObject> current = Handle<JSObject>::cast(p);
10484       Handle<FixedArray> current_keys =
10485           isolate->factory()->NewFixedArray(
10486               current->NumberOfLocalElements(NONE));
10487       current->GetLocalElementKeys(*current_keys, NONE);
10488       keys = UnionOfKeys(keys, current_keys);
10489     }
10490     // Erase any keys >= length.
10491     // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10492     // is changed to let this happen on the JS side.
10493     for (int i = 0; i < keys->length(); i++) {
10494       if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10495     }
10496     return *isolate->factory()->NewJSArrayWithElements(keys);
10497   } else {
10498     ASSERT(array->HasFastSmiOrObjectElements() ||
10499            array->HasFastDoubleElements());
10500     uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10501     return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10502   }
10503 }
10504
10505
10506 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10507   SealHandleScope shs(isolate);
10508   ASSERT(args.length() == 3);
10509   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
10510   CONVERT_ARG_CHECKED(Name, name, 1);
10511   CONVERT_SMI_ARG_CHECKED(flag, 2);
10512   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10513   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10514   return JSObject::cast(receiver)->LookupAccessor(name, component);
10515 }
10516
10517
10518 #ifdef ENABLE_DEBUGGER_SUPPORT
10519 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10520   SealHandleScope shs(isolate);
10521   ASSERT(args.length() == 0);
10522   return Execution::DebugBreakHelper();
10523 }
10524
10525
10526 // Helper functions for wrapping and unwrapping stack frame ids.
10527 static Smi* WrapFrameId(StackFrame::Id id) {
10528   ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10529   return Smi::FromInt(id >> 2);
10530 }
10531
10532
10533 static StackFrame::Id UnwrapFrameId(int wrapped) {
10534   return static_cast<StackFrame::Id>(wrapped << 2);
10535 }
10536
10537
10538 // Adds a JavaScript function as a debug event listener.
10539 // args[0]: debug event listener function to set or null or undefined for
10540 //          clearing the event listener function
10541 // args[1]: object supplied during callback
10542 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10543   SealHandleScope shs(isolate);
10544   ASSERT(args.length() == 2);
10545   RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10546                  args[0]->IsUndefined() ||
10547                  args[0]->IsNull());
10548   Handle<Object> callback = args.at<Object>(0);
10549   Handle<Object> data = args.at<Object>(1);
10550   isolate->debugger()->SetEventListener(callback, data);
10551
10552   return isolate->heap()->undefined_value();
10553 }
10554
10555
10556 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10557   SealHandleScope shs(isolate);
10558   ASSERT(args.length() == 0);
10559   isolate->stack_guard()->DebugBreak();
10560   return isolate->heap()->undefined_value();
10561 }
10562
10563
10564 static MaybeObject* DebugLookupResultValue(Heap* heap,
10565                                            Object* receiver,
10566                                            Name* name,
10567                                            LookupResult* result,
10568                                            bool* caught_exception) {
10569   Object* value;
10570   switch (result->type()) {
10571     case NORMAL:
10572       value = result->holder()->GetNormalizedProperty(result);
10573       if (value->IsTheHole()) {
10574         return heap->undefined_value();
10575       }
10576       return value;
10577     case FIELD: {
10578       Object* value;
10579       MaybeObject* maybe_value =
10580           JSObject::cast(result->holder())->FastPropertyAt(
10581               result->representation(),
10582               result->GetFieldIndex().field_index());
10583       if (!maybe_value->To(&value)) return maybe_value;
10584       if (value->IsTheHole()) {
10585         return heap->undefined_value();
10586       }
10587       return value;
10588     }
10589     case CONSTANT:
10590       return result->GetConstant();
10591     case CALLBACKS: {
10592       Object* structure = result->GetCallbackObject();
10593       if (structure->IsForeign() || structure->IsAccessorInfo()) {
10594         MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
10595             receiver, structure, name);
10596         if (!maybe_value->ToObject(&value)) {
10597           if (maybe_value->IsRetryAfterGC()) return maybe_value;
10598           ASSERT(maybe_value->IsException());
10599           maybe_value = heap->isolate()->pending_exception();
10600           heap->isolate()->clear_pending_exception();
10601           if (caught_exception != NULL) {
10602             *caught_exception = true;
10603           }
10604           return maybe_value;
10605         }
10606         return value;
10607       } else {
10608         return heap->undefined_value();
10609       }
10610     }
10611     case INTERCEPTOR:
10612     case TRANSITION:
10613       return heap->undefined_value();
10614     case HANDLER:
10615     case NONEXISTENT:
10616       UNREACHABLE();
10617       return heap->undefined_value();
10618   }
10619   UNREACHABLE();  // keep the compiler happy
10620   return heap->undefined_value();
10621 }
10622
10623
10624 // Get debugger related details for an object property.
10625 // args[0]: object holding property
10626 // args[1]: name of the property
10627 //
10628 // The array returned contains the following information:
10629 // 0: Property value
10630 // 1: Property details
10631 // 2: Property value is exception
10632 // 3: Getter function if defined
10633 // 4: Setter function if defined
10634 // Items 2-4 are only filled if the property has either a getter or a setter
10635 // defined through __defineGetter__ and/or __defineSetter__.
10636 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10637   HandleScope scope(isolate);
10638
10639   ASSERT(args.length() == 2);
10640
10641   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10642   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10643
10644   // Make sure to set the current context to the context before the debugger was
10645   // entered (if the debugger is entered). The reason for switching context here
10646   // is that for some property lookups (accessors and interceptors) callbacks
10647   // into the embedding application can occour, and the embedding application
10648   // could have the assumption that its own native context is the current
10649   // context and not some internal debugger context.
10650   SaveContext save(isolate);
10651   if (isolate->debug()->InDebugger()) {
10652     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10653   }
10654
10655   // Skip the global proxy as it has no properties and always delegates to the
10656   // real global object.
10657   if (obj->IsJSGlobalProxy()) {
10658     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10659   }
10660
10661
10662   // Check if the name is trivially convertible to an index and get the element
10663   // if so.
10664   uint32_t index;
10665   if (name->AsArrayIndex(&index)) {
10666     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10667     Object* element_or_char;
10668     { MaybeObject* maybe_element_or_char =
10669           Runtime::GetElementOrCharAt(isolate, obj, index);
10670       if (!maybe_element_or_char->ToObject(&element_or_char)) {
10671         return maybe_element_or_char;
10672       }
10673     }
10674     details->set(0, element_or_char);
10675     details->set(
10676         1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
10677     return *isolate->factory()->NewJSArrayWithElements(details);
10678   }
10679
10680   // Find the number of objects making up this.
10681   int length = LocalPrototypeChainLength(*obj);
10682
10683   // Try local lookup on each of the objects.
10684   Handle<JSObject> jsproto = obj;
10685   for (int i = 0; i < length; i++) {
10686     LookupResult result(isolate);
10687     jsproto->LocalLookup(*name, &result);
10688     if (result.IsFound()) {
10689       // LookupResult is not GC safe as it holds raw object pointers.
10690       // GC can happen later in this code so put the required fields into
10691       // local variables using handles when required for later use.
10692       Handle<Object> result_callback_obj;
10693       if (result.IsPropertyCallbacks()) {
10694         result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10695                                              isolate);
10696       }
10697       Smi* property_details = result.GetPropertyDetails().AsSmi();
10698       // DebugLookupResultValue can cause GC so details from LookupResult needs
10699       // to be copied to handles before this.
10700       bool caught_exception = false;
10701       Object* raw_value;
10702       { MaybeObject* maybe_raw_value =
10703             DebugLookupResultValue(isolate->heap(), *obj, *name,
10704                                    &result, &caught_exception);
10705         if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10706       }
10707       Handle<Object> value(raw_value, isolate);
10708
10709       // If the callback object is a fixed array then it contains JavaScript
10710       // getter and/or setter.
10711       bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
10712                                     result_callback_obj->IsAccessorPair();
10713       Handle<FixedArray> details =
10714           isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10715       details->set(0, *value);
10716       details->set(1, property_details);
10717       if (hasJavaScriptAccessors) {
10718         AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10719         details->set(2, isolate->heap()->ToBoolean(caught_exception));
10720         details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10721         details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10722       }
10723
10724       return *isolate->factory()->NewJSArrayWithElements(details);
10725     }
10726     if (i < length - 1) {
10727       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10728     }
10729   }
10730
10731   return isolate->heap()->undefined_value();
10732 }
10733
10734
10735 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10736   HandleScope scope(isolate);
10737
10738   ASSERT(args.length() == 2);
10739
10740   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10741   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10742
10743   LookupResult result(isolate);
10744   obj->Lookup(*name, &result);
10745   if (result.IsFound()) {
10746     return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10747   }
10748   return isolate->heap()->undefined_value();
10749 }
10750
10751
10752 // Return the property type calculated from the property details.
10753 // args[0]: smi with property details.
10754 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10755   SealHandleScope shs(isolate);
10756   ASSERT(args.length() == 1);
10757   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10758   return Smi::FromInt(static_cast<int>(details.type()));
10759 }
10760
10761
10762 // Return the property attribute calculated from the property details.
10763 // args[0]: smi with property details.
10764 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10765   SealHandleScope shs(isolate);
10766   ASSERT(args.length() == 1);
10767   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10768   return Smi::FromInt(static_cast<int>(details.attributes()));
10769 }
10770
10771
10772 // Return the property insertion index calculated from the property details.
10773 // args[0]: smi with property details.
10774 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10775   SealHandleScope shs(isolate);
10776   ASSERT(args.length() == 1);
10777   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10778   // TODO(verwaest): Depends on the type of details.
10779   return Smi::FromInt(details.dictionary_index());
10780 }
10781
10782
10783 // Return property value from named interceptor.
10784 // args[0]: object
10785 // args[1]: property name
10786 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10787   HandleScope scope(isolate);
10788   ASSERT(args.length() == 2);
10789   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10790   RUNTIME_ASSERT(obj->HasNamedInterceptor());
10791   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10792
10793   PropertyAttributes attributes;
10794   return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
10795 }
10796
10797
10798 // Return element value from indexed interceptor.
10799 // args[0]: object
10800 // args[1]: index
10801 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10802   HandleScope scope(isolate);
10803   ASSERT(args.length() == 2);
10804   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10805   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10806   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10807
10808   return obj->GetElementWithInterceptor(*obj, index);
10809 }
10810
10811
10812 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10813   SealHandleScope shs(isolate);
10814   ASSERT(args.length() >= 1);
10815   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10816   // Check that the break id is valid.
10817   if (isolate->debug()->break_id() == 0 ||
10818       break_id != isolate->debug()->break_id()) {
10819     return isolate->Throw(
10820         isolate->heap()->illegal_execution_state_string());
10821   }
10822
10823   return isolate->heap()->true_value();
10824 }
10825
10826
10827 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10828   HandleScope scope(isolate);
10829   ASSERT(args.length() == 1);
10830
10831   // Check arguments.
10832   Object* result;
10833   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10834       RUNTIME_ARGUMENTS(isolate, args));
10835     if (!maybe_result->ToObject(&result)) return maybe_result;
10836   }
10837
10838   // Count all frames which are relevant to debugging stack trace.
10839   int n = 0;
10840   StackFrame::Id id = isolate->debug()->break_frame_id();
10841   if (id == StackFrame::NO_ID) {
10842     // If there is no JavaScript stack frame count is 0.
10843     return Smi::FromInt(0);
10844   }
10845
10846   for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10847     n += it.frame()->GetInlineCount();
10848   }
10849   return Smi::FromInt(n);
10850 }
10851
10852
10853 class FrameInspector {
10854  public:
10855   FrameInspector(JavaScriptFrame* frame,
10856                  int inlined_jsframe_index,
10857                  Isolate* isolate)
10858       : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
10859     // Calculate the deoptimized frame.
10860     if (frame->is_optimized()) {
10861       deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
10862           frame, inlined_jsframe_index, isolate);
10863     }
10864     has_adapted_arguments_ = frame_->has_adapted_arguments();
10865     is_bottommost_ = inlined_jsframe_index == 0;
10866     is_optimized_ = frame_->is_optimized();
10867   }
10868
10869   ~FrameInspector() {
10870     // Get rid of the calculated deoptimized frame if any.
10871     if (deoptimized_frame_ != NULL) {
10872       Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
10873                                                   isolate_);
10874     }
10875   }
10876
10877   int GetParametersCount() {
10878     return is_optimized_
10879         ? deoptimized_frame_->parameters_count()
10880         : frame_->ComputeParametersCount();
10881   }
10882   int expression_count() { return deoptimized_frame_->expression_count(); }
10883   Object* GetFunction() {
10884     return is_optimized_
10885         ? deoptimized_frame_->GetFunction()
10886         : frame_->function();
10887   }
10888   Object* GetParameter(int index) {
10889     return is_optimized_
10890         ? deoptimized_frame_->GetParameter(index)
10891         : frame_->GetParameter(index);
10892   }
10893   Object* GetExpression(int index) {
10894     return is_optimized_
10895         ? deoptimized_frame_->GetExpression(index)
10896         : frame_->GetExpression(index);
10897   }
10898   int GetSourcePosition() {
10899     return is_optimized_
10900         ? deoptimized_frame_->GetSourcePosition()
10901         : frame_->LookupCode()->SourcePosition(frame_->pc());
10902   }
10903   bool IsConstructor() {
10904     return is_optimized_ && !is_bottommost_
10905         ? deoptimized_frame_->HasConstructStub()
10906         : frame_->IsConstructor();
10907   }
10908
10909   // To inspect all the provided arguments the frame might need to be
10910   // replaced with the arguments frame.
10911   void SetArgumentsFrame(JavaScriptFrame* frame) {
10912     ASSERT(has_adapted_arguments_);
10913     frame_ = frame;
10914     is_optimized_ = frame_->is_optimized();
10915     ASSERT(!is_optimized_);
10916   }
10917
10918  private:
10919   JavaScriptFrame* frame_;
10920   DeoptimizedFrameInfo* deoptimized_frame_;
10921   Isolate* isolate_;
10922   bool is_optimized_;
10923   bool is_bottommost_;
10924   bool has_adapted_arguments_;
10925
10926   DISALLOW_COPY_AND_ASSIGN(FrameInspector);
10927 };
10928
10929
10930 static const int kFrameDetailsFrameIdIndex = 0;
10931 static const int kFrameDetailsReceiverIndex = 1;
10932 static const int kFrameDetailsFunctionIndex = 2;
10933 static const int kFrameDetailsArgumentCountIndex = 3;
10934 static const int kFrameDetailsLocalCountIndex = 4;
10935 static const int kFrameDetailsSourcePositionIndex = 5;
10936 static const int kFrameDetailsConstructCallIndex = 6;
10937 static const int kFrameDetailsAtReturnIndex = 7;
10938 static const int kFrameDetailsFlagsIndex = 8;
10939 static const int kFrameDetailsFirstDynamicIndex = 9;
10940
10941
10942 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
10943                                              JavaScriptFrame* frame) {
10944   SaveContext* save = isolate->save_context();
10945   while (save != NULL && !save->IsBelowFrame(frame)) {
10946     save = save->prev();
10947   }
10948   ASSERT(save != NULL);
10949   return save;
10950 }
10951
10952
10953 // Return an array with frame details
10954 // args[0]: number: break id
10955 // args[1]: number: frame index
10956 //
10957 // The array returned contains the following information:
10958 // 0: Frame id
10959 // 1: Receiver
10960 // 2: Function
10961 // 3: Argument count
10962 // 4: Local count
10963 // 5: Source position
10964 // 6: Constructor call
10965 // 7: Is at return
10966 // 8: Flags
10967 // Arguments name, value
10968 // Locals name, value
10969 // Return value if any
10970 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
10971   HandleScope scope(isolate);
10972   ASSERT(args.length() == 2);
10973
10974   // Check arguments.
10975   Object* check;
10976   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10977       RUNTIME_ARGUMENTS(isolate, args));
10978     if (!maybe_check->ToObject(&check)) return maybe_check;
10979   }
10980   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10981   Heap* heap = isolate->heap();
10982
10983   // Find the relevant frame with the requested index.
10984   StackFrame::Id id = isolate->debug()->break_frame_id();
10985   if (id == StackFrame::NO_ID) {
10986     // If there are no JavaScript stack frames return undefined.
10987     return heap->undefined_value();
10988   }
10989
10990   int count = 0;
10991   JavaScriptFrameIterator it(isolate, id);
10992   for (; !it.done(); it.Advance()) {
10993     if (index < count + it.frame()->GetInlineCount()) break;
10994     count += it.frame()->GetInlineCount();
10995   }
10996   if (it.done()) return heap->undefined_value();
10997
10998   bool is_optimized = it.frame()->is_optimized();
10999
11000   int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
11001   if (is_optimized) {
11002     inlined_jsframe_index =
11003         it.frame()->GetInlineCount() - (index - count) - 1;
11004   }
11005   FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11006
11007   // Traverse the saved contexts chain to find the active context for the
11008   // selected frame.
11009   SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11010
11011   // Get the frame id.
11012   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11013
11014   // Find source position in unoptimized code.
11015   int position = frame_inspector.GetSourcePosition();
11016
11017   // Check for constructor frame.
11018   bool constructor = frame_inspector.IsConstructor();
11019
11020   // Get scope info and read from it for local variable information.
11021   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11022   Handle<SharedFunctionInfo> shared(function->shared());
11023   Handle<ScopeInfo> scope_info(shared->scope_info());
11024   ASSERT(*scope_info != ScopeInfo::Empty(isolate));
11025
11026   // Get the locals names and values into a temporary array.
11027   //
11028   // TODO(1240907): Hide compiler-introduced stack variables
11029   // (e.g. .result)?  For users of the debugger, they will probably be
11030   // confusing.
11031   Handle<FixedArray> locals =
11032       isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
11033
11034   // Fill in the values of the locals.
11035   int i = 0;
11036   for (; i < scope_info->StackLocalCount(); ++i) {
11037     // Use the value from the stack.
11038     locals->set(i * 2, scope_info->LocalName(i));
11039     locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
11040   }
11041   if (i < scope_info->LocalCount()) {
11042     // Get the context containing declarations.
11043     Handle<Context> context(
11044         Context::cast(it.frame()->context())->declaration_context());
11045     for (; i < scope_info->LocalCount(); ++i) {
11046       Handle<String> name(scope_info->LocalName(i));
11047       VariableMode mode;
11048       InitializationFlag init_flag;
11049       locals->set(i * 2, *name);
11050       locals->set(i * 2 + 1, context->get(
11051           scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
11052     }
11053   }
11054
11055   // Check whether this frame is positioned at return. If not top
11056   // frame or if the frame is optimized it cannot be at a return.
11057   bool at_return = false;
11058   if (!is_optimized && index == 0) {
11059     at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11060   }
11061
11062   // If positioned just before return find the value to be returned and add it
11063   // to the frame information.
11064   Handle<Object> return_value = isolate->factory()->undefined_value();
11065   if (at_return) {
11066     StackFrameIterator it2(isolate);
11067     Address internal_frame_sp = NULL;
11068     while (!it2.done()) {
11069       if (it2.frame()->is_internal()) {
11070         internal_frame_sp = it2.frame()->sp();
11071       } else {
11072         if (it2.frame()->is_java_script()) {
11073           if (it2.frame()->id() == it.frame()->id()) {
11074             // The internal frame just before the JavaScript frame contains the
11075             // value to return on top. A debug break at return will create an
11076             // internal frame to store the return value (eax/rax/r0) before
11077             // entering the debug break exit frame.
11078             if (internal_frame_sp != NULL) {
11079               return_value =
11080                   Handle<Object>(Memory::Object_at(internal_frame_sp),
11081                                  isolate);
11082               break;
11083             }
11084           }
11085         }
11086
11087         // Indicate that the previous frame was not an internal frame.
11088         internal_frame_sp = NULL;
11089       }
11090       it2.Advance();
11091     }
11092   }
11093
11094   // Now advance to the arguments adapter frame (if any). It contains all
11095   // the provided parameters whereas the function frame always have the number
11096   // of arguments matching the functions parameters. The rest of the
11097   // information (except for what is collected above) is the same.
11098   if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11099     it.AdvanceToArgumentsFrame();
11100     frame_inspector.SetArgumentsFrame(it.frame());
11101   }
11102
11103   // Find the number of arguments to fill. At least fill the number of
11104   // parameters for the function and fill more if more parameters are provided.
11105   int argument_count = scope_info->ParameterCount();
11106   if (argument_count < frame_inspector.GetParametersCount()) {
11107     argument_count = frame_inspector.GetParametersCount();
11108   }
11109
11110   // Calculate the size of the result.
11111   int details_size = kFrameDetailsFirstDynamicIndex +
11112                      2 * (argument_count + scope_info->LocalCount()) +
11113                      (at_return ? 1 : 0);
11114   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11115
11116   // Add the frame id.
11117   details->set(kFrameDetailsFrameIdIndex, *frame_id);
11118
11119   // Add the function (same as in function frame).
11120   details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11121
11122   // Add the arguments count.
11123   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11124
11125   // Add the locals count
11126   details->set(kFrameDetailsLocalCountIndex,
11127                Smi::FromInt(scope_info->LocalCount()));
11128
11129   // Add the source position.
11130   if (position != RelocInfo::kNoPosition) {
11131     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11132   } else {
11133     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11134   }
11135
11136   // Add the constructor information.
11137   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11138
11139   // Add the at return information.
11140   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11141
11142   // Add flags to indicate information on whether this frame is
11143   //   bit 0: invoked in the debugger context.
11144   //   bit 1: optimized frame.
11145   //   bit 2: inlined in optimized frame
11146   int flags = 0;
11147   if (*save->context() == *isolate->debug()->debug_context()) {
11148     flags |= 1 << 0;
11149   }
11150   if (is_optimized) {
11151     flags |= 1 << 1;
11152     flags |= inlined_jsframe_index << 2;
11153   }
11154   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11155
11156   // Fill the dynamic part.
11157   int details_index = kFrameDetailsFirstDynamicIndex;
11158
11159   // Add arguments name and value.
11160   for (int i = 0; i < argument_count; i++) {
11161     // Name of the argument.
11162     if (i < scope_info->ParameterCount()) {
11163       details->set(details_index++, scope_info->ParameterName(i));
11164     } else {
11165       details->set(details_index++, heap->undefined_value());
11166     }
11167
11168     // Parameter value.
11169     if (i < frame_inspector.GetParametersCount()) {
11170       // Get the value from the stack.
11171       details->set(details_index++, frame_inspector.GetParameter(i));
11172     } else {
11173       details->set(details_index++, heap->undefined_value());
11174     }
11175   }
11176
11177   // Add locals name and value from the temporary copy from the function frame.
11178   for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
11179     details->set(details_index++, locals->get(i));
11180   }
11181
11182   // Add the value being returned.
11183   if (at_return) {
11184     details->set(details_index++, *return_value);
11185   }
11186
11187   // Add the receiver (same as in function frame).
11188   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11189   // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11190   Handle<Object> receiver(it.frame()->receiver(), isolate);
11191   if (!receiver->IsJSObject() &&
11192       shared->is_classic_mode() &&
11193       !function->IsBuiltin()) {
11194     // If the receiver is not a JSObject and the function is not a
11195     // builtin or strict-mode we have hit an optimization where a
11196     // value object is not converted into a wrapped JS objects. To
11197     // hide this optimization from the debugger, we wrap the receiver
11198     // by creating correct wrapper object based on the calling frame's
11199     // native context.
11200     it.Advance();
11201     Handle<Context> calling_frames_native_context(
11202         Context::cast(Context::cast(it.frame()->context())->native_context()));
11203     ASSERT(!receiver->IsUndefined() && !receiver->IsNull());
11204     receiver =
11205         isolate->factory()->ToObject(receiver, calling_frames_native_context);
11206   }
11207   details->set(kFrameDetailsReceiverIndex, *receiver);
11208
11209   ASSERT_EQ(details_size, details_index);
11210   return *isolate->factory()->NewJSArrayWithElements(details);
11211 }
11212
11213
11214 // Create a plain JSObject which materializes the local scope for the specified
11215 // frame.
11216 static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
11217     Isolate* isolate,
11218     Handle<JSObject> target,
11219     Handle<JSFunction> function,
11220     FrameInspector* frame_inspector) {
11221   Handle<SharedFunctionInfo> shared(function->shared());
11222   Handle<ScopeInfo> scope_info(shared->scope_info());
11223
11224   // First fill all parameters.
11225   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11226     Handle<Object> value(i < frame_inspector->GetParametersCount()
11227                              ? frame_inspector->GetParameter(i)
11228                              : isolate->heap()->undefined_value(),
11229                          isolate);
11230     ASSERT(!value->IsTheHole());
11231
11232     RETURN_IF_EMPTY_HANDLE_VALUE(
11233         isolate,
11234         SetProperty(isolate,
11235                     target,
11236                     Handle<String>(scope_info->ParameterName(i)),
11237                     value,
11238                     NONE,
11239                     kNonStrictMode),
11240         Handle<JSObject>());
11241   }
11242
11243   // Second fill all stack locals.
11244   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11245     Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11246     if (value->IsTheHole()) continue;
11247
11248     RETURN_IF_EMPTY_HANDLE_VALUE(
11249         isolate,
11250         SetProperty(isolate,
11251                     target,
11252                     Handle<String>(scope_info->StackLocalName(i)),
11253                     value,
11254                     NONE,
11255                     kNonStrictMode),
11256         Handle<JSObject>());
11257   }
11258
11259   return target;
11260 }
11261
11262
11263 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11264                                                     Handle<JSObject> target,
11265                                                     Handle<JSFunction> function,
11266                                                     JavaScriptFrame* frame,
11267                                                     int inlined_jsframe_index) {
11268   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11269     // Optimized frames are not supported.
11270     // TODO(yangguo): make sure all code deoptimized when debugger is active
11271     //                and assert that this cannot happen.
11272     return;
11273   }
11274
11275   Handle<SharedFunctionInfo> shared(function->shared());
11276   Handle<ScopeInfo> scope_info(shared->scope_info());
11277
11278   // Parameters.
11279   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11280     ASSERT(!frame->GetParameter(i)->IsTheHole());
11281     HandleScope scope(isolate);
11282     Handle<Object> value = GetProperty(
11283         isolate, target, Handle<String>(scope_info->ParameterName(i)));
11284     frame->SetParameterValue(i, *value);
11285   }
11286
11287   // Stack locals.
11288   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11289     if (frame->GetExpression(i)->IsTheHole()) continue;
11290     HandleScope scope(isolate);
11291     Handle<Object> value = GetProperty(
11292         isolate, target, Handle<String>(scope_info->StackLocalName(i)));
11293     frame->SetExpression(i, *value);
11294   }
11295 }
11296
11297
11298 static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
11299                                                 Handle<JSObject> target,
11300                                                 Handle<JSFunction> function,
11301                                                 JavaScriptFrame* frame) {
11302   HandleScope scope(isolate);
11303   Handle<SharedFunctionInfo> shared(function->shared());
11304   Handle<ScopeInfo> scope_info(shared->scope_info());
11305
11306   if (!scope_info->HasContext()) return target;
11307
11308   // Third fill all context locals.
11309   Handle<Context> frame_context(Context::cast(frame->context()));
11310   Handle<Context> function_context(frame_context->declaration_context());
11311   if (!scope_info->CopyContextLocalsToScopeObject(
11312           isolate, function_context, target)) {
11313     return Handle<JSObject>();
11314   }
11315
11316   // Finally copy any properties from the function context extension.
11317   // These will be variables introduced by eval.
11318   if (function_context->closure() == *function) {
11319     if (function_context->has_extension() &&
11320         !function_context->IsNativeContext()) {
11321       Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11322       bool threw = false;
11323       Handle<FixedArray> keys =
11324           GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11325       if (threw) return Handle<JSObject>();
11326
11327       for (int i = 0; i < keys->length(); i++) {
11328         // Names of variables introduced by eval are strings.
11329         ASSERT(keys->get(i)->IsString());
11330         Handle<String> key(String::cast(keys->get(i)));
11331         RETURN_IF_EMPTY_HANDLE_VALUE(
11332             isolate,
11333             SetProperty(isolate,
11334                         target,
11335                         key,
11336                         GetProperty(isolate, ext, key),
11337                         NONE,
11338                         kNonStrictMode),
11339             Handle<JSObject>());
11340       }
11341     }
11342   }
11343
11344   return target;
11345 }
11346
11347
11348 static Handle<JSObject> MaterializeLocalScope(
11349     Isolate* isolate,
11350     JavaScriptFrame* frame,
11351     int inlined_jsframe_index) {
11352   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11353   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11354
11355   Handle<JSObject> local_scope =
11356       isolate->factory()->NewJSObject(isolate->object_function());
11357   local_scope = MaterializeStackLocalsWithFrameInspector(
11358                     isolate, local_scope, function, &frame_inspector);
11359   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
11360
11361   return MaterializeLocalContext(isolate, local_scope, function, frame);
11362 }
11363
11364
11365 // Set the context local variable value.
11366 static bool SetContextLocalValue(Isolate* isolate,
11367                                  Handle<ScopeInfo> scope_info,
11368                                  Handle<Context> context,
11369                                  Handle<String> variable_name,
11370                                  Handle<Object> new_value) {
11371   for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11372     Handle<String> next_name(scope_info->ContextLocalName(i));
11373     if (variable_name->Equals(*next_name)) {
11374       VariableMode mode;
11375       InitializationFlag init_flag;
11376       int context_index =
11377           scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
11378       context->set(context_index, *new_value);
11379       return true;
11380     }
11381   }
11382
11383   return false;
11384 }
11385
11386
11387 static bool SetLocalVariableValue(Isolate* isolate,
11388                                   JavaScriptFrame* frame,
11389                                   int inlined_jsframe_index,
11390                                   Handle<String> variable_name,
11391                                   Handle<Object> new_value) {
11392   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11393     // Optimized frames are not supported.
11394     return false;
11395   }
11396
11397   Handle<JSFunction> function(frame->function());
11398   Handle<SharedFunctionInfo> shared(function->shared());
11399   Handle<ScopeInfo> scope_info(shared->scope_info());
11400
11401   bool default_result = false;
11402
11403   // Parameters.
11404   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11405     if (scope_info->ParameterName(i)->Equals(*variable_name)) {
11406       frame->SetParameterValue(i, *new_value);
11407       // Argument might be shadowed in heap context, don't stop here.
11408       default_result = true;
11409     }
11410   }
11411
11412   // Stack locals.
11413   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11414     if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
11415       frame->SetExpression(i, *new_value);
11416       return true;
11417     }
11418   }
11419
11420   if (scope_info->HasContext()) {
11421     // Context locals.
11422     Handle<Context> frame_context(Context::cast(frame->context()));
11423     Handle<Context> function_context(frame_context->declaration_context());
11424     if (SetContextLocalValue(
11425         isolate, scope_info, function_context, variable_name, new_value)) {
11426       return true;
11427     }
11428
11429     // Function context extension. These are variables introduced by eval.
11430     if (function_context->closure() == *function) {
11431       if (function_context->has_extension() &&
11432           !function_context->IsNativeContext()) {
11433         Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11434
11435         if (ext->HasProperty(*variable_name)) {
11436           // We don't expect this to do anything except replacing
11437           // property value.
11438           SetProperty(isolate,
11439                       ext,
11440                       variable_name,
11441                       new_value,
11442                       NONE,
11443                       kNonStrictMode);
11444           return true;
11445         }
11446       }
11447     }
11448   }
11449
11450   return default_result;
11451 }
11452
11453
11454 // Create a plain JSObject which materializes the closure content for the
11455 // context.
11456 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
11457                                            Handle<Context> context) {
11458   ASSERT(context->IsFunctionContext());
11459
11460   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11461   Handle<ScopeInfo> scope_info(shared->scope_info());
11462
11463   // Allocate and initialize a JSObject with all the content of this function
11464   // closure.
11465   Handle<JSObject> closure_scope =
11466       isolate->factory()->NewJSObject(isolate->object_function());
11467
11468   // Fill all context locals to the context extension.
11469   if (!scope_info->CopyContextLocalsToScopeObject(
11470           isolate, context, closure_scope)) {
11471     return Handle<JSObject>();
11472   }
11473
11474   // Finally copy any properties from the function context extension. This will
11475   // be variables introduced by eval.
11476   if (context->has_extension()) {
11477     Handle<JSObject> ext(JSObject::cast(context->extension()));
11478     bool threw = false;
11479     Handle<FixedArray> keys =
11480         GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11481     if (threw) return Handle<JSObject>();
11482
11483     for (int i = 0; i < keys->length(); i++) {
11484       // Names of variables introduced by eval are strings.
11485       ASSERT(keys->get(i)->IsString());
11486       Handle<String> key(String::cast(keys->get(i)));
11487        RETURN_IF_EMPTY_HANDLE_VALUE(
11488           isolate,
11489           SetProperty(isolate,
11490                       closure_scope,
11491                       key,
11492                       GetProperty(isolate, ext, key),
11493                       NONE,
11494                       kNonStrictMode),
11495           Handle<JSObject>());
11496     }
11497   }
11498
11499   return closure_scope;
11500 }
11501
11502
11503 // This method copies structure of MaterializeClosure method above.
11504 static bool SetClosureVariableValue(Isolate* isolate,
11505                                     Handle<Context> context,
11506                                     Handle<String> variable_name,
11507                                     Handle<Object> new_value) {
11508   ASSERT(context->IsFunctionContext());
11509
11510   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11511   Handle<ScopeInfo> scope_info(shared->scope_info());
11512
11513   // Context locals to the context extension.
11514   if (SetContextLocalValue(
11515           isolate, scope_info, context, variable_name, new_value)) {
11516     return true;
11517   }
11518
11519   // Properties from the function context extension. This will
11520   // be variables introduced by eval.
11521   if (context->has_extension()) {
11522     Handle<JSObject> ext(JSObject::cast(context->extension()));
11523     if (ext->HasProperty(*variable_name)) {
11524       // We don't expect this to do anything except replacing property value.
11525       SetProperty(isolate,
11526                   ext,
11527                   variable_name,
11528                   new_value,
11529                   NONE,
11530                   kNonStrictMode);
11531       return true;
11532     }
11533   }
11534
11535   return false;
11536 }
11537
11538
11539 // Create a plain JSObject which materializes the scope for the specified
11540 // catch context.
11541 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11542                                               Handle<Context> context) {
11543   ASSERT(context->IsCatchContext());
11544   Handle<String> name(String::cast(context->extension()));
11545   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11546                                isolate);
11547   Handle<JSObject> catch_scope =
11548       isolate->factory()->NewJSObject(isolate->object_function());
11549   RETURN_IF_EMPTY_HANDLE_VALUE(
11550       isolate,
11551       SetProperty(isolate,
11552                   catch_scope,
11553                   name,
11554                   thrown_object,
11555                   NONE,
11556                   kNonStrictMode),
11557       Handle<JSObject>());
11558   return catch_scope;
11559 }
11560
11561
11562 static bool SetCatchVariableValue(Isolate* isolate,
11563                                   Handle<Context> context,
11564                                   Handle<String> variable_name,
11565                                   Handle<Object> new_value) {
11566   ASSERT(context->IsCatchContext());
11567   Handle<String> name(String::cast(context->extension()));
11568   if (!name->Equals(*variable_name)) {
11569     return false;
11570   }
11571   context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11572   return true;
11573 }
11574
11575
11576 // Create a plain JSObject which materializes the block scope for the specified
11577 // block context.
11578 static Handle<JSObject> MaterializeBlockScope(
11579     Isolate* isolate,
11580     Handle<Context> context) {
11581   ASSERT(context->IsBlockContext());
11582   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11583
11584   // Allocate and initialize a JSObject with all the arguments, stack locals
11585   // heap locals and extension properties of the debugged function.
11586   Handle<JSObject> block_scope =
11587       isolate->factory()->NewJSObject(isolate->object_function());
11588
11589   // Fill all context locals.
11590   if (!scope_info->CopyContextLocalsToScopeObject(
11591           isolate, context, block_scope)) {
11592     return Handle<JSObject>();
11593   }
11594
11595   return block_scope;
11596 }
11597
11598
11599 // Create a plain JSObject which materializes the module scope for the specified
11600 // module context.
11601 static Handle<JSObject> MaterializeModuleScope(
11602     Isolate* isolate,
11603     Handle<Context> context) {
11604   ASSERT(context->IsModuleContext());
11605   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11606
11607   // Allocate and initialize a JSObject with all the members of the debugged
11608   // module.
11609   Handle<JSObject> module_scope =
11610       isolate->factory()->NewJSObject(isolate->object_function());
11611
11612   // Fill all context locals.
11613   if (!scope_info->CopyContextLocalsToScopeObject(
11614           isolate, context, module_scope)) {
11615     return Handle<JSObject>();
11616   }
11617
11618   return module_scope;
11619 }
11620
11621
11622 // Iterate over the actual scopes visible from a stack frame or from a closure.
11623 // The iteration proceeds from the innermost visible nested scope outwards.
11624 // All scopes are backed by an actual context except the local scope,
11625 // which is inserted "artificially" in the context chain.
11626 class ScopeIterator {
11627  public:
11628   enum ScopeType {
11629     ScopeTypeGlobal = 0,
11630     ScopeTypeLocal,
11631     ScopeTypeWith,
11632     ScopeTypeClosure,
11633     ScopeTypeCatch,
11634     ScopeTypeBlock,
11635     ScopeTypeModule
11636   };
11637
11638   ScopeIterator(Isolate* isolate,
11639                 JavaScriptFrame* frame,
11640                 int inlined_jsframe_index)
11641     : isolate_(isolate),
11642       frame_(frame),
11643       inlined_jsframe_index_(inlined_jsframe_index),
11644       function_(frame->function()),
11645       context_(Context::cast(frame->context())),
11646       nested_scope_chain_(4),
11647       failed_(false) {
11648
11649     // Catch the case when the debugger stops in an internal function.
11650     Handle<SharedFunctionInfo> shared_info(function_->shared());
11651     Handle<ScopeInfo> scope_info(shared_info->scope_info());
11652     if (shared_info->script() == isolate->heap()->undefined_value()) {
11653       while (context_->closure() == *function_) {
11654         context_ = Handle<Context>(context_->previous(), isolate_);
11655       }
11656       return;
11657     }
11658
11659     // Get the debug info (create it if it does not exist).
11660     if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
11661       // Return if ensuring debug info failed.
11662       return;
11663     }
11664     Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11665
11666     // Find the break point where execution has stopped.
11667     BreakLocationIterator break_location_iterator(debug_info,
11668                                                   ALL_BREAK_LOCATIONS);
11669     // pc points to the instruction after the current one, possibly a break
11670     // location as well. So the "- 1" to exclude it from the search.
11671     break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
11672     if (break_location_iterator.IsExit()) {
11673       // We are within the return sequence. At the momemt it is not possible to
11674       // get a source position which is consistent with the current scope chain.
11675       // Thus all nested with, catch and block contexts are skipped and we only
11676       // provide the function scope.
11677       if (scope_info->HasContext()) {
11678         context_ = Handle<Context>(context_->declaration_context(), isolate_);
11679       } else {
11680         while (context_->closure() == *function_) {
11681           context_ = Handle<Context>(context_->previous(), isolate_);
11682         }
11683       }
11684       if (scope_info->scope_type() != EVAL_SCOPE) {
11685         nested_scope_chain_.Add(scope_info);
11686       }
11687     } else {
11688       // Reparse the code and analyze the scopes.
11689       Handle<Script> script(Script::cast(shared_info->script()));
11690       Scope* scope = NULL;
11691
11692       // Check whether we are in global, eval or function code.
11693       Handle<ScopeInfo> scope_info(shared_info->scope_info());
11694       if (scope_info->scope_type() != FUNCTION_SCOPE) {
11695         // Global or eval code.
11696         CompilationInfoWithZone info(script);
11697         if (scope_info->scope_type() == GLOBAL_SCOPE) {
11698           info.MarkAsGlobal();
11699         } else {
11700           ASSERT(scope_info->scope_type() == EVAL_SCOPE);
11701           info.MarkAsEval();
11702           info.SetContext(Handle<Context>(function_->context()));
11703         }
11704         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11705           scope = info.function()->scope();
11706         }
11707         RetrieveScopeChain(scope, shared_info);
11708       } else {
11709         // Function code
11710         CompilationInfoWithZone info(shared_info);
11711         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11712           scope = info.function()->scope();
11713         }
11714         RetrieveScopeChain(scope, shared_info);
11715       }
11716     }
11717   }
11718
11719   ScopeIterator(Isolate* isolate,
11720                 Handle<JSFunction> function)
11721     : isolate_(isolate),
11722       frame_(NULL),
11723       inlined_jsframe_index_(0),
11724       function_(function),
11725       context_(function->context()),
11726       failed_(false) {
11727     if (function->IsBuiltin()) {
11728       context_ = Handle<Context>();
11729     }
11730   }
11731
11732   // More scopes?
11733   bool Done() {
11734     ASSERT(!failed_);
11735     return context_.is_null();
11736   }
11737
11738   bool Failed() { return failed_; }
11739
11740   // Move to the next scope.
11741   void Next() {
11742     ASSERT(!failed_);
11743     ScopeType scope_type = Type();
11744     if (scope_type == ScopeTypeGlobal) {
11745       // The global scope is always the last in the chain.
11746       ASSERT(context_->IsNativeContext());
11747       context_ = Handle<Context>();
11748       return;
11749     }
11750     if (nested_scope_chain_.is_empty()) {
11751       context_ = Handle<Context>(context_->previous(), isolate_);
11752     } else {
11753       if (nested_scope_chain_.last()->HasContext()) {
11754         ASSERT(context_->previous() != NULL);
11755         context_ = Handle<Context>(context_->previous(), isolate_);
11756       }
11757       nested_scope_chain_.RemoveLast();
11758     }
11759   }
11760
11761   // Return the type of the current scope.
11762   ScopeType Type() {
11763     ASSERT(!failed_);
11764     if (!nested_scope_chain_.is_empty()) {
11765       Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11766       switch (scope_info->scope_type()) {
11767         case FUNCTION_SCOPE:
11768           ASSERT(context_->IsFunctionContext() ||
11769                  !scope_info->HasContext());
11770           return ScopeTypeLocal;
11771         case MODULE_SCOPE:
11772           ASSERT(context_->IsModuleContext());
11773           return ScopeTypeModule;
11774         case GLOBAL_SCOPE:
11775           ASSERT(context_->IsNativeContext());
11776           return ScopeTypeGlobal;
11777         case WITH_SCOPE:
11778           ASSERT(context_->IsWithContext());
11779           return ScopeTypeWith;
11780         case CATCH_SCOPE:
11781           ASSERT(context_->IsCatchContext());
11782           return ScopeTypeCatch;
11783         case BLOCK_SCOPE:
11784           ASSERT(!scope_info->HasContext() ||
11785                  context_->IsBlockContext());
11786           return ScopeTypeBlock;
11787         case EVAL_SCOPE:
11788           UNREACHABLE();
11789       }
11790     }
11791     if (context_->IsNativeContext()) {
11792       ASSERT(context_->global_object()->IsGlobalObject());
11793       return ScopeTypeGlobal;
11794     }
11795     if (context_->IsFunctionContext()) {
11796       return ScopeTypeClosure;
11797     }
11798     if (context_->IsCatchContext()) {
11799       return ScopeTypeCatch;
11800     }
11801     if (context_->IsBlockContext()) {
11802       return ScopeTypeBlock;
11803     }
11804     if (context_->IsModuleContext()) {
11805       return ScopeTypeModule;
11806     }
11807     ASSERT(context_->IsWithContext());
11808     return ScopeTypeWith;
11809   }
11810
11811   // Return the JavaScript object with the content of the current scope.
11812   Handle<JSObject> ScopeObject() {
11813     ASSERT(!failed_);
11814     switch (Type()) {
11815       case ScopeIterator::ScopeTypeGlobal:
11816         return Handle<JSObject>(CurrentContext()->global_object());
11817       case ScopeIterator::ScopeTypeLocal:
11818         // Materialize the content of the local scope into a JSObject.
11819         ASSERT(nested_scope_chain_.length() == 1);
11820         return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11821       case ScopeIterator::ScopeTypeWith:
11822         // Return the with object.
11823         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11824       case ScopeIterator::ScopeTypeCatch:
11825         return MaterializeCatchScope(isolate_, CurrentContext());
11826       case ScopeIterator::ScopeTypeClosure:
11827         // Materialize the content of the closure scope into a JSObject.
11828         return MaterializeClosure(isolate_, CurrentContext());
11829       case ScopeIterator::ScopeTypeBlock:
11830         return MaterializeBlockScope(isolate_, CurrentContext());
11831       case ScopeIterator::ScopeTypeModule:
11832         return MaterializeModuleScope(isolate_, CurrentContext());
11833     }
11834     UNREACHABLE();
11835     return Handle<JSObject>();
11836   }
11837
11838   bool SetVariableValue(Handle<String> variable_name,
11839                         Handle<Object> new_value) {
11840     ASSERT(!failed_);
11841     switch (Type()) {
11842       case ScopeIterator::ScopeTypeGlobal:
11843         break;
11844       case ScopeIterator::ScopeTypeLocal:
11845         return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
11846             variable_name, new_value);
11847       case ScopeIterator::ScopeTypeWith:
11848         break;
11849       case ScopeIterator::ScopeTypeCatch:
11850         return SetCatchVariableValue(isolate_, CurrentContext(),
11851             variable_name, new_value);
11852       case ScopeIterator::ScopeTypeClosure:
11853         return SetClosureVariableValue(isolate_, CurrentContext(),
11854             variable_name, new_value);
11855       case ScopeIterator::ScopeTypeBlock:
11856         // TODO(2399): should we implement it?
11857         break;
11858       case ScopeIterator::ScopeTypeModule:
11859         // TODO(2399): should we implement it?
11860         break;
11861     }
11862     return false;
11863   }
11864
11865   Handle<ScopeInfo> CurrentScopeInfo() {
11866     ASSERT(!failed_);
11867     if (!nested_scope_chain_.is_empty()) {
11868       return nested_scope_chain_.last();
11869     } else if (context_->IsBlockContext()) {
11870       return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
11871     } else if (context_->IsFunctionContext()) {
11872       return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
11873     }
11874     return Handle<ScopeInfo>::null();
11875   }
11876
11877   // Return the context for this scope. For the local context there might not
11878   // be an actual context.
11879   Handle<Context> CurrentContext() {
11880     ASSERT(!failed_);
11881     if (Type() == ScopeTypeGlobal ||
11882         nested_scope_chain_.is_empty()) {
11883       return context_;
11884     } else if (nested_scope_chain_.last()->HasContext()) {
11885       return context_;
11886     } else {
11887       return Handle<Context>();
11888     }
11889   }
11890
11891 #ifdef DEBUG
11892   // Debug print of the content of the current scope.
11893   void DebugPrint() {
11894     ASSERT(!failed_);
11895     switch (Type()) {
11896       case ScopeIterator::ScopeTypeGlobal:
11897         PrintF("Global:\n");
11898         CurrentContext()->Print();
11899         break;
11900
11901       case ScopeIterator::ScopeTypeLocal: {
11902         PrintF("Local:\n");
11903         function_->shared()->scope_info()->Print();
11904         if (!CurrentContext().is_null()) {
11905           CurrentContext()->Print();
11906           if (CurrentContext()->has_extension()) {
11907             Handle<Object> extension(CurrentContext()->extension(), isolate_);
11908             if (extension->IsJSContextExtensionObject()) {
11909               extension->Print();
11910             }
11911           }
11912         }
11913         break;
11914       }
11915
11916       case ScopeIterator::ScopeTypeWith:
11917         PrintF("With:\n");
11918         CurrentContext()->extension()->Print();
11919         break;
11920
11921       case ScopeIterator::ScopeTypeCatch:
11922         PrintF("Catch:\n");
11923         CurrentContext()->extension()->Print();
11924         CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
11925         break;
11926
11927       case ScopeIterator::ScopeTypeClosure:
11928         PrintF("Closure:\n");
11929         CurrentContext()->Print();
11930         if (CurrentContext()->has_extension()) {
11931           Handle<Object> extension(CurrentContext()->extension(), isolate_);
11932           if (extension->IsJSContextExtensionObject()) {
11933             extension->Print();
11934           }
11935         }
11936         break;
11937
11938       default:
11939         UNREACHABLE();
11940     }
11941     PrintF("\n");
11942   }
11943 #endif
11944
11945  private:
11946   Isolate* isolate_;
11947   JavaScriptFrame* frame_;
11948   int inlined_jsframe_index_;
11949   Handle<JSFunction> function_;
11950   Handle<Context> context_;
11951   List<Handle<ScopeInfo> > nested_scope_chain_;
11952   bool failed_;
11953
11954   void RetrieveScopeChain(Scope* scope,
11955                           Handle<SharedFunctionInfo> shared_info) {
11956     if (scope != NULL) {
11957       int source_position = shared_info->code()->SourcePosition(frame_->pc());
11958       scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
11959     } else {
11960       // A failed reparse indicates that the preparser has diverged from the
11961       // parser or that the preparse data given to the initial parse has been
11962       // faulty. We fail in debug mode but in release mode we only provide the
11963       // information we get from the context chain but nothing about
11964       // completely stack allocated scopes or stack allocated locals.
11965       // Or it could be due to stack overflow.
11966       ASSERT(isolate_->has_pending_exception());
11967       failed_ = true;
11968     }
11969   }
11970
11971   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11972 };
11973
11974
11975 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11976   HandleScope scope(isolate);
11977   ASSERT(args.length() == 2);
11978
11979   // Check arguments.
11980   Object* check;
11981   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11982       RUNTIME_ARGUMENTS(isolate, args));
11983     if (!maybe_check->ToObject(&check)) return maybe_check;
11984   }
11985   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11986
11987   // Get the frame where the debugging is performed.
11988   StackFrame::Id id = UnwrapFrameId(wrapped_id);
11989   JavaScriptFrameIterator it(isolate, id);
11990   JavaScriptFrame* frame = it.frame();
11991
11992   // Count the visible scopes.
11993   int n = 0;
11994   for (ScopeIterator it(isolate, frame, 0);
11995        !it.Done();
11996        it.Next()) {
11997     n++;
11998   }
11999
12000   return Smi::FromInt(n);
12001 }
12002
12003
12004 // Returns the list of step-in positions (text offset) in a function of the
12005 // stack frame in a range from the current debug break position to the end
12006 // of the corresponding statement.
12007 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
12008   HandleScope scope(isolate);
12009   ASSERT(args.length() == 2);
12010
12011   // Check arguments.
12012   Object* check;
12013   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12014       RUNTIME_ARGUMENTS(isolate, args));
12015     if (!maybe_check->ToObject(&check)) return maybe_check;
12016   }
12017   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12018
12019   // Get the frame where the debugging is performed.
12020   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12021   JavaScriptFrameIterator frame_it(isolate, id);
12022   JavaScriptFrame* frame = frame_it.frame();
12023
12024   Handle<JSFunction> fun =
12025       Handle<JSFunction>(frame->function());
12026   Handle<SharedFunctionInfo> shared =
12027       Handle<SharedFunctionInfo>(fun->shared());
12028
12029   if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12030     return isolate->heap()->undefined_value();
12031   }
12032
12033   Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12034
12035   int len = 0;
12036   Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12037   // Find the break point where execution has stopped.
12038   BreakLocationIterator break_location_iterator(debug_info,
12039                                                 ALL_BREAK_LOCATIONS);
12040
12041   break_location_iterator.FindBreakLocationFromAddress(frame->pc());
12042   int current_statement_pos = break_location_iterator.statement_position();
12043
12044   while (!break_location_iterator.Done()) {
12045     if (break_location_iterator.pc() > frame->pc()) {
12046       if (break_location_iterator.IsStepInLocation(isolate)) {
12047         Smi* position_value = Smi::FromInt(break_location_iterator.position());
12048         JSObject::SetElement(array, len,
12049             Handle<Object>(position_value, isolate),
12050             NONE, kNonStrictMode);
12051         len++;
12052       }
12053     }
12054     // Advance iterator.
12055     break_location_iterator.Next();
12056     if (current_statement_pos !=
12057         break_location_iterator.statement_position()) {
12058       break;
12059     }
12060   }
12061   return *array;
12062 }
12063
12064
12065 static const int kScopeDetailsTypeIndex = 0;
12066 static const int kScopeDetailsObjectIndex = 1;
12067 static const int kScopeDetailsSize = 2;
12068
12069
12070 static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
12071     ScopeIterator* it) {
12072   // Calculate the size of the result.
12073   int details_size = kScopeDetailsSize;
12074   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12075
12076   // Fill in scope details.
12077   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12078   Handle<JSObject> scope_object = it->ScopeObject();
12079   RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
12080   details->set(kScopeDetailsObjectIndex, *scope_object);
12081
12082   return *isolate->factory()->NewJSArrayWithElements(details);
12083 }
12084
12085
12086 // Return an array with scope details
12087 // args[0]: number: break id
12088 // args[1]: number: frame index
12089 // args[2]: number: inlined frame index
12090 // args[3]: number: scope index
12091 //
12092 // The array returned contains the following information:
12093 // 0: Scope type
12094 // 1: Scope object
12095 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
12096   HandleScope scope(isolate);
12097   ASSERT(args.length() == 4);
12098
12099   // Check arguments.
12100   Object* check;
12101   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12102       RUNTIME_ARGUMENTS(isolate, args));
12103     if (!maybe_check->ToObject(&check)) return maybe_check;
12104   }
12105   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12106   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12107   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12108
12109   // Get the frame where the debugging is performed.
12110   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12111   JavaScriptFrameIterator frame_it(isolate, id);
12112   JavaScriptFrame* frame = frame_it.frame();
12113
12114   // Find the requested scope.
12115   int n = 0;
12116   ScopeIterator it(isolate, frame, inlined_jsframe_index);
12117   for (; !it.Done() && n < index; it.Next()) {
12118     n++;
12119   }
12120   if (it.Done()) {
12121     return isolate->heap()->undefined_value();
12122   }
12123   return MaterializeScopeDetails(isolate, &it);
12124 }
12125
12126
12127 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
12128   HandleScope scope(isolate);
12129   ASSERT(args.length() == 1);
12130
12131   // Check arguments.
12132   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12133
12134   // Count the visible scopes.
12135   int n = 0;
12136   for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12137     n++;
12138   }
12139
12140   return Smi::FromInt(n);
12141 }
12142
12143
12144 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
12145   HandleScope scope(isolate);
12146   ASSERT(args.length() == 2);
12147
12148   // Check arguments.
12149   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12150   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12151
12152   // Find the requested scope.
12153   int n = 0;
12154   ScopeIterator it(isolate, fun);
12155   for (; !it.Done() && n < index; it.Next()) {
12156     n++;
12157   }
12158   if (it.Done()) {
12159     return isolate->heap()->undefined_value();
12160   }
12161
12162   return MaterializeScopeDetails(isolate, &it);
12163 }
12164
12165
12166 static bool SetScopeVariableValue(ScopeIterator* it, int index,
12167                                   Handle<String> variable_name,
12168                                   Handle<Object> new_value) {
12169   for (int n = 0; !it->Done() && n < index; it->Next()) {
12170     n++;
12171   }
12172   if (it->Done()) {
12173     return false;
12174   }
12175   return it->SetVariableValue(variable_name, new_value);
12176 }
12177
12178
12179 // Change variable value in closure or local scope
12180 // args[0]: number or JsFunction: break id or function
12181 // args[1]: number: frame index (when arg[0] is break id)
12182 // args[2]: number: inlined frame index (when arg[0] is break id)
12183 // args[3]: number: scope index
12184 // args[4]: string: variable name
12185 // args[5]: object: new value
12186 //
12187 // Return true if success and false otherwise
12188 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
12189   HandleScope scope(isolate);
12190   ASSERT(args.length() == 6);
12191
12192   // Check arguments.
12193   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12194   CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12195   Handle<Object> new_value = args.at<Object>(5);
12196
12197   bool res;
12198   if (args[0]->IsNumber()) {
12199     Object* check;
12200     { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12201         RUNTIME_ARGUMENTS(isolate, args));
12202       if (!maybe_check->ToObject(&check)) return maybe_check;
12203     }
12204     CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12205     CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12206
12207     // Get the frame where the debugging is performed.
12208     StackFrame::Id id = UnwrapFrameId(wrapped_id);
12209     JavaScriptFrameIterator frame_it(isolate, id);
12210     JavaScriptFrame* frame = frame_it.frame();
12211
12212     ScopeIterator it(isolate, frame, inlined_jsframe_index);
12213     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12214   } else {
12215     CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12216     ScopeIterator it(isolate, fun);
12217     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12218   }
12219
12220   return isolate->heap()->ToBoolean(res);
12221 }
12222
12223
12224 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
12225   HandleScope scope(isolate);
12226   ASSERT(args.length() == 0);
12227
12228 #ifdef DEBUG
12229   // Print the scopes for the top frame.
12230   StackFrameLocator locator(isolate);
12231   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12232   for (ScopeIterator it(isolate, frame, 0);
12233        !it.Done();
12234        it.Next()) {
12235     it.DebugPrint();
12236   }
12237 #endif
12238   return isolate->heap()->undefined_value();
12239 }
12240
12241
12242 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
12243   HandleScope scope(isolate);
12244   ASSERT(args.length() == 1);
12245
12246   // Check arguments.
12247   Object* result;
12248   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12249       RUNTIME_ARGUMENTS(isolate, args));
12250     if (!maybe_result->ToObject(&result)) return maybe_result;
12251   }
12252
12253   // Count all archived V8 threads.
12254   int n = 0;
12255   for (ThreadState* thread =
12256           isolate->thread_manager()->FirstThreadStateInUse();
12257        thread != NULL;
12258        thread = thread->Next()) {
12259     n++;
12260   }
12261
12262   // Total number of threads is current thread and archived threads.
12263   return Smi::FromInt(n + 1);
12264 }
12265
12266
12267 static const int kThreadDetailsCurrentThreadIndex = 0;
12268 static const int kThreadDetailsThreadIdIndex = 1;
12269 static const int kThreadDetailsSize = 2;
12270
12271 // Return an array with thread details
12272 // args[0]: number: break id
12273 // args[1]: number: thread index
12274 //
12275 // The array returned contains the following information:
12276 // 0: Is current thread?
12277 // 1: Thread id
12278 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
12279   HandleScope scope(isolate);
12280   ASSERT(args.length() == 2);
12281
12282   // Check arguments.
12283   Object* check;
12284   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12285       RUNTIME_ARGUMENTS(isolate, args));
12286     if (!maybe_check->ToObject(&check)) return maybe_check;
12287   }
12288   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12289
12290   // Allocate array for result.
12291   Handle<FixedArray> details =
12292       isolate->factory()->NewFixedArray(kThreadDetailsSize);
12293
12294   // Thread index 0 is current thread.
12295   if (index == 0) {
12296     // Fill the details.
12297     details->set(kThreadDetailsCurrentThreadIndex,
12298                  isolate->heap()->true_value());
12299     details->set(kThreadDetailsThreadIdIndex,
12300                  Smi::FromInt(ThreadId::Current().ToInteger()));
12301   } else {
12302     // Find the thread with the requested index.
12303     int n = 1;
12304     ThreadState* thread =
12305         isolate->thread_manager()->FirstThreadStateInUse();
12306     while (index != n && thread != NULL) {
12307       thread = thread->Next();
12308       n++;
12309     }
12310     if (thread == NULL) {
12311       return isolate->heap()->undefined_value();
12312     }
12313
12314     // Fill the details.
12315     details->set(kThreadDetailsCurrentThreadIndex,
12316                  isolate->heap()->false_value());
12317     details->set(kThreadDetailsThreadIdIndex,
12318                  Smi::FromInt(thread->id().ToInteger()));
12319   }
12320
12321   // Convert to JS array and return.
12322   return *isolate->factory()->NewJSArrayWithElements(details);
12323 }
12324
12325
12326 // Sets the disable break state
12327 // args[0]: disable break state
12328 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
12329   HandleScope scope(isolate);
12330   ASSERT(args.length() == 1);
12331   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12332   isolate->debug()->set_disable_break(disable_break);
12333   return  isolate->heap()->undefined_value();
12334 }
12335
12336
12337 static bool IsPositionAlignmentCodeCorrect(int alignment) {
12338   return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12339 }
12340
12341
12342 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
12343   HandleScope scope(isolate);
12344   ASSERT(args.length() == 2);
12345
12346   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12347   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12348
12349   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12350     return isolate->ThrowIllegalOperation();
12351   }
12352   BreakPositionAlignment alignment =
12353       static_cast<BreakPositionAlignment>(statement_aligned_code);
12354
12355   Handle<SharedFunctionInfo> shared(fun->shared());
12356   // Find the number of break points
12357   Handle<Object> break_locations =
12358       Debug::GetSourceBreakLocations(shared, alignment);
12359   if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12360   // Return array as JS array
12361   return *isolate->factory()->NewJSArrayWithElements(
12362       Handle<FixedArray>::cast(break_locations));
12363 }
12364
12365
12366 // Set a break point in a function.
12367 // args[0]: function
12368 // args[1]: number: break source position (within the function source)
12369 // args[2]: number: break point object
12370 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
12371   HandleScope scope(isolate);
12372   ASSERT(args.length() == 3);
12373   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12374   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12375   RUNTIME_ASSERT(source_position >= 0);
12376   Handle<Object> break_point_object_arg = args.at<Object>(2);
12377
12378   // Set break point.
12379   isolate->debug()->SetBreakPoint(function, break_point_object_arg,
12380                                   &source_position);
12381
12382   return Smi::FromInt(source_position);
12383 }
12384
12385
12386 // Changes the state of a break point in a script and returns source position
12387 // where break point was set. NOTE: Regarding performance see the NOTE for
12388 // GetScriptFromScriptData.
12389 // args[0]: script to set break point in
12390 // args[1]: number: break source position (within the script source)
12391 // args[2]: number, breakpoint position alignment
12392 // args[3]: number: break point object
12393 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
12394   HandleScope scope(isolate);
12395   ASSERT(args.length() == 4);
12396   CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12397   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12398   RUNTIME_ASSERT(source_position >= 0);
12399   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12400   Handle<Object> break_point_object_arg = args.at<Object>(3);
12401
12402   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12403     return isolate->ThrowIllegalOperation();
12404   }
12405   BreakPositionAlignment alignment =
12406       static_cast<BreakPositionAlignment>(statement_aligned_code);
12407
12408   // Get the script from the script wrapper.
12409   RUNTIME_ASSERT(wrapper->value()->IsScript());
12410   Handle<Script> script(Script::cast(wrapper->value()));
12411
12412   // Set break point.
12413   if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12414                                                 &source_position,
12415                                                 alignment)) {
12416     return  isolate->heap()->undefined_value();
12417   }
12418
12419   return Smi::FromInt(source_position);
12420 }
12421
12422
12423 // Clear a break point
12424 // args[0]: number: break point object
12425 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
12426   HandleScope scope(isolate);
12427   ASSERT(args.length() == 1);
12428   Handle<Object> break_point_object_arg = args.at<Object>(0);
12429
12430   // Clear break point.
12431   isolate->debug()->ClearBreakPoint(break_point_object_arg);
12432
12433   return isolate->heap()->undefined_value();
12434 }
12435
12436
12437 // Change the state of break on exceptions.
12438 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12439 // args[1]: Boolean indicating on/off.
12440 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
12441   HandleScope scope(isolate);
12442   ASSERT(args.length() == 2);
12443   RUNTIME_ASSERT(args[0]->IsNumber());
12444   CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12445
12446   // If the number doesn't match an enum value, the ChangeBreakOnException
12447   // function will default to affecting caught exceptions.
12448   ExceptionBreakType type =
12449       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12450   // Update break point state.
12451   isolate->debug()->ChangeBreakOnException(type, enable);
12452   return isolate->heap()->undefined_value();
12453 }
12454
12455
12456 // Returns the state of break on exceptions
12457 // args[0]: boolean indicating uncaught exceptions
12458 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
12459   HandleScope scope(isolate);
12460   ASSERT(args.length() == 1);
12461   RUNTIME_ASSERT(args[0]->IsNumber());
12462
12463   ExceptionBreakType type =
12464       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12465   bool result = isolate->debug()->IsBreakOnException(type);
12466   return Smi::FromInt(result);
12467 }
12468
12469
12470 // Prepare for stepping
12471 // args[0]: break id for checking execution state
12472 // args[1]: step action from the enumeration StepAction
12473 // args[2]: number of times to perform the step, for step out it is the number
12474 //          of frames to step down.
12475 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
12476   HandleScope scope(isolate);
12477   ASSERT(args.length() == 3);
12478   // Check arguments.
12479   Object* check;
12480   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12481       RUNTIME_ARGUMENTS(isolate, args));
12482     if (!maybe_check->ToObject(&check)) return maybe_check;
12483   }
12484   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12485     return isolate->Throw(isolate->heap()->illegal_argument_string());
12486   }
12487
12488   // Get the step action and check validity.
12489   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12490   if (step_action != StepIn &&
12491       step_action != StepNext &&
12492       step_action != StepOut &&
12493       step_action != StepInMin &&
12494       step_action != StepMin) {
12495     return isolate->Throw(isolate->heap()->illegal_argument_string());
12496   }
12497
12498   // Get the number of steps.
12499   int step_count = NumberToInt32(args[2]);
12500   if (step_count < 1) {
12501     return isolate->Throw(isolate->heap()->illegal_argument_string());
12502   }
12503
12504   // Clear all current stepping setup.
12505   isolate->debug()->ClearStepping();
12506
12507   // Prepare step.
12508   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12509                                 step_count);
12510   return isolate->heap()->undefined_value();
12511 }
12512
12513
12514 // Clear all stepping set by PrepareStep.
12515 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
12516   HandleScope scope(isolate);
12517   ASSERT(args.length() == 0);
12518   isolate->debug()->ClearStepping();
12519   return isolate->heap()->undefined_value();
12520 }
12521
12522
12523 // Helper function to find or create the arguments object for
12524 // Runtime_DebugEvaluate.
12525 static Handle<JSObject> MaterializeArgumentsObject(
12526     Isolate* isolate,
12527     Handle<JSObject> target,
12528     Handle<JSFunction> function) {
12529   // Do not materialize the arguments object for eval or top-level code.
12530   // Skip if "arguments" is already taken.
12531   if (!function->shared()->is_function() ||
12532       target->HasLocalProperty(isolate->heap()->arguments_string())) {
12533     return target;
12534   }
12535
12536   // FunctionGetArguments can't throw an exception.
12537   Handle<JSObject> arguments = Handle<JSObject>::cast(
12538       Accessors::FunctionGetArguments(function));
12539   SetProperty(isolate,
12540               target,
12541               isolate->factory()->arguments_string(),
12542               arguments,
12543               ::NONE,
12544               kNonStrictMode);
12545   return target;
12546 }
12547
12548
12549 // Compile and evaluate source for the given context.
12550 static MaybeObject* DebugEvaluate(Isolate* isolate,
12551                                   Handle<Context> context,
12552                                   Handle<Object> context_extension,
12553                                   Handle<Object> receiver,
12554                                   Handle<String> source) {
12555   if (context_extension->IsJSObject()) {
12556     Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12557     Handle<JSFunction> closure(context->closure(), isolate);
12558     context = isolate->factory()->NewWithContext(closure, context, extension);
12559   }
12560
12561   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
12562       source,
12563       context,
12564       context->IsNativeContext(),
12565       CLASSIC_MODE,
12566       NO_PARSE_RESTRICTION,
12567       RelocInfo::kNoPosition);
12568   RETURN_IF_EMPTY_HANDLE(isolate, shared);
12569
12570   Handle<JSFunction> eval_fun =
12571       isolate->factory()->NewFunctionFromSharedFunctionInfo(
12572           shared, context, NOT_TENURED);
12573   bool pending_exception;
12574   Handle<Object> result = Execution::Call(
12575       eval_fun, receiver, 0, NULL, &pending_exception);
12576
12577   if (pending_exception) return Failure::Exception();
12578
12579   // Skip the global proxy as it has no properties and always delegates to the
12580   // real global object.
12581   if (result->IsJSGlobalProxy()) {
12582     result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
12583   }
12584
12585   // Clear the oneshot breakpoints so that the debugger does not step further.
12586   isolate->debug()->ClearStepping();
12587   return *result;
12588 }
12589
12590
12591 // Evaluate a piece of JavaScript in the context of a stack frame for
12592 // debugging.  Things that need special attention are:
12593 // - Parameters and stack-allocated locals need to be materialized.  Altered
12594 //   values need to be written back to the stack afterwards.
12595 // - The arguments object needs to materialized.
12596 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
12597   HandleScope scope(isolate);
12598
12599   // Check the execution state and decode arguments frame and source to be
12600   // evaluated.
12601   ASSERT(args.length() == 6);
12602   Object* check_result;
12603   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12604       RUNTIME_ARGUMENTS(isolate, args));
12605     if (!maybe_result->ToObject(&check_result)) return maybe_result;
12606   }
12607   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12608   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12609   CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
12610   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
12611   Handle<Object> context_extension(args[5], isolate);
12612
12613   // Handle the processing of break.
12614   DisableBreak disable_break_save(disable_break);
12615
12616   // Get the frame where the debugging is performed.
12617   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12618   JavaScriptFrameIterator it(isolate, id);
12619   JavaScriptFrame* frame = it.frame();
12620   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12621   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12622
12623   // Traverse the saved contexts chain to find the active context for the
12624   // selected frame.
12625   SaveContext* save = FindSavedContextForFrame(isolate, frame);
12626
12627   SaveContext savex(isolate);
12628   isolate->set_context(*(save->context()));
12629
12630   // Evaluate on the context of the frame.
12631   Handle<Context> context(Context::cast(frame->context()));
12632   ASSERT(!context.is_null());
12633
12634   // Materialize stack locals and the arguments object.
12635   Handle<JSObject> materialized =
12636       isolate->factory()->NewJSObject(isolate->object_function());
12637
12638   materialized = MaterializeStackLocalsWithFrameInspector(
12639       isolate, materialized, function, &frame_inspector);
12640   RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12641
12642   materialized = MaterializeArgumentsObject(isolate, materialized, function);
12643   RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12644
12645   // Add the materialized object in a with-scope to shadow the stack locals.
12646   context = isolate->factory()->NewWithContext(function, context, materialized);
12647
12648   Handle<Object> receiver(frame->receiver(), isolate);
12649   Object* evaluate_result_object;
12650   { MaybeObject* maybe_result =
12651     DebugEvaluate(isolate, context, context_extension, receiver, source);
12652     if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
12653   }
12654
12655   Handle<Object> result(evaluate_result_object, isolate);
12656
12657   // Write back potential changes to materialized stack locals to the stack.
12658   UpdateStackLocalsFromMaterializedObject(
12659       isolate, materialized, function, frame, inlined_jsframe_index);
12660
12661   return *result;
12662 }
12663
12664
12665 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
12666   HandleScope scope(isolate);
12667
12668   // Check the execution state and decode arguments frame and source to be
12669   // evaluated.
12670   ASSERT(args.length() == 4);
12671   Object* check_result;
12672   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12673       RUNTIME_ARGUMENTS(isolate, args));
12674     if (!maybe_result->ToObject(&check_result)) return maybe_result;
12675   }
12676   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12677   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
12678   Handle<Object> context_extension(args[3], isolate);
12679
12680   // Handle the processing of break.
12681   DisableBreak disable_break_save(disable_break);
12682
12683   // Enter the top context from before the debugger was invoked.
12684   SaveContext save(isolate);
12685   SaveContext* top = &save;
12686   while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
12687     top = top->prev();
12688   }
12689   if (top != NULL) {
12690     isolate->set_context(*top->context());
12691   }
12692
12693   // Get the native context now set to the top context from before the
12694   // debugger was invoked.
12695   Handle<Context> context = isolate->native_context();
12696   Handle<Object> receiver = isolate->global_object();
12697   return DebugEvaluate(isolate, context, context_extension, receiver, source);
12698 }
12699
12700
12701 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
12702   HandleScope scope(isolate);
12703   ASSERT(args.length() == 0);
12704
12705   // Fill the script objects.
12706   Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
12707
12708   // Convert the script objects to proper JS objects.
12709   for (int i = 0; i < instances->length(); i++) {
12710     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
12711     // Get the script wrapper in a local handle before calling GetScriptWrapper,
12712     // because using
12713     //   instances->set(i, *GetScriptWrapper(script))
12714     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12715     // already have dereferenced the instances handle.
12716     Handle<JSValue> wrapper = GetScriptWrapper(script);
12717     instances->set(i, *wrapper);
12718   }
12719
12720   // Return result as a JS array.
12721   Handle<JSObject> result =
12722       isolate->factory()->NewJSObject(isolate->array_function());
12723   isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12724   return *result;
12725 }
12726
12727
12728 // Helper function used by Runtime_DebugReferencedBy below.
12729 static int DebugReferencedBy(HeapIterator* iterator,
12730                              JSObject* target,
12731                              Object* instance_filter, int max_references,
12732                              FixedArray* instances, int instances_size,
12733                              JSFunction* arguments_function) {
12734   Isolate* isolate = target->GetIsolate();
12735   SealHandleScope shs(isolate);
12736   DisallowHeapAllocation no_allocation;
12737
12738   // Iterate the heap.
12739   int count = 0;
12740   JSObject* last = NULL;
12741   HeapObject* heap_obj = NULL;
12742   while (((heap_obj = iterator->next()) != NULL) &&
12743          (max_references == 0 || count < max_references)) {
12744     // Only look at all JSObjects.
12745     if (heap_obj->IsJSObject()) {
12746       // Skip context extension objects and argument arrays as these are
12747       // checked in the context of functions using them.
12748       JSObject* obj = JSObject::cast(heap_obj);
12749       if (obj->IsJSContextExtensionObject() ||
12750           obj->map()->constructor() == arguments_function) {
12751         continue;
12752       }
12753
12754       // Check if the JS object has a reference to the object looked for.
12755       if (obj->ReferencesObject(target)) {
12756         // Check instance filter if supplied. This is normally used to avoid
12757         // references from mirror objects (see Runtime_IsInPrototypeChain).
12758         if (!instance_filter->IsUndefined()) {
12759           Object* V = obj;
12760           while (true) {
12761             Object* prototype = V->GetPrototype(isolate);
12762             if (prototype->IsNull()) {
12763               break;
12764             }
12765             if (instance_filter == prototype) {
12766               obj = NULL;  // Don't add this object.
12767               break;
12768             }
12769             V = prototype;
12770           }
12771         }
12772
12773         if (obj != NULL) {
12774           // Valid reference found add to instance array if supplied an update
12775           // count.
12776           if (instances != NULL && count < instances_size) {
12777             instances->set(count, obj);
12778           }
12779           last = obj;
12780           count++;
12781         }
12782       }
12783     }
12784   }
12785
12786   // Check for circular reference only. This can happen when the object is only
12787   // referenced from mirrors and has a circular reference in which case the
12788   // object is not really alive and would have been garbage collected if not
12789   // referenced from the mirror.
12790   if (count == 1 && last == target) {
12791     count = 0;
12792   }
12793
12794   // Return the number of referencing objects found.
12795   return count;
12796 }
12797
12798
12799 // Scan the heap for objects with direct references to an object
12800 // args[0]: the object to find references to
12801 // args[1]: constructor function for instances to exclude (Mirror)
12802 // args[2]: the the maximum number of objects to return
12803 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12804   SealHandleScope shs(isolate);
12805   ASSERT(args.length() == 3);
12806
12807   // First perform a full GC in order to avoid references from dead objects.
12808   isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12809                                      "%DebugReferencedBy");
12810   // The heap iterator reserves the right to do a GC to make the heap iterable.
12811   // Due to the GC above we know it won't need to do that, but it seems cleaner
12812   // to get the heap iterator constructed before we start having unprotected
12813   // Object* locals that are not protected by handles.
12814
12815   // Check parameters.
12816   CONVERT_ARG_CHECKED(JSObject, target, 0);
12817   Object* instance_filter = args[1];
12818   RUNTIME_ASSERT(instance_filter->IsUndefined() ||
12819                  instance_filter->IsJSObject());
12820   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
12821   RUNTIME_ASSERT(max_references >= 0);
12822
12823
12824   // Get the constructor function for context extension and arguments array.
12825   JSObject* arguments_boilerplate =
12826       isolate->context()->native_context()->arguments_boilerplate();
12827   JSFunction* arguments_function =
12828       JSFunction::cast(arguments_boilerplate->map()->constructor());
12829
12830   // Get the number of referencing objects.
12831   int count;
12832   Heap* heap = isolate->heap();
12833   HeapIterator heap_iterator(heap);
12834   count = DebugReferencedBy(&heap_iterator,
12835                             target, instance_filter, max_references,
12836                             NULL, 0, arguments_function);
12837
12838   // Allocate an array to hold the result.
12839   Object* object;
12840   { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
12841     if (!maybe_object->ToObject(&object)) return maybe_object;
12842   }
12843   FixedArray* instances = FixedArray::cast(object);
12844
12845   // Fill the referencing objects.
12846   // AllocateFixedArray above does not make the heap non-iterable.
12847   ASSERT(heap->IsHeapIterable());
12848   HeapIterator heap_iterator2(heap);
12849   count = DebugReferencedBy(&heap_iterator2,
12850                             target, instance_filter, max_references,
12851                             instances, count, arguments_function);
12852
12853   // Return result as JS array.
12854   Object* result;
12855   MaybeObject* maybe_result = heap->AllocateJSObject(
12856       isolate->context()->native_context()->array_function());
12857   if (!maybe_result->ToObject(&result)) return maybe_result;
12858   return JSArray::cast(result)->SetContent(instances);
12859 }
12860
12861
12862 // Helper function used by Runtime_DebugConstructedBy below.
12863 static int DebugConstructedBy(HeapIterator* iterator,
12864                               JSFunction* constructor,
12865                               int max_references,
12866                               FixedArray* instances,
12867                               int instances_size) {
12868   DisallowHeapAllocation no_allocation;
12869
12870   // Iterate the heap.
12871   int count = 0;
12872   HeapObject* heap_obj = NULL;
12873   while (((heap_obj = iterator->next()) != NULL) &&
12874          (max_references == 0 || count < max_references)) {
12875     // Only look at all JSObjects.
12876     if (heap_obj->IsJSObject()) {
12877       JSObject* obj = JSObject::cast(heap_obj);
12878       if (obj->map()->constructor() == constructor) {
12879         // Valid reference found add to instance array if supplied an update
12880         // count.
12881         if (instances != NULL && count < instances_size) {
12882           instances->set(count, obj);
12883         }
12884         count++;
12885       }
12886     }
12887   }
12888
12889   // Return the number of referencing objects found.
12890   return count;
12891 }
12892
12893
12894 // Scan the heap for objects constructed by a specific function.
12895 // args[0]: the constructor to find instances of
12896 // args[1]: the the maximum number of objects to return
12897 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
12898   SealHandleScope shs(isolate);
12899   ASSERT(args.length() == 2);
12900
12901   // First perform a full GC in order to avoid dead objects.
12902   Heap* heap = isolate->heap();
12903   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
12904
12905   // Check parameters.
12906   CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
12907   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
12908   RUNTIME_ASSERT(max_references >= 0);
12909
12910   // Get the number of referencing objects.
12911   int count;
12912   HeapIterator heap_iterator(heap);
12913   count = DebugConstructedBy(&heap_iterator,
12914                              constructor,
12915                              max_references,
12916                              NULL,
12917                              0);
12918
12919   // Allocate an array to hold the result.
12920   Object* object;
12921   { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
12922     if (!maybe_object->ToObject(&object)) return maybe_object;
12923   }
12924   FixedArray* instances = FixedArray::cast(object);
12925
12926   ASSERT(HEAP->IsHeapIterable());
12927   // Fill the referencing objects.
12928   HeapIterator heap_iterator2(heap);
12929   count = DebugConstructedBy(&heap_iterator2,
12930                              constructor,
12931                              max_references,
12932                              instances,
12933                              count);
12934
12935   // Return result as JS array.
12936   Object* result;
12937   { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12938       isolate->context()->native_context()->array_function());
12939     if (!maybe_result->ToObject(&result)) return maybe_result;
12940   }
12941   return JSArray::cast(result)->SetContent(instances);
12942 }
12943
12944
12945 // Find the effective prototype object as returned by __proto__.
12946 // args[0]: the object to find the prototype for.
12947 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
12948   SealHandleScope shs(isolate);
12949   ASSERT(args.length() == 1);
12950   CONVERT_ARG_CHECKED(JSObject, obj, 0);
12951   return GetPrototypeSkipHiddenPrototypes(isolate, obj);
12952 }
12953
12954
12955 // Patches script source (should be called upon BeforeCompile event).
12956 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
12957   HandleScope scope(isolate);
12958   ASSERT(args.length() == 2);
12959
12960   CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
12961   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12962
12963   RUNTIME_ASSERT(script_wrapper->value()->IsScript());
12964   Handle<Script> script(Script::cast(script_wrapper->value()));
12965
12966   int compilation_state = script->compilation_state();
12967   RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
12968   script->set_source(*source);
12969
12970   return isolate->heap()->undefined_value();
12971 }
12972
12973
12974 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
12975   SealHandleScope shs(isolate);
12976   ASSERT(args.length() == 0);
12977   CPU::DebugBreak();
12978   return isolate->heap()->undefined_value();
12979 }
12980
12981
12982 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
12983   HandleScope scope(isolate);
12984 #ifdef DEBUG
12985   ASSERT(args.length() == 1);
12986   // Get the function and make sure it is compiled.
12987   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12988   if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
12989     return Failure::Exception();
12990   }
12991   func->code()->PrintLn();
12992 #endif  // DEBUG
12993   return isolate->heap()->undefined_value();
12994 }
12995
12996
12997 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
12998   HandleScope scope(isolate);
12999 #ifdef DEBUG
13000   ASSERT(args.length() == 1);
13001   // Get the function and make sure it is compiled.
13002   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13003   if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
13004     return Failure::Exception();
13005   }
13006   func->shared()->construct_stub()->PrintLn();
13007 #endif  // DEBUG
13008   return isolate->heap()->undefined_value();
13009 }
13010
13011
13012 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
13013   SealHandleScope shs(isolate);
13014   ASSERT(args.length() == 1);
13015
13016   CONVERT_ARG_CHECKED(JSFunction, f, 0);
13017   return f->shared()->inferred_name();
13018 }
13019
13020
13021 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13022                                             Script* script,
13023                                             FixedArray* buffer) {
13024   DisallowHeapAllocation no_allocation;
13025   int counter = 0;
13026   int buffer_size = buffer->length();
13027   for (HeapObject* obj = iterator->next();
13028        obj != NULL;
13029        obj = iterator->next()) {
13030     ASSERT(obj != NULL);
13031     if (!obj->IsSharedFunctionInfo()) {
13032       continue;
13033     }
13034     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13035     if (shared->script() != script) {
13036       continue;
13037     }
13038     if (counter < buffer_size) {
13039       buffer->set(counter, shared);
13040     }
13041     counter++;
13042   }
13043   return counter;
13044 }
13045
13046
13047 // For a script finds all SharedFunctionInfo's in the heap that points
13048 // to this script. Returns JSArray of SharedFunctionInfo wrapped
13049 // in OpaqueReferences.
13050 RUNTIME_FUNCTION(MaybeObject*,
13051                  Runtime_LiveEditFindSharedFunctionInfosForScript) {
13052   HandleScope scope(isolate);
13053   CHECK(isolate->debugger()->live_edit_enabled());
13054   ASSERT(args.length() == 1);
13055   CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13056
13057   RUNTIME_ASSERT(script_value->value()->IsScript());
13058   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13059
13060   const int kBufferSize = 32;
13061
13062   Handle<FixedArray> array;
13063   array = isolate->factory()->NewFixedArray(kBufferSize);
13064   int number;
13065   Heap* heap = isolate->heap();
13066   {
13067     heap->EnsureHeapIsIterable();
13068     DisallowHeapAllocation no_allocation;
13069     HeapIterator heap_iterator(heap);
13070     Script* scr = *script;
13071     FixedArray* arr = *array;
13072     number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13073   }
13074   if (number > kBufferSize) {
13075     array = isolate->factory()->NewFixedArray(number);
13076     heap->EnsureHeapIsIterable();
13077     DisallowHeapAllocation no_allocation;
13078     HeapIterator heap_iterator(heap);
13079     Script* scr = *script;
13080     FixedArray* arr = *array;
13081     FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13082   }
13083
13084   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13085   result->set_length(Smi::FromInt(number));
13086
13087   LiveEdit::WrapSharedFunctionInfos(result);
13088
13089   return *result;
13090 }
13091
13092
13093 // For a script calculates compilation information about all its functions.
13094 // The script source is explicitly specified by the second argument.
13095 // The source of the actual script is not used, however it is important that
13096 // all generated code keeps references to this particular instance of script.
13097 // Returns a JSArray of compilation infos. The array is ordered so that
13098 // each function with all its descendant is always stored in a continues range
13099 // with the function itself going first. The root function is a script function.
13100 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
13101   HandleScope scope(isolate);
13102   CHECK(isolate->debugger()->live_edit_enabled());
13103   ASSERT(args.length() == 2);
13104   CONVERT_ARG_CHECKED(JSValue, script, 0);
13105   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13106
13107   RUNTIME_ASSERT(script->value()->IsScript());
13108   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13109
13110   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
13111
13112   if (isolate->has_pending_exception()) {
13113     return Failure::Exception();
13114   }
13115
13116   return result;
13117 }
13118
13119
13120 // Changes the source of the script to a new_source.
13121 // If old_script_name is provided (i.e. is a String), also creates a copy of
13122 // the script with its original source and sends notification to debugger.
13123 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
13124   HandleScope scope(isolate);
13125   CHECK(isolate->debugger()->live_edit_enabled());
13126   ASSERT(args.length() == 3);
13127   CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13128   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13129   Handle<Object> old_script_name(args[2], isolate);
13130
13131   RUNTIME_ASSERT(original_script_value->value()->IsScript());
13132   Handle<Script> original_script(Script::cast(original_script_value->value()));
13133
13134   Object* old_script = LiveEdit::ChangeScriptSource(original_script,
13135                                                     new_source,
13136                                                     old_script_name);
13137
13138   if (old_script->IsScript()) {
13139     Handle<Script> script_handle(Script::cast(old_script));
13140     return *(GetScriptWrapper(script_handle));
13141   } else {
13142     return isolate->heap()->null_value();
13143   }
13144 }
13145
13146
13147 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
13148   HandleScope scope(isolate);
13149   CHECK(isolate->debugger()->live_edit_enabled());
13150   ASSERT(args.length() == 1);
13151   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13152   return LiveEdit::FunctionSourceUpdated(shared_info);
13153 }
13154
13155
13156 // Replaces code of SharedFunctionInfo with a new one.
13157 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
13158   HandleScope scope(isolate);
13159   CHECK(isolate->debugger()->live_edit_enabled());
13160   ASSERT(args.length() == 2);
13161   CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13162   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13163
13164   return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13165 }
13166
13167
13168 // Connects SharedFunctionInfo to another script.
13169 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
13170   HandleScope scope(isolate);
13171   CHECK(isolate->debugger()->live_edit_enabled());
13172   ASSERT(args.length() == 2);
13173   Handle<Object> function_object(args[0], isolate);
13174   Handle<Object> script_object(args[1], isolate);
13175
13176   if (function_object->IsJSValue()) {
13177     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13178     if (script_object->IsJSValue()) {
13179       RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13180       Script* script = Script::cast(JSValue::cast(*script_object)->value());
13181       script_object = Handle<Object>(script, isolate);
13182     }
13183
13184     LiveEdit::SetFunctionScript(function_wrapper, script_object);
13185   } else {
13186     // Just ignore this. We may not have a SharedFunctionInfo for some functions
13187     // and we check it in this function.
13188   }
13189
13190   return isolate->heap()->undefined_value();
13191 }
13192
13193
13194 // In a code of a parent function replaces original function as embedded object
13195 // with a substitution one.
13196 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
13197   HandleScope scope(isolate);
13198   CHECK(isolate->debugger()->live_edit_enabled());
13199   ASSERT(args.length() == 3);
13200
13201   CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13202   CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13203   CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13204
13205   LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
13206                                        subst_wrapper);
13207
13208   return isolate->heap()->undefined_value();
13209 }
13210
13211
13212 // Updates positions of a shared function info (first parameter) according
13213 // to script source change. Text change is described in second parameter as
13214 // array of groups of 3 numbers:
13215 // (change_begin, change_end, change_end_new_position).
13216 // Each group describes a change in text; groups are sorted by change_begin.
13217 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
13218   HandleScope scope(isolate);
13219   CHECK(isolate->debugger()->live_edit_enabled());
13220   ASSERT(args.length() == 2);
13221   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13222   CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13223
13224   return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13225 }
13226
13227
13228 // For array of SharedFunctionInfo's (each wrapped in JSValue)
13229 // checks that none of them have activations on stacks (of any thread).
13230 // Returns array of the same length with corresponding results of
13231 // LiveEdit::FunctionPatchabilityStatus type.
13232 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
13233   HandleScope scope(isolate);
13234   CHECK(isolate->debugger()->live_edit_enabled());
13235   ASSERT(args.length() == 2);
13236   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13237   CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13238
13239   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13240 }
13241
13242
13243 // Compares 2 strings line-by-line, then token-wise and returns diff in form
13244 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13245 // of diff chunks.
13246 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
13247   HandleScope scope(isolate);
13248   CHECK(isolate->debugger()->live_edit_enabled());
13249   ASSERT(args.length() == 2);
13250   CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13251   CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13252
13253   return *LiveEdit::CompareStrings(s1, s2);
13254 }
13255
13256
13257 // Restarts a call frame and completely drops all frames above.
13258 // Returns true if successful. Otherwise returns undefined or an error message.
13259 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
13260   HandleScope scope(isolate);
13261   CHECK(isolate->debugger()->live_edit_enabled());
13262   ASSERT(args.length() == 2);
13263
13264   // Check arguments.
13265   Object* check;
13266   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
13267       RUNTIME_ARGUMENTS(isolate, args));
13268     if (!maybe_check->ToObject(&check)) return maybe_check;
13269   }
13270   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13271   Heap* heap = isolate->heap();
13272
13273   // Find the relevant frame with the requested index.
13274   StackFrame::Id id = isolate->debug()->break_frame_id();
13275   if (id == StackFrame::NO_ID) {
13276     // If there are no JavaScript stack frames return undefined.
13277     return heap->undefined_value();
13278   }
13279
13280   int count = 0;
13281   JavaScriptFrameIterator it(isolate, id);
13282   for (; !it.done(); it.Advance()) {
13283     if (index < count + it.frame()->GetInlineCount()) break;
13284     count += it.frame()->GetInlineCount();
13285   }
13286   if (it.done()) return heap->undefined_value();
13287
13288   const char* error_message = LiveEdit::RestartFrame(it.frame());
13289   if (error_message) {
13290     return *(isolate->factory()->InternalizeUtf8String(error_message));
13291   }
13292   return heap->true_value();
13293 }
13294
13295
13296 // A testing entry. Returns statement position which is the closest to
13297 // source_position.
13298 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
13299   HandleScope scope(isolate);
13300   CHECK(isolate->debugger()->live_edit_enabled());
13301   ASSERT(args.length() == 2);
13302   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13303   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13304
13305   Handle<Code> code(function->code(), isolate);
13306
13307   if (code->kind() != Code::FUNCTION &&
13308       code->kind() != Code::OPTIMIZED_FUNCTION) {
13309     return isolate->heap()->undefined_value();
13310   }
13311
13312   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13313   int closest_pc = 0;
13314   int distance = kMaxInt;
13315   while (!it.done()) {
13316     int statement_position = static_cast<int>(it.rinfo()->data());
13317     // Check if this break point is closer that what was previously found.
13318     if (source_position <= statement_position &&
13319         statement_position - source_position < distance) {
13320       closest_pc =
13321           static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13322       distance = statement_position - source_position;
13323       // Check whether we can't get any closer.
13324       if (distance == 0) break;
13325     }
13326     it.next();
13327   }
13328
13329   return Smi::FromInt(closest_pc);
13330 }
13331
13332
13333 // Calls specified function with or without entering the debugger.
13334 // This is used in unit tests to run code as if debugger is entered or simply
13335 // to have a stack with C++ frame in the middle.
13336 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
13337   HandleScope scope(isolate);
13338   ASSERT(args.length() == 2);
13339   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13340   CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13341
13342   Handle<Object> result;
13343   bool pending_exception;
13344   {
13345     if (without_debugger) {
13346       result = Execution::Call(function, isolate->global_object(), 0, NULL,
13347                                &pending_exception);
13348     } else {
13349       EnterDebugger enter_debugger;
13350       result = Execution::Call(function, isolate->global_object(), 0, NULL,
13351                                &pending_exception);
13352     }
13353   }
13354   if (!pending_exception) {
13355     return *result;
13356   } else {
13357     return Failure::Exception();
13358   }
13359 }
13360
13361
13362 // Sets a v8 flag.
13363 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
13364   SealHandleScope shs(isolate);
13365   CONVERT_ARG_CHECKED(String, arg, 0);
13366   SmartArrayPointer<char> flags =
13367       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13368   FlagList::SetFlagsFromString(*flags, StrLength(*flags));
13369   return isolate->heap()->undefined_value();
13370 }
13371
13372
13373 // Performs a GC.
13374 // Presently, it only does a full GC.
13375 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
13376   SealHandleScope shs(isolate);
13377   isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13378   return isolate->heap()->undefined_value();
13379 }
13380
13381
13382 // Gets the current heap usage.
13383 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
13384   SealHandleScope shs(isolate);
13385   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13386   if (!Smi::IsValid(usage)) {
13387     return *isolate->factory()->NewNumberFromInt(usage);
13388   }
13389   return Smi::FromInt(usage);
13390 }
13391
13392 #endif  // ENABLE_DEBUGGER_SUPPORT
13393
13394
13395 #ifdef V8_I18N_SUPPORT
13396 RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
13397   HandleScope scope(isolate);
13398
13399   ASSERT(args.length() == 1);
13400   CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13401
13402   v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13403
13404   // Return value which denotes invalid language tag.
13405   const char* const kInvalidTag = "invalid-tag";
13406
13407   UErrorCode error = U_ZERO_ERROR;
13408   char icu_result[ULOC_FULLNAME_CAPACITY];
13409   int icu_length = 0;
13410
13411   uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13412                       &icu_length, &error);
13413   if (U_FAILURE(error) || icu_length == 0) {
13414     return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13415   }
13416
13417   char result[ULOC_FULLNAME_CAPACITY];
13418
13419   // Force strict BCP47 rules.
13420   uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13421
13422   if (U_FAILURE(error)) {
13423     return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13424   }
13425
13426   return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13427 }
13428
13429
13430 RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
13431   HandleScope scope(isolate);
13432
13433   ASSERT(args.length() == 1);
13434   CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13435
13436   const icu::Locale* available_locales = NULL;
13437   int32_t count = 0;
13438
13439   if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13440     available_locales = icu::Collator::getAvailableLocales(count);
13441   } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13442     available_locales = icu::NumberFormat::getAvailableLocales(count);
13443   } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13444     available_locales = icu::DateFormat::getAvailableLocales(count);
13445   } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13446     available_locales = icu::BreakIterator::getAvailableLocales(count);
13447   }
13448
13449   UErrorCode error = U_ZERO_ERROR;
13450   char result[ULOC_FULLNAME_CAPACITY];
13451   Handle<JSObject> locales =
13452       isolate->factory()->NewJSObject(isolate->object_function());
13453
13454   for (int32_t i = 0; i < count; ++i) {
13455     const char* icu_name = available_locales[i].getName();
13456
13457     error = U_ZERO_ERROR;
13458     // No need to force strict BCP47 rules.
13459     uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13460     if (U_FAILURE(error)) {
13461       // This shouldn't happen, but lets not break the user.
13462       continue;
13463     }
13464
13465     RETURN_IF_EMPTY_HANDLE(isolate,
13466         JSObject::SetLocalPropertyIgnoreAttributes(
13467             locales,
13468             isolate->factory()->NewStringFromAscii(CStrVector(result)),
13469             isolate->factory()->NewNumber(i),
13470             NONE));
13471   }
13472
13473   return *locales;
13474 }
13475
13476
13477 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
13478   SealHandleScope shs(isolate);
13479
13480   ASSERT(args.length() == 0);
13481
13482   icu::Locale default_locale;
13483
13484   // Set the locale
13485   char result[ULOC_FULLNAME_CAPACITY];
13486   UErrorCode status = U_ZERO_ERROR;
13487   uloc_toLanguageTag(
13488       default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13489   if (U_SUCCESS(status)) {
13490     return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13491   }
13492
13493   return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
13494 }
13495
13496
13497 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
13498   HandleScope scope(isolate);
13499
13500   ASSERT(args.length() == 1);
13501
13502   CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13503
13504   uint32_t length = static_cast<uint32_t>(input->length()->Number());
13505   Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
13506   Handle<Name> maximized =
13507       isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
13508   Handle<Name> base =
13509       isolate->factory()->NewStringFromAscii(CStrVector("base"));
13510   for (unsigned int i = 0; i < length; ++i) {
13511     MaybeObject* maybe_string = input->GetElement(i);
13512     Object* locale_id;
13513     if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
13514       return isolate->Throw(isolate->heap()->illegal_argument_string());
13515     }
13516
13517     v8::String::Utf8Value utf8_locale_id(
13518         v8::Utils::ToLocal(Handle<String>(String::cast(locale_id))));
13519
13520     UErrorCode error = U_ZERO_ERROR;
13521
13522     // Convert from BCP47 to ICU format.
13523     // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13524     char icu_locale[ULOC_FULLNAME_CAPACITY];
13525     int icu_locale_length = 0;
13526     uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13527                         &icu_locale_length, &error);
13528     if (U_FAILURE(error) || icu_locale_length == 0) {
13529       return isolate->Throw(isolate->heap()->illegal_argument_string());
13530     }
13531
13532     // Maximize the locale.
13533     // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13534     char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13535     uloc_addLikelySubtags(
13536         icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13537
13538     // Remove extensions from maximized locale.
13539     // de_Latn_DE@collation=phonebook -> de_Latn_DE
13540     char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13541     uloc_getBaseName(
13542         icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13543
13544     // Get original name without extensions.
13545     // de_DE@collation=phonebook -> de_DE
13546     char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13547     uloc_getBaseName(
13548         icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13549
13550     // Convert from ICU locale format to BCP47 format.
13551     // de_Latn_DE -> de-Latn-DE
13552     char base_max_locale[ULOC_FULLNAME_CAPACITY];
13553     uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13554                        ULOC_FULLNAME_CAPACITY, FALSE, &error);
13555
13556     // de_DE -> de-DE
13557     char base_locale[ULOC_FULLNAME_CAPACITY];
13558     uloc_toLanguageTag(
13559         icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13560
13561     if (U_FAILURE(error)) {
13562       return isolate->Throw(isolate->heap()->illegal_argument_string());
13563     }
13564
13565     Handle<JSObject> result =
13566         isolate->factory()->NewJSObject(isolate->object_function());
13567     RETURN_IF_EMPTY_HANDLE(isolate,
13568         JSObject::SetLocalPropertyIgnoreAttributes(
13569             result,
13570             maximized,
13571             isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
13572             NONE));
13573     RETURN_IF_EMPTY_HANDLE(isolate,
13574         JSObject::SetLocalPropertyIgnoreAttributes(
13575             result,
13576             base,
13577             isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
13578             NONE));
13579     output->set(i, *result);
13580   }
13581
13582   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
13583   result->set_length(Smi::FromInt(length));
13584   return *result;
13585 }
13586
13587
13588 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
13589   HandleScope scope(isolate);
13590
13591   ASSERT(args.length() == 3);
13592
13593   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13594   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13595   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13596
13597   Handle<ObjectTemplateInfo> date_format_template =
13598       I18N::GetTemplate(isolate);
13599
13600   // Create an empty object wrapper.
13601   bool has_pending_exception = false;
13602   Handle<JSObject> local_object = Execution::InstantiateObject(
13603       date_format_template, &has_pending_exception);
13604   if (has_pending_exception) {
13605     ASSERT(isolate->has_pending_exception());
13606     return Failure::Exception();
13607   }
13608
13609   // Set date time formatter as internal field of the resulting JS object.
13610   icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
13611       isolate, locale, options, resolved);
13612
13613   if (!date_format) return isolate->ThrowIllegalOperation();
13614
13615   local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
13616
13617   RETURN_IF_EMPTY_HANDLE(isolate,
13618       JSObject::SetLocalPropertyIgnoreAttributes(
13619           local_object,
13620           isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
13621           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13622           NONE));
13623
13624   Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
13625                                  v8::Utils::ToLocal(local_object));
13626   // Make object handle weak so we can delete the data format once GC kicks in.
13627   wrapper.MakeWeak<void>(NULL, &DateFormat::DeleteDateFormat);
13628   wrapper.ClearAndLeak();
13629   return *local_object;
13630 }
13631
13632
13633 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
13634   HandleScope scope(isolate);
13635
13636   ASSERT(args.length() == 2);
13637
13638   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13639   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
13640
13641   bool has_pending_exception = false;
13642   double millis = Execution::ToNumber(date, &has_pending_exception)->Number();
13643   if (has_pending_exception) {
13644     ASSERT(isolate->has_pending_exception());
13645     return Failure::Exception();
13646   }
13647
13648   icu::SimpleDateFormat* date_format =
13649       DateFormat::UnpackDateFormat(isolate, date_format_holder);
13650   if (!date_format) return isolate->ThrowIllegalOperation();
13651
13652   icu::UnicodeString result;
13653   date_format->format(millis, result);
13654
13655   return *isolate->factory()->NewStringFromTwoByte(
13656       Vector<const uint16_t>(
13657           reinterpret_cast<const uint16_t*>(result.getBuffer()),
13658           result.length()));
13659 }
13660
13661
13662 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
13663   HandleScope scope(isolate);
13664
13665   ASSERT(args.length() == 2);
13666
13667   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13668   CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
13669
13670   v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
13671   icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
13672   icu::SimpleDateFormat* date_format =
13673       DateFormat::UnpackDateFormat(isolate, date_format_holder);
13674   if (!date_format) return isolate->ThrowIllegalOperation();
13675
13676   UErrorCode status = U_ZERO_ERROR;
13677   UDate date = date_format->parse(u_date, status);
13678   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
13679
13680   bool has_pending_exception = false;
13681   Handle<JSDate> result = Handle<JSDate>::cast(
13682       Execution::NewDate(static_cast<double>(date), &has_pending_exception));
13683   if (has_pending_exception) {
13684     ASSERT(isolate->has_pending_exception());
13685     return Failure::Exception();
13686   }
13687   return *result;
13688 }
13689
13690
13691 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
13692   HandleScope scope(isolate);
13693
13694   ASSERT(args.length() == 3);
13695
13696   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13697   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13698   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13699
13700   Handle<ObjectTemplateInfo> number_format_template =
13701       I18N::GetTemplate(isolate);
13702
13703   // Create an empty object wrapper.
13704   bool has_pending_exception = false;
13705   Handle<JSObject> local_object = Execution::InstantiateObject(
13706       number_format_template, &has_pending_exception);
13707   if (has_pending_exception) {
13708     ASSERT(isolate->has_pending_exception());
13709     return Failure::Exception();
13710   }
13711
13712   // Set number formatter as internal field of the resulting JS object.
13713   icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
13714       isolate, locale, options, resolved);
13715
13716   if (!number_format) return isolate->ThrowIllegalOperation();
13717
13718   local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
13719
13720   RETURN_IF_EMPTY_HANDLE(isolate,
13721       JSObject::SetLocalPropertyIgnoreAttributes(
13722           local_object,
13723           isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
13724           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13725           NONE));
13726
13727   Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
13728                                  v8::Utils::ToLocal(local_object));
13729   // Make object handle weak so we can delete the number format once GC kicks
13730   // in.
13731   wrapper.MakeWeak<void>(NULL, &NumberFormat::DeleteNumberFormat);
13732   wrapper.ClearAndLeak();
13733   return *local_object;
13734 }
13735
13736
13737 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
13738   HandleScope scope(isolate);
13739
13740   ASSERT(args.length() == 2);
13741
13742   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13743   CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
13744
13745   bool has_pending_exception = false;
13746   double value = Execution::ToNumber(number, &has_pending_exception)->Number();
13747   if (has_pending_exception) {
13748     ASSERT(isolate->has_pending_exception());
13749     return Failure::Exception();
13750   }
13751
13752   icu::DecimalFormat* number_format =
13753       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13754   if (!number_format) return isolate->ThrowIllegalOperation();
13755
13756   icu::UnicodeString result;
13757   number_format->format(value, result);
13758
13759   return *isolate->factory()->NewStringFromTwoByte(
13760       Vector<const uint16_t>(
13761           reinterpret_cast<const uint16_t*>(result.getBuffer()),
13762           result.length()));
13763 }
13764
13765
13766 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
13767   HandleScope scope(isolate);
13768
13769   ASSERT(args.length() == 2);
13770
13771   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13772   CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
13773
13774   v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
13775   icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
13776   icu::DecimalFormat* number_format =
13777       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13778   if (!number_format) return isolate->ThrowIllegalOperation();
13779
13780   UErrorCode status = U_ZERO_ERROR;
13781   icu::Formattable result;
13782   // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
13783   // to be part of Chrome.
13784   // TODO(cira): Include currency parsing code using parseCurrency call.
13785   // We need to check if the formatter parses all currencies or only the
13786   // one it was constructed with (it will impact the API - how to return ISO
13787   // code and the value).
13788   number_format->parse(u_number, result, status);
13789   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
13790
13791   switch (result.getType()) {
13792   case icu::Formattable::kDouble:
13793     return *isolate->factory()->NewNumber(result.getDouble());
13794   case icu::Formattable::kLong:
13795     return *isolate->factory()->NewNumberFromInt(result.getLong());
13796   case icu::Formattable::kInt64:
13797     return *isolate->factory()->NewNumber(
13798         static_cast<double>(result.getInt64()));
13799   default:
13800     return isolate->heap()->undefined_value();
13801   }
13802 }
13803
13804
13805 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
13806   HandleScope scope(isolate);
13807
13808   ASSERT(args.length() == 3);
13809
13810   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13811   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13812   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13813
13814   Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
13815
13816   // Create an empty object wrapper.
13817   bool has_pending_exception = false;
13818   Handle<JSObject> local_object = Execution::InstantiateObject(
13819       collator_template, &has_pending_exception);
13820   if (has_pending_exception) {
13821     ASSERT(isolate->has_pending_exception());
13822     return Failure::Exception();
13823   }
13824
13825   // Set collator as internal field of the resulting JS object.
13826   icu::Collator* collator = Collator::InitializeCollator(
13827       isolate, locale, options, resolved);
13828
13829   if (!collator) return isolate->ThrowIllegalOperation();
13830
13831   local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
13832
13833   RETURN_IF_EMPTY_HANDLE(isolate,
13834       JSObject::SetLocalPropertyIgnoreAttributes(
13835           local_object,
13836           isolate->factory()->NewStringFromAscii(CStrVector("collator")),
13837           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13838           NONE));
13839
13840   Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
13841                                  v8::Utils::ToLocal(local_object));
13842   // Make object handle weak so we can delete the collator once GC kicks in.
13843   wrapper.MakeWeak<void>(NULL, &Collator::DeleteCollator);
13844   wrapper.ClearAndLeak();
13845   return *local_object;
13846 }
13847
13848
13849 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
13850   HandleScope scope(isolate);
13851
13852   ASSERT(args.length() == 3);
13853
13854   CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
13855   CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
13856   CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
13857
13858   icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
13859   if (!collator) return isolate->ThrowIllegalOperation();
13860
13861   v8::String::Value string_value1(v8::Utils::ToLocal(string1));
13862   v8::String::Value string_value2(v8::Utils::ToLocal(string2));
13863   const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
13864   const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
13865   UErrorCode status = U_ZERO_ERROR;
13866   UCollationResult result = collator->compare(u_string1,
13867                                               string_value1.length(),
13868                                               u_string2,
13869                                               string_value2.length(),
13870                                               status);
13871   if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
13872
13873   return *isolate->factory()->NewNumberFromInt(result);
13874 }
13875 #endif  // V8_I18N_SUPPORT
13876
13877
13878 // Finds the script object from the script data. NOTE: This operation uses
13879 // heap traversal to find the function generated for the source position
13880 // for the requested break point. For lazily compiled functions several heap
13881 // traversals might be required rendering this operation as a rather slow
13882 // operation. However for setting break points which is normally done through
13883 // some kind of user interaction the performance is not crucial.
13884 static Handle<Object> Runtime_GetScriptFromScriptName(
13885     Handle<String> script_name) {
13886   // Scan the heap for Script objects to find the script with the requested
13887   // script data.
13888   Handle<Script> script;
13889   Factory* factory = script_name->GetIsolate()->factory();
13890   Heap* heap = script_name->GetHeap();
13891   heap->EnsureHeapIsIterable();
13892   DisallowHeapAllocation no_allocation_during_heap_iteration;
13893   HeapIterator iterator(heap);
13894   HeapObject* obj = NULL;
13895   while (script.is_null() && ((obj = iterator.next()) != NULL)) {
13896     // If a script is found check if it has the script data requested.
13897     if (obj->IsScript()) {
13898       if (Script::cast(obj)->name()->IsString()) {
13899         if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
13900           script = Handle<Script>(Script::cast(obj));
13901         }
13902       }
13903     }
13904   }
13905
13906   // If no script with the requested script data is found return undefined.
13907   if (script.is_null()) return factory->undefined_value();
13908
13909   // Return the script found.
13910   return GetScriptWrapper(script);
13911 }
13912
13913
13914 // Get the script object from script data. NOTE: Regarding performance
13915 // see the NOTE for GetScriptFromScriptData.
13916 // args[0]: script data for the script to find the source for
13917 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
13918   HandleScope scope(isolate);
13919
13920   ASSERT(args.length() == 1);
13921
13922   CONVERT_ARG_CHECKED(String, script_name, 0);
13923
13924   // Find the requested script.
13925   Handle<Object> result =
13926       Runtime_GetScriptFromScriptName(Handle<String>(script_name));
13927   return *result;
13928 }
13929
13930
13931 // Collect the raw data for a stack trace.  Returns an array of 4
13932 // element segments each containing a receiver, function, code and
13933 // native code offset.
13934 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
13935   HandleScope scope(isolate);
13936   ASSERT_EQ(args.length(), 3);
13937   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
13938   Handle<Object> caller = args.at<Object>(1);
13939   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
13940
13941   // Optionally capture a more detailed stack trace for the message.
13942   isolate->CaptureAndSetDetailedStackTrace(error_object);
13943   // Capture a simple stack trace for the stack property.
13944   return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
13945 }
13946
13947
13948 // Retrieve the stack trace.  This is the raw stack trace that yet has to
13949 // be formatted.  Since we only need this once, clear it afterwards.
13950 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
13951   HandleScope scope(isolate);
13952   ASSERT_EQ(args.length(), 1);
13953   CONVERT_ARG_CHECKED(JSObject, error_object, 0);
13954   String* key = isolate->heap()->hidden_stack_trace_string();
13955   Object* result = error_object->GetHiddenProperty(key);
13956   if (result->IsTheHole()) return isolate->heap()->undefined_value();
13957   RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
13958   error_object->DeleteHiddenProperty(key);
13959   return result;
13960 }
13961
13962
13963 // Returns V8 version as a string.
13964 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
13965   SealHandleScope shs(isolate);
13966   ASSERT_EQ(args.length(), 0);
13967
13968   const char* version_string = v8::V8::GetVersion();
13969
13970   return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
13971                                                   NOT_TENURED);
13972 }
13973
13974
13975 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
13976   SealHandleScope shs(isolate);
13977   ASSERT(args.length() == 2);
13978   OS::PrintError("abort: %s\n",
13979                  reinterpret_cast<char*>(args[0]) + args.smi_at(1));
13980   isolate->PrintStack(stderr);
13981   OS::Abort();
13982   UNREACHABLE();
13983   return NULL;
13984 }
13985
13986
13987 RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
13988   HandleScope scope(isolate);
13989   ASSERT(args.length() == 1);
13990   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
13991   FlattenString(str);
13992   return isolate->heap()->undefined_value();
13993 }
13994
13995
13996 RUNTIME_FUNCTION(MaybeObject*, Runtime_MigrateInstance) {
13997   HandleScope scope(isolate);
13998   ASSERT(args.length() == 1);
13999   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14000   if (!object->IsJSObject()) return Smi::FromInt(0);
14001   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14002   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14003   JSObject::MigrateInstance(js_object);
14004   return *object;
14005 }
14006
14007
14008 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
14009   SealHandleScope shs(isolate);
14010   // This is only called from codegen, so checks might be more lax.
14011   CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
14012   Object* key = args[1];
14013
14014   int finger_index = cache->finger_index();
14015   Object* o = cache->get(finger_index);
14016   if (o == key) {
14017     // The fastest case: hit the same place again.
14018     return cache->get(finger_index + 1);
14019   }
14020
14021   for (int i = finger_index - 2;
14022        i >= JSFunctionResultCache::kEntriesIndex;
14023        i -= 2) {
14024     o = cache->get(i);
14025     if (o == key) {
14026       cache->set_finger_index(i);
14027       return cache->get(i + 1);
14028     }
14029   }
14030
14031   int size = cache->size();
14032   ASSERT(size <= cache->length());
14033
14034   for (int i = size - 2; i > finger_index; i -= 2) {
14035     o = cache->get(i);
14036     if (o == key) {
14037       cache->set_finger_index(i);
14038       return cache->get(i + 1);
14039     }
14040   }
14041
14042   // There is no value in the cache.  Invoke the function and cache result.
14043   HandleScope scope(isolate);
14044
14045   Handle<JSFunctionResultCache> cache_handle(cache);
14046   Handle<Object> key_handle(key, isolate);
14047   Handle<Object> value;
14048   {
14049     Handle<JSFunction> factory(JSFunction::cast(
14050           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14051     // TODO(antonm): consider passing a receiver when constructing a cache.
14052     Handle<Object> receiver(isolate->native_context()->global_object(),
14053                             isolate);
14054     // This handle is nor shared, nor used later, so it's safe.
14055     Handle<Object> argv[] = { key_handle };
14056     bool pending_exception;
14057     value = Execution::Call(factory,
14058                             receiver,
14059                             ARRAY_SIZE(argv),
14060                             argv,
14061                             &pending_exception);
14062     if (pending_exception) return Failure::Exception();
14063   }
14064
14065 #ifdef VERIFY_HEAP
14066   if (FLAG_verify_heap) {
14067     cache_handle->JSFunctionResultCacheVerify();
14068   }
14069 #endif
14070
14071   // Function invocation may have cleared the cache.  Reread all the data.
14072   finger_index = cache_handle->finger_index();
14073   size = cache_handle->size();
14074
14075   // If we have spare room, put new data into it, otherwise evict post finger
14076   // entry which is likely to be the least recently used.
14077   int index = -1;
14078   if (size < cache_handle->length()) {
14079     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14080     index = size;
14081   } else {
14082     index = finger_index + JSFunctionResultCache::kEntrySize;
14083     if (index == cache_handle->length()) {
14084       index = JSFunctionResultCache::kEntriesIndex;
14085     }
14086   }
14087
14088   ASSERT(index % 2 == 0);
14089   ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
14090   ASSERT(index < cache_handle->length());
14091
14092   cache_handle->set(index, *key_handle);
14093   cache_handle->set(index + 1, *value);
14094   cache_handle->set_finger_index(index);
14095
14096 #ifdef VERIFY_HEAP
14097   if (FLAG_verify_heap) {
14098     cache_handle->JSFunctionResultCacheVerify();
14099   }
14100 #endif
14101
14102   return *value;
14103 }
14104
14105
14106 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
14107   SealHandleScope shs(isolate);
14108   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14109   return Smi::FromInt(message->start_position());
14110 }
14111
14112
14113 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
14114   SealHandleScope shs(isolate);
14115   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14116   return message->script();
14117 }
14118
14119
14120 #ifdef DEBUG
14121 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
14122 // Exclude the code in release mode.
14123 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
14124   HandleScope scope(isolate);
14125   ASSERT(args.length() == 0);
14126 #define COUNT_ENTRY(Name, argc, ressize) + 1
14127   int entry_count = 0
14128       RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14129       INLINE_FUNCTION_LIST(COUNT_ENTRY)
14130       INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
14131 #undef COUNT_ENTRY
14132   Factory* factory = isolate->factory();
14133   Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14134   int index = 0;
14135   bool inline_runtime_functions = false;
14136 #define ADD_ENTRY(Name, argc, ressize)                                       \
14137   {                                                                          \
14138     HandleScope inner(isolate);                                              \
14139     Handle<String> name;                                                     \
14140     /* Inline runtime functions have an underscore in front of the name. */  \
14141     if (inline_runtime_functions) {                                          \
14142       name = factory->NewStringFromAscii(                                    \
14143           Vector<const char>("_" #Name, StrLength("_" #Name)));              \
14144     } else {                                                                 \
14145       name = factory->NewStringFromAscii(                                    \
14146           Vector<const char>(#Name, StrLength(#Name)));                      \
14147     }                                                                        \
14148     Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
14149     pair_elements->set(0, *name);                                            \
14150     pair_elements->set(1, Smi::FromInt(argc));                               \
14151     Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
14152     elements->set(index++, *pair);                                           \
14153   }
14154   inline_runtime_functions = false;
14155   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14156   inline_runtime_functions = true;
14157   INLINE_FUNCTION_LIST(ADD_ENTRY)
14158   INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14159 #undef ADD_ENTRY
14160   ASSERT_EQ(index, entry_count);
14161   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14162   return *result;
14163 }
14164 #endif
14165
14166
14167 RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
14168   SealHandleScope shs(isolate);
14169   ASSERT(args.length() == 2);
14170   CONVERT_ARG_CHECKED(String, format, 0);
14171   CONVERT_ARG_CHECKED(JSArray, elms, 1);
14172   DisallowHeapAllocation no_gc;
14173   String::FlatContent format_content = format->GetFlatContent();
14174   RUNTIME_ASSERT(format_content.IsAscii());
14175   Vector<const uint8_t> chars = format_content.ToOneByteVector();
14176   isolate->logger()->LogRuntime(Vector<const char>::cast(chars), elms);
14177   return isolate->heap()->undefined_value();
14178 }
14179
14180
14181 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
14182   UNREACHABLE();  // implemented as macro in the parser
14183   return NULL;
14184 }
14185
14186
14187 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
14188   RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
14189     CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
14190     return isolate->heap()->ToBoolean(obj->Has##Name());  \
14191   }
14192
14193 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
14194 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14195 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14196 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14197 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14198 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14199 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
14200 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
14201 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14202 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
14203 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
14204 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
14205 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
14206 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
14207 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
14208 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
14209 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
14210 // Properties test sitting with elements tests - not fooling anyone.
14211 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
14212
14213 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14214
14215
14216 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
14217   SealHandleScope shs(isolate);
14218   ASSERT(args.length() == 2);
14219   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14220   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14221   return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14222 }
14223
14224
14225 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
14226   SealHandleScope shs(isolate);
14227   ASSERT(args.length() == 1);
14228
14229   if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14230   JSReceiver* obj = JSReceiver::cast(args[0]);
14231   if (obj->IsJSGlobalProxy()) {
14232     Object* proto = obj->GetPrototype();
14233     if (proto->IsNull()) return isolate->heap()->false_value();
14234     ASSERT(proto->IsJSGlobalObject());
14235     obj = JSReceiver::cast(proto);
14236   }
14237   return isolate->heap()->ToBoolean(obj->map()->is_observed());
14238 }
14239
14240
14241 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
14242   SealHandleScope shs(isolate);
14243   ASSERT(args.length() == 1);
14244   CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
14245   if (obj->IsJSGlobalProxy()) {
14246     Object* proto = obj->GetPrototype();
14247     if (proto->IsNull()) return isolate->heap()->undefined_value();
14248     ASSERT(proto->IsJSGlobalObject());
14249     obj = JSReceiver::cast(proto);
14250   }
14251   if (obj->IsJSProxy())
14252     return isolate->heap()->undefined_value();
14253
14254   ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
14255            JSObject::cast(obj)->HasFastElements()));
14256   ASSERT(obj->IsJSObject());
14257   return JSObject::cast(obj)->SetObserved(isolate);
14258 }
14259
14260
14261 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetObserverDeliveryPending) {
14262   SealHandleScope shs(isolate);
14263   ASSERT(args.length() == 0);
14264   isolate->set_observer_delivery_pending(true);
14265   return isolate->heap()->undefined_value();
14266 }
14267
14268
14269 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
14270   SealHandleScope shs(isolate);
14271   ASSERT(args.length() == 0);
14272   return isolate->heap()->observation_state();
14273 }
14274
14275
14276 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
14277   HandleScope scope(isolate);
14278   ASSERT(args.length() == 0);
14279   // TODO(adamk): Currently this runtime function is only called three times per
14280   // isolate. If it's called more often, the map should be moved into the
14281   // strong root list.
14282   Handle<Map> map =
14283       isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
14284   Handle<JSWeakMap> weakmap =
14285       Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
14286   return WeakCollectionInitialize(isolate, weakmap);
14287 }
14288
14289
14290 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
14291   SealHandleScope shs(isolate);
14292   ASSERT(args.length() == 1);
14293   Object* object = args[0];
14294   if (object->IsJSGlobalProxy()) {
14295     object = object->GetPrototype(isolate);
14296     if (object->IsNull()) return isolate->heap()->undefined_value();
14297   }
14298   return object;
14299 }
14300
14301
14302 static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
14303                                            Handle<JSFunction> constructor,
14304                                            Handle<Object> type_info,
14305                                            Arguments* caller_args) {
14306   bool holey = false;
14307   bool can_use_type_feedback = true;
14308   if (caller_args->length() == 1) {
14309     Object* argument_one = (*caller_args)[0];
14310     if (argument_one->IsSmi()) {
14311       int value = Smi::cast(argument_one)->value();
14312       if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
14313         // the array is a dictionary in this case.
14314         can_use_type_feedback = false;
14315       } else if (value != 0) {
14316         holey = true;
14317       }
14318     } else {
14319       // Non-smi length argument produces a dictionary
14320       can_use_type_feedback = false;
14321     }
14322   }
14323
14324   JSArray* array;
14325   MaybeObject* maybe_array;
14326   if (!type_info.is_null() &&
14327       *type_info != isolate->heap()->undefined_value() &&
14328       Cell::cast(*type_info)->value()->IsAllocationSite() &&
14329       can_use_type_feedback) {
14330     Handle<Cell> cell = Handle<Cell>::cast(type_info);
14331     Handle<AllocationSite> site = Handle<AllocationSite>(
14332         AllocationSite::cast(cell->value()), isolate);
14333     ASSERT(!site->IsLiteralSite());
14334     ElementsKind to_kind = site->GetElementsKind();
14335     if (holey && !IsFastHoleyElementsKind(to_kind)) {
14336       to_kind = GetHoleyElementsKind(to_kind);
14337       // Update the allocation site info to reflect the advice alteration.
14338       site->SetElementsKind(to_kind);
14339     }
14340
14341     maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite(
14342         *constructor, site);
14343     if (!maybe_array->To(&array)) return maybe_array;
14344   } else {
14345     maybe_array = isolate->heap()->AllocateJSObject(*constructor);
14346     if (!maybe_array->To(&array)) return maybe_array;
14347     // We might need to transition to holey
14348     ElementsKind kind = constructor->initial_map()->elements_kind();
14349     if (holey && !IsFastHoleyElementsKind(kind)) {
14350       kind = GetHoleyElementsKind(kind);
14351       maybe_array = array->TransitionElementsKind(kind);
14352       if (maybe_array->IsFailure()) return maybe_array;
14353     }
14354   }
14355
14356   maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0,
14357       DONT_INITIALIZE_ARRAY_ELEMENTS);
14358   if (maybe_array->IsFailure()) return maybe_array;
14359   maybe_array = ArrayConstructInitializeElements(array, caller_args);
14360   if (maybe_array->IsFailure()) return maybe_array;
14361   return array;
14362 }
14363
14364
14365 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
14366   HandleScope scope(isolate);
14367   // If we get 2 arguments then they are the stub parameters (constructor, type
14368   // info).  If we get 3, then the first one is a pointer to the arguments
14369   // passed by the caller.
14370   Arguments empty_args(0, NULL);
14371   bool no_caller_args = args.length() == 2;
14372   ASSERT(no_caller_args || args.length() == 3);
14373   int parameters_start = no_caller_args ? 0 : 1;
14374   Arguments* caller_args = no_caller_args
14375       ? &empty_args
14376       : reinterpret_cast<Arguments*>(args[0]);
14377   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14378   CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
14379
14380   return ArrayConstructorCommon(isolate,
14381                                 constructor,
14382                                 type_info,
14383                                 caller_args);
14384 }
14385
14386
14387 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) {
14388   HandleScope scope(isolate);
14389   Arguments empty_args(0, NULL);
14390   bool no_caller_args = args.length() == 1;
14391   ASSERT(no_caller_args || args.length() == 2);
14392   int parameters_start = no_caller_args ? 0 : 1;
14393   Arguments* caller_args = no_caller_args
14394       ? &empty_args
14395       : reinterpret_cast<Arguments*>(args[0]);
14396   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14397
14398   return ArrayConstructorCommon(isolate,
14399                                 constructor,
14400                                 Handle<Object>::null(),
14401                                 caller_args);
14402 }
14403
14404
14405 // ----------------------------------------------------------------------------
14406 // Implementation of Runtime
14407
14408 #define F(name, number_of_args, result_size)                             \
14409   { Runtime::k##name, Runtime::RUNTIME, #name,   \
14410     FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
14411
14412
14413 #define I(name, number_of_args, result_size)                             \
14414   { Runtime::kInline##name, Runtime::INLINE,     \
14415     "_" #name, NULL, number_of_args, result_size },
14416
14417 static const Runtime::Function kIntrinsicFunctions[] = {
14418   RUNTIME_FUNCTION_LIST(F)
14419   INLINE_FUNCTION_LIST(I)
14420   INLINE_RUNTIME_FUNCTION_LIST(I)
14421 };
14422
14423
14424 MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
14425                                                        Object* dictionary) {
14426   ASSERT(Isolate::Current()->heap() == heap);
14427   ASSERT(dictionary != NULL);
14428   ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
14429   for (int i = 0; i < kNumFunctions; ++i) {
14430     Object* name_string;
14431     { MaybeObject* maybe_name_string =
14432           heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
14433       if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
14434     }
14435     NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
14436     { MaybeObject* maybe_dictionary = name_dictionary->Add(
14437           String::cast(name_string),
14438           Smi::FromInt(i),
14439           PropertyDetails(NONE, NORMAL, Representation::None()));
14440       if (!maybe_dictionary->ToObject(&dictionary)) {
14441         // Non-recoverable failure.  Calling code must restart heap
14442         // initialization.
14443         return maybe_dictionary;
14444       }
14445     }
14446   }
14447   return dictionary;
14448 }
14449
14450
14451 const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
14452   Heap* heap = name->GetHeap();
14453   int entry = heap->intrinsic_function_names()->FindEntry(*name);
14454   if (entry != kNotFound) {
14455     Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
14456     int function_index = Smi::cast(smi_index)->value();
14457     return &(kIntrinsicFunctions[function_index]);
14458   }
14459   return NULL;
14460 }
14461
14462
14463 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
14464   return &(kIntrinsicFunctions[static_cast<int>(id)]);
14465 }
14466
14467
14468 void Runtime::PerformGC(Object* result) {
14469   Isolate* isolate = Isolate::Current();
14470   Failure* failure = Failure::cast(result);
14471   if (failure->IsRetryAfterGC()) {
14472     if (isolate->heap()->new_space()->AddFreshPage()) {
14473       return;
14474     }
14475
14476     // Try to do a garbage collection; ignore it if it fails. The C
14477     // entry stub will throw an out-of-memory exception in that case.
14478     isolate->heap()->CollectGarbage(failure->allocation_space(),
14479                                     "Runtime::PerformGC");
14480   } else {
14481     // Handle last resort GC and make sure to allow future allocations
14482     // to grow the heap without causing GCs (if possible).
14483     isolate->counters()->gc_last_resort_from_js()->Increment();
14484     isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
14485                                        "Runtime::PerformGC");
14486   }
14487 }
14488
14489
14490 } }  // namespace v8::internal