d1c509cccf7b230c2989204f733a593b44f3294e
[platform/framework/web/crosswalk.git] / src / 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 "allocation-site-scopes.h"
35 #include "api.h"
36 #include "arguments.h"
37 #include "bootstrapper.h"
38 #include "codegen.h"
39 #include "compilation-cache.h"
40 #include "compiler.h"
41 #include "cpu.h"
42 #include "cpu-profiler.h"
43 #include "dateparser-inl.h"
44 #include "debug.h"
45 #include "deoptimizer.h"
46 #include "date.h"
47 #include "execution.h"
48 #include "full-codegen.h"
49 #include "global-handles.h"
50 #include "isolate-inl.h"
51 #include "jsregexp.h"
52 #include "jsregexp-inl.h"
53 #include "json-parser.h"
54 #include "json-stringifier.h"
55 #include "liveedit.h"
56 #include "misc-intrinsics.h"
57 #include "parser.h"
58 #include "platform.h"
59 #include "runtime-profiler.h"
60 #include "runtime.h"
61 #include "scopeinfo.h"
62 #include "smart-pointers.h"
63 #include "string-search.h"
64 #include "stub-cache.h"
65 #include "uri.h"
66 #include "v8conversions.h"
67 #include "v8threads.h"
68 #include "vm-state-inl.h"
69
70 #ifdef V8_I18N_SUPPORT
71 #include "i18n.h"
72 #include "unicode/brkiter.h"
73 #include "unicode/calendar.h"
74 #include "unicode/coll.h"
75 #include "unicode/curramt.h"
76 #include "unicode/datefmt.h"
77 #include "unicode/dcfmtsym.h"
78 #include "unicode/decimfmt.h"
79 #include "unicode/dtfmtsym.h"
80 #include "unicode/dtptngen.h"
81 #include "unicode/locid.h"
82 #include "unicode/numfmt.h"
83 #include "unicode/numsys.h"
84 #include "unicode/rbbi.h"
85 #include "unicode/smpdtfmt.h"
86 #include "unicode/timezone.h"
87 #include "unicode/uchar.h"
88 #include "unicode/ucol.h"
89 #include "unicode/ucurr.h"
90 #include "unicode/uloc.h"
91 #include "unicode/unum.h"
92 #include "unicode/uversion.h"
93 #endif
94
95 #ifndef _STLP_VENDOR_CSTD
96 // STLPort doesn't import fpclassify and isless into the std namespace.
97 using std::fpclassify;
98 using std::isless;
99 #endif
100
101 namespace v8 {
102 namespace internal {
103
104
105 #define RUNTIME_ASSERT(value) \
106   if (!(value)) return isolate->ThrowIllegalOperation();
107
108 // Cast the given object to a value of the specified type and store
109 // it in a variable with the given name.  If the object is not of the
110 // expected type call IllegalOperation and return.
111 #define CONVERT_ARG_CHECKED(Type, name, index)                       \
112   RUNTIME_ASSERT(args[index]->Is##Type());                           \
113   Type* name = Type::cast(args[index]);
114
115 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
116   RUNTIME_ASSERT(args[index]->Is##Type());                           \
117   Handle<Type> name = args.at<Type>(index);
118
119 // Cast the given object to a boolean and store it in a variable with
120 // the given name.  If the object is not a boolean call IllegalOperation
121 // and return.
122 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
123   RUNTIME_ASSERT(args[index]->IsBoolean());                          \
124   bool name = args[index]->IsTrue();
125
126 // Cast the given argument to a Smi and store its value in an int variable
127 // with the given name.  If the argument is not a Smi call IllegalOperation
128 // and return.
129 #define CONVERT_SMI_ARG_CHECKED(name, index)                         \
130   RUNTIME_ASSERT(args[index]->IsSmi());                              \
131   int name = args.smi_at(index);
132
133 // Cast the given argument to a double and store it in a variable with
134 // the given name.  If the argument is not a number (as opposed to
135 // the number not-a-number) call IllegalOperation and return.
136 #define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
137   RUNTIME_ASSERT(args[index]->IsNumber());                           \
138   double name = args.number_at(index);
139
140 // Call the specified converter on the object *comand store the result in
141 // a variable of the specified type with the given name.  If the
142 // object is not a Number call IllegalOperation and return.
143 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
144   RUNTIME_ASSERT(obj->IsNumber());                                   \
145   type name = NumberTo##Type(obj);
146
147
148 // Cast the given argument to PropertyDetails and store its value in a
149 // variable with the given name.  If the argument is not a Smi call
150 // IllegalOperation and return.
151 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
152   RUNTIME_ASSERT(args[index]->IsSmi());                              \
153   PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
154
155
156 // Assert that the given argument has a valid value for a StrictMode
157 // and store it in a StrictMode variable with the given name.
158 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
159   RUNTIME_ASSERT(args[index]->IsSmi());                              \
160   RUNTIME_ASSERT(args.smi_at(index) == STRICT ||                     \
161                  args.smi_at(index) == SLOPPY);                      \
162   StrictMode name = static_cast<StrictMode>(args.smi_at(index));
163
164
165 static Handle<Map> ComputeObjectLiteralMap(
166     Handle<Context> context,
167     Handle<FixedArray> constant_properties,
168     bool* is_result_from_cache) {
169   Isolate* isolate = context->GetIsolate();
170   int properties_length = constant_properties->length();
171   int number_of_properties = properties_length / 2;
172   // Check that there are only internal strings and array indices among keys.
173   int number_of_string_keys = 0;
174   for (int p = 0; p != properties_length; p += 2) {
175     Object* key = constant_properties->get(p);
176     uint32_t element_index = 0;
177     if (key->IsInternalizedString()) {
178       number_of_string_keys++;
179     } else if (key->ToArrayIndex(&element_index)) {
180       // An index key does not require space in the property backing store.
181       number_of_properties--;
182     } else {
183       // Bail out as a non-internalized-string non-index key makes caching
184       // impossible.
185       // ASSERT to make sure that the if condition after the loop is false.
186       ASSERT(number_of_string_keys != number_of_properties);
187       break;
188     }
189   }
190   // If we only have internalized strings and array indices among keys then we
191   // can use the map cache in the native context.
192   const int kMaxKeys = 10;
193   if ((number_of_string_keys == number_of_properties) &&
194       (number_of_string_keys < kMaxKeys)) {
195     // Create the fixed array with the key.
196     Handle<FixedArray> keys =
197         isolate->factory()->NewFixedArray(number_of_string_keys);
198     if (number_of_string_keys > 0) {
199       int index = 0;
200       for (int p = 0; p < properties_length; p += 2) {
201         Object* key = constant_properties->get(p);
202         if (key->IsInternalizedString()) {
203           keys->set(index++, key);
204         }
205       }
206       ASSERT(index == number_of_string_keys);
207     }
208     *is_result_from_cache = true;
209     return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
210   }
211   *is_result_from_cache = false;
212   return isolate->factory()->CopyMap(
213       Handle<Map>(context->object_function()->initial_map()),
214       number_of_properties);
215 }
216
217
218 static Handle<Object> CreateLiteralBoilerplate(
219     Isolate* isolate,
220     Handle<FixedArray> literals,
221     Handle<FixedArray> constant_properties);
222
223
224 static Handle<Object> CreateObjectLiteralBoilerplate(
225     Isolate* isolate,
226     Handle<FixedArray> literals,
227     Handle<FixedArray> constant_properties,
228     bool should_have_fast_elements,
229     bool has_function_literal) {
230   // Get the native context from the literals array.  This is the
231   // context in which the function was created and we use the object
232   // function from this context to create the object literal.  We do
233   // not use the object function from the current native context
234   // because this might be the object function from another context
235   // which we should not have access to.
236   Handle<Context> context =
237       Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
238
239   // In case we have function literals, we want the object to be in
240   // slow properties mode for now. We don't go in the map cache because
241   // maps with constant functions can't be shared if the functions are
242   // not the same (which is the common case).
243   bool is_result_from_cache = false;
244   Handle<Map> map = has_function_literal
245       ? Handle<Map>(context->object_function()->initial_map())
246       : ComputeObjectLiteralMap(context,
247                                 constant_properties,
248                                 &is_result_from_cache);
249
250   PretenureFlag pretenure_flag =
251       isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
252
253   Handle<JSObject> boilerplate =
254       isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
255
256   // Normalize the elements of the boilerplate to save space if needed.
257   if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
258
259   // Add the constant properties to the boilerplate.
260   int length = constant_properties->length();
261   bool should_transform =
262       !is_result_from_cache && boilerplate->HasFastProperties();
263   if (should_transform || has_function_literal) {
264     // Normalize the properties of object to avoid n^2 behavior
265     // when extending the object multiple properties. Indicate the number of
266     // properties to be added.
267     JSObject::NormalizeProperties(
268         boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
269   }
270
271   // TODO(verwaest): Support tracking representations in the boilerplate.
272   for (int index = 0; index < length; index +=2) {
273     Handle<Object> key(constant_properties->get(index+0), isolate);
274     Handle<Object> value(constant_properties->get(index+1), isolate);
275     if (value->IsFixedArray()) {
276       // The value contains the constant_properties of a
277       // simple object or array literal.
278       Handle<FixedArray> array = Handle<FixedArray>::cast(value);
279       value = CreateLiteralBoilerplate(isolate, literals, array);
280       if (value.is_null()) return value;
281     }
282     Handle<Object> result;
283     uint32_t element_index = 0;
284     StoreMode mode = value->IsJSObject() ? FORCE_FIELD : ALLOW_AS_CONSTANT;
285     if (key->IsInternalizedString()) {
286       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
287         // Array index as string (uint32).
288         result = JSObject::SetOwnElement(
289             boilerplate, element_index, value, SLOPPY);
290       } else {
291         Handle<String> name(String::cast(*key));
292         ASSERT(!name->AsArrayIndex(&element_index));
293         result = JSObject::SetLocalPropertyIgnoreAttributes(
294             boilerplate, name, value, NONE,
295             Object::OPTIMAL_REPRESENTATION, mode);
296       }
297     } else if (key->ToArrayIndex(&element_index)) {
298       // Array index (uint32).
299       result = JSObject::SetOwnElement(
300           boilerplate, element_index, value, SLOPPY);
301     } else {
302       // Non-uint32 number.
303       ASSERT(key->IsNumber());
304       double num = key->Number();
305       char arr[100];
306       Vector<char> buffer(arr, ARRAY_SIZE(arr));
307       const char* str = DoubleToCString(num, buffer);
308       Handle<String> name =
309           isolate->factory()->NewStringFromAscii(CStrVector(str));
310       result = JSObject::SetLocalPropertyIgnoreAttributes(
311           boilerplate, name, value, NONE,
312           Object::OPTIMAL_REPRESENTATION, mode);
313     }
314     // If setting the property on the boilerplate throws an
315     // exception, the exception is converted to an empty handle in
316     // the handle based operations.  In that case, we need to
317     // convert back to an exception.
318     if (result.is_null()) return result;
319   }
320
321   // Transform to fast properties if necessary. For object literals with
322   // containing function literals we defer this operation until after all
323   // computed properties have been assigned so that we can generate
324   // constant function properties.
325   if (should_transform && !has_function_literal) {
326     JSObject::TransformToFastProperties(
327         boilerplate, boilerplate->map()->unused_property_fields());
328   }
329
330   return boilerplate;
331 }
332
333
334 MaybeObject* TransitionElements(Handle<Object> object,
335                                 ElementsKind to_kind,
336                                 Isolate* isolate) {
337   HandleScope scope(isolate);
338   if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
339   ElementsKind from_kind =
340       Handle<JSObject>::cast(object)->map()->elements_kind();
341   if (Map::IsValidElementsTransition(from_kind, to_kind)) {
342     JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
343     return *object;
344   }
345   return isolate->ThrowIllegalOperation();
346 }
347
348
349 static const int kSmiLiteralMinimumLength = 1024;
350
351
352 Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
353     Isolate* isolate,
354     Handle<FixedArray> literals,
355     Handle<FixedArray> elements) {
356   // Create the JSArray.
357   Handle<JSFunction> constructor(
358       JSFunction::NativeContextFromLiterals(*literals)->array_function());
359
360   PretenureFlag pretenure_flag =
361       isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
362
363   Handle<JSArray> object = Handle<JSArray>::cast(
364       isolate->factory()->NewJSObject(constructor, pretenure_flag));
365
366   ElementsKind constant_elements_kind =
367       static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
368   Handle<FixedArrayBase> constant_elements_values(
369       FixedArrayBase::cast(elements->get(1)));
370
371   ASSERT(IsFastElementsKind(constant_elements_kind));
372   Context* native_context = isolate->context()->native_context();
373   Object* maybe_maps_array = native_context->js_array_maps();
374   ASSERT(!maybe_maps_array->IsUndefined());
375   Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
376       constant_elements_kind);
377   ASSERT(maybe_map->IsMap());
378   object->set_map(Map::cast(maybe_map));
379
380   Handle<FixedArrayBase> copied_elements_values;
381   if (IsFastDoubleElementsKind(constant_elements_kind)) {
382     ASSERT(FLAG_smi_only_arrays);
383     copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
384         Handle<FixedDoubleArray>::cast(constant_elements_values));
385   } else {
386     ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
387     const bool is_cow =
388         (constant_elements_values->map() ==
389          isolate->heap()->fixed_cow_array_map());
390     if (is_cow) {
391       copied_elements_values = constant_elements_values;
392 #if DEBUG
393       Handle<FixedArray> fixed_array_values =
394           Handle<FixedArray>::cast(copied_elements_values);
395       for (int i = 0; i < fixed_array_values->length(); i++) {
396         ASSERT(!fixed_array_values->get(i)->IsFixedArray());
397       }
398 #endif
399     } else {
400       Handle<FixedArray> fixed_array_values =
401           Handle<FixedArray>::cast(constant_elements_values);
402       Handle<FixedArray> fixed_array_values_copy =
403           isolate->factory()->CopyFixedArray(fixed_array_values);
404       copied_elements_values = fixed_array_values_copy;
405       for (int i = 0; i < fixed_array_values->length(); i++) {
406         Object* current = fixed_array_values->get(i);
407         if (current->IsFixedArray()) {
408           // The value contains the constant_properties of a
409           // simple object or array literal.
410           Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
411           Handle<Object> result =
412               CreateLiteralBoilerplate(isolate, literals, fa);
413           if (result.is_null()) return result;
414           fixed_array_values_copy->set(i, *result);
415         }
416       }
417     }
418   }
419   object->set_elements(*copied_elements_values);
420   object->set_length(Smi::FromInt(copied_elements_values->length()));
421
422   //  Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
423   //  on or the object is larger than the threshold.
424   if (!FLAG_smi_only_arrays &&
425       constant_elements_values->length() < kSmiLiteralMinimumLength) {
426     ElementsKind elements_kind = object->GetElementsKind();
427     if (!IsFastObjectElementsKind(elements_kind)) {
428       if (IsFastHoleyElementsKind(elements_kind)) {
429         CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
430                                   isolate)->IsFailure());
431       } else {
432         CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
433       }
434     }
435   }
436
437   object->ValidateElements();
438   return object;
439 }
440
441
442 static Handle<Object> CreateLiteralBoilerplate(
443     Isolate* isolate,
444     Handle<FixedArray> literals,
445     Handle<FixedArray> array) {
446   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
447   const bool kHasNoFunctionLiteral = false;
448   switch (CompileTimeValue::GetLiteralType(array)) {
449     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
450       return CreateObjectLiteralBoilerplate(isolate,
451                                             literals,
452                                             elements,
453                                             true,
454                                             kHasNoFunctionLiteral);
455     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
456       return CreateObjectLiteralBoilerplate(isolate,
457                                             literals,
458                                             elements,
459                                             false,
460                                             kHasNoFunctionLiteral);
461     case CompileTimeValue::ARRAY_LITERAL:
462       return Runtime::CreateArrayLiteralBoilerplate(
463           isolate, literals, elements);
464     default:
465       UNREACHABLE();
466       return Handle<Object>::null();
467   }
468 }
469
470
471 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateObjectLiteral) {
472   HandleScope scope(isolate);
473   ASSERT(args.length() == 4);
474   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
475   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
476   CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
477   CONVERT_SMI_ARG_CHECKED(flags, 3);
478   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
479   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
480
481   // Check if boilerplate exists. If not, create it first.
482   Handle<Object> literal_site(literals->get(literals_index), isolate);
483   Handle<AllocationSite> site;
484   Handle<JSObject> boilerplate;
485   if (*literal_site == isolate->heap()->undefined_value()) {
486     Handle<Object> raw_boilerplate = CreateObjectLiteralBoilerplate(
487         isolate,
488         literals,
489         constant_properties,
490         should_have_fast_elements,
491         has_function_literal);
492     RETURN_IF_EMPTY_HANDLE(isolate, raw_boilerplate);
493     boilerplate = Handle<JSObject>::cast(raw_boilerplate);
494
495     AllocationSiteCreationContext creation_context(isolate);
496     site = creation_context.EnterNewScope();
497     RETURN_IF_EMPTY_HANDLE(isolate,
498                            JSObject::DeepWalk(boilerplate, &creation_context));
499     creation_context.ExitScope(site, boilerplate);
500
501     // Update the functions literal and return the boilerplate.
502     literals->set(literals_index, *site);
503   } else {
504     site = Handle<AllocationSite>::cast(literal_site);
505     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
506                                    isolate);
507   }
508
509   AllocationSiteUsageContext usage_context(isolate, site, true);
510   usage_context.EnterNewScope();
511   Handle<Object> copy = JSObject::DeepCopy(boilerplate, &usage_context);
512   usage_context.ExitScope(site, boilerplate);
513   RETURN_IF_EMPTY_HANDLE(isolate, copy);
514   return *copy;
515 }
516
517
518 static Handle<AllocationSite> GetLiteralAllocationSite(
519     Isolate* isolate,
520     Handle<FixedArray> literals,
521     int literals_index,
522     Handle<FixedArray> elements) {
523   // Check if boilerplate exists. If not, create it first.
524   Handle<Object> literal_site(literals->get(literals_index), isolate);
525   Handle<AllocationSite> site;
526   if (*literal_site == isolate->heap()->undefined_value()) {
527     ASSERT(*elements != isolate->heap()->empty_fixed_array());
528     Handle<Object> boilerplate =
529         Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
530     if (boilerplate.is_null()) return Handle<AllocationSite>::null();
531
532     AllocationSiteCreationContext creation_context(isolate);
533     site = creation_context.EnterNewScope();
534     if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate),
535                            &creation_context).is_null()) {
536       return Handle<AllocationSite>::null();
537     }
538     creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
539
540     literals->set(literals_index, *site);
541   } else {
542     site = Handle<AllocationSite>::cast(literal_site);
543   }
544
545   return site;
546 }
547
548
549 static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
550                                            Handle<FixedArray> literals,
551                                            int literals_index,
552                                            Handle<FixedArray> elements,
553                                            int flags) {
554   Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
555       literals_index, elements);
556   RETURN_IF_EMPTY_HANDLE(isolate, site);
557
558   bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
559   Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
560   AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
561   usage_context.EnterNewScope();
562   JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
563       ? JSObject::kNoHints
564       : JSObject::kObjectIsShallowArray;
565   Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
566                                              hints);
567   usage_context.ExitScope(site, boilerplate);
568   RETURN_IF_EMPTY_HANDLE(isolate, copy);
569   return *copy;
570 }
571
572
573 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateArrayLiteral) {
574   HandleScope scope(isolate);
575   ASSERT(args.length() == 4);
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   CONVERT_SMI_ARG_CHECKED(flags, 3);
580
581   return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
582                                 flags);
583 }
584
585
586 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateArrayLiteralStubBailout) {
587   HandleScope scope(isolate);
588   ASSERT(args.length() == 3);
589   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
590   CONVERT_SMI_ARG_CHECKED(literals_index, 1);
591   CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
592
593   return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
594                                 ArrayLiteral::kShallowElements);
595 }
596
597
598 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
599   HandleScope scope(isolate);
600   ASSERT(args.length() == 1);
601   Handle<Object> name(args[0], isolate);
602   RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
603   Symbol* symbol;
604   MaybeObject* maybe = isolate->heap()->AllocateSymbol();
605   if (!maybe->To(&symbol)) return maybe;
606   if (name->IsString()) symbol->set_name(*name);
607   return symbol;
608 }
609
610
611 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreatePrivateSymbol) {
612   HandleScope scope(isolate);
613   ASSERT(args.length() == 1);
614   Handle<Object> name(args[0], isolate);
615   RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
616   Symbol* symbol;
617   MaybeObject* maybe = isolate->heap()->AllocatePrivateSymbol();
618   if (!maybe->To(&symbol)) return maybe;
619   if (name->IsString()) symbol->set_name(*name);
620   return symbol;
621 }
622
623
624 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateGlobalPrivateSymbol) {
625   HandleScope scope(isolate);
626   ASSERT(args.length() == 1);
627   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
628   Handle<JSObject> registry = isolate->GetSymbolRegistry();
629   Handle<String> part = isolate->factory()->private_intern_string();
630   Handle<JSObject> privates =
631       Handle<JSObject>::cast(JSObject::GetProperty(registry, part));
632   Handle<Object> symbol = JSObject::GetProperty(privates, name);
633   if (!symbol->IsSymbol()) {
634     ASSERT(symbol->IsUndefined());
635     symbol = isolate->factory()->NewPrivateSymbol();
636     Handle<Symbol>::cast(symbol)->set_name(*name);
637     JSObject::SetProperty(privates, name, symbol, NONE, STRICT);
638   }
639   return *symbol;
640 }
641
642
643 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewSymbolWrapper) {
644   ASSERT(args.length() == 1);
645   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
646   return symbol->ToObject(isolate);
647 }
648
649
650 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolDescription) {
651   SealHandleScope shs(isolate);
652   ASSERT(args.length() == 1);
653   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
654   return symbol->name();
655 }
656
657
658 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolRegistry) {
659   HandleScope scope(isolate);
660   ASSERT(args.length() == 0);
661   return *isolate->GetSymbolRegistry();
662 }
663
664
665 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolIsPrivate) {
666   SealHandleScope shs(isolate);
667   ASSERT(args.length() == 1);
668   CONVERT_ARG_CHECKED(Symbol, symbol, 0);
669   return isolate->heap()->ToBoolean(symbol->is_private());
670 }
671
672
673 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
674   SealHandleScope shs(isolate);
675   ASSERT(args.length() == 2);
676   CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
677   Object* prototype = args[1];
678   Object* used_prototype =
679       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
680   return isolate->heap()->AllocateJSProxy(handler, used_prototype);
681 }
682
683
684 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
685   SealHandleScope shs(isolate);
686   ASSERT(args.length() == 4);
687   CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
688   Object* call_trap = args[1];
689   RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
690   CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
691   Object* prototype = args[3];
692   Object* used_prototype =
693       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
694   return isolate->heap()->AllocateJSFunctionProxy(
695       handler, call_trap, construct_trap, used_prototype);
696 }
697
698
699 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
700   SealHandleScope shs(isolate);
701   ASSERT(args.length() == 1);
702   Object* obj = args[0];
703   return isolate->heap()->ToBoolean(obj->IsJSProxy());
704 }
705
706
707 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
708   SealHandleScope shs(isolate);
709   ASSERT(args.length() == 1);
710   Object* obj = args[0];
711   return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
712 }
713
714
715 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
716   SealHandleScope shs(isolate);
717   ASSERT(args.length() == 1);
718   CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
719   return proxy->handler();
720 }
721
722
723 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
724   SealHandleScope shs(isolate);
725   ASSERT(args.length() == 1);
726   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
727   return proxy->call_trap();
728 }
729
730
731 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
732   SealHandleScope shs(isolate);
733   ASSERT(args.length() == 1);
734   CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
735   return proxy->construct_trap();
736 }
737
738
739 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
740   HandleScope scope(isolate);
741   ASSERT(args.length() == 1);
742   CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
743   JSProxy::Fix(proxy);
744   return isolate->heap()->undefined_value();
745 }
746
747
748 void Runtime::FreeArrayBuffer(Isolate* isolate,
749                               JSArrayBuffer* phantom_array_buffer) {
750   if (phantom_array_buffer->should_be_freed()) {
751     ASSERT(phantom_array_buffer->is_external());
752     free(phantom_array_buffer->backing_store());
753   }
754   if (phantom_array_buffer->is_external()) return;
755
756   size_t allocated_length = NumberToSize(
757       isolate, phantom_array_buffer->byte_length());
758
759   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
760       -static_cast<int64_t>(allocated_length));
761   CHECK(V8::ArrayBufferAllocator() != NULL);
762   V8::ArrayBufferAllocator()->Free(
763       phantom_array_buffer->backing_store(),
764       allocated_length);
765 }
766
767
768 void Runtime::SetupArrayBuffer(Isolate* isolate,
769                                Handle<JSArrayBuffer> array_buffer,
770                                bool is_external,
771                                void* data,
772                                size_t allocated_length) {
773   ASSERT(array_buffer->GetInternalFieldCount() ==
774       v8::ArrayBuffer::kInternalFieldCount);
775   for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
776     array_buffer->SetInternalField(i, Smi::FromInt(0));
777   }
778   array_buffer->set_backing_store(data);
779   array_buffer->set_flag(Smi::FromInt(0));
780   array_buffer->set_is_external(is_external);
781
782   Handle<Object> byte_length =
783       isolate->factory()->NewNumberFromSize(allocated_length);
784   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
785   array_buffer->set_byte_length(*byte_length);
786
787   array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
788   isolate->heap()->set_array_buffers_list(*array_buffer);
789   array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
790 }
791
792
793 bool Runtime::SetupArrayBufferAllocatingData(
794     Isolate* isolate,
795     Handle<JSArrayBuffer> array_buffer,
796     size_t allocated_length,
797     bool initialize) {
798   void* data;
799   CHECK(V8::ArrayBufferAllocator() != NULL);
800   if (allocated_length != 0) {
801     if (initialize) {
802       data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
803     } else {
804       data =
805         V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
806     }
807     if (data == NULL) return false;
808   } else {
809     data = NULL;
810   }
811
812   SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
813
814   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
815
816   return true;
817 }
818
819
820 void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
821   Isolate* isolate = array_buffer->GetIsolate();
822   for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate);
823        !view_obj->IsUndefined();) {
824     Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj));
825     if (view->IsJSTypedArray()) {
826       JSTypedArray::cast(*view)->Neuter();
827     } else if (view->IsJSDataView()) {
828       JSDataView::cast(*view)->Neuter();
829     } else {
830       UNREACHABLE();
831     }
832     view_obj = handle(view->weak_next(), isolate);
833   }
834   array_buffer->Neuter();
835 }
836
837
838 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
839   HandleScope scope(isolate);
840   ASSERT(args.length() == 2);
841   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
842   CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
843   size_t allocated_length;
844   if (byteLength->IsSmi()) {
845     allocated_length = Smi::cast(*byteLength)->value();
846   } else {
847     ASSERT(byteLength->IsHeapNumber());
848     double value = HeapNumber::cast(*byteLength)->value();
849
850     ASSERT(value >= 0);
851
852     if (value > std::numeric_limits<size_t>::max()) {
853       return isolate->Throw(
854           *isolate->factory()->NewRangeError("invalid_array_buffer_length",
855             HandleVector<Object>(NULL, 0)));
856     }
857
858     allocated_length = static_cast<size_t>(value);
859   }
860
861   if (!Runtime::SetupArrayBufferAllocatingData(isolate,
862                                                holder, allocated_length)) {
863       return isolate->Throw(*isolate->factory()->
864           NewRangeError("invalid_array_buffer_length",
865             HandleVector<Object>(NULL, 0)));
866   }
867
868   return *holder;
869 }
870
871
872 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
873   SealHandleScope shs(isolate);
874   ASSERT(args.length() == 1);
875   CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
876   return holder->byte_length();
877 }
878
879
880 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
881   HandleScope scope(isolate);
882   ASSERT(args.length() == 3);
883   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
884   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
885   CONVERT_DOUBLE_ARG_CHECKED(first, 2);
886   size_t start = static_cast<size_t>(first);
887   size_t target_length = NumberToSize(isolate, target->byte_length());
888
889   if (target_length == 0) return isolate->heap()->undefined_value();
890
891   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
892   CHECK(start <= source_byte_length);
893   CHECK(source_byte_length - start >= target_length);
894   uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
895   uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
896   CopyBytes(target_data, source_data + start, target_length);
897   return isolate->heap()->undefined_value();
898 }
899
900
901 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) {
902   HandleScope scope(isolate);
903   ASSERT(args.length() == 1);
904   CONVERT_ARG_CHECKED(Object, object, 0);
905   return object->IsJSArrayBufferView()
906     ? isolate->heap()->true_value()
907     : isolate->heap()->false_value();
908 }
909
910
911 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferNeuter) {
912   HandleScope scope(isolate);
913   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
914   if (array_buffer->backing_store() == NULL) {
915     CHECK(Smi::FromInt(0) == array_buffer->byte_length());
916     return isolate->heap()->undefined_value();
917   }
918   ASSERT(!array_buffer->is_external());
919   void* backing_store = array_buffer->backing_store();
920   size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
921   array_buffer->set_is_external(true);
922   Runtime::NeuterArrayBuffer(array_buffer);
923   V8::ArrayBufferAllocator()->Free(backing_store, byte_length);
924   return isolate->heap()->undefined_value();
925 }
926
927
928 void Runtime::ArrayIdToTypeAndSize(
929     int arrayId,
930     ExternalArrayType* array_type,
931     ElementsKind* external_elements_kind,
932     ElementsKind* fixed_elements_kind,
933     size_t* element_size) {
934   switch (arrayId) {
935 #define ARRAY_ID_CASE(Type, type, TYPE, ctype, size)                           \
936     case ARRAY_ID_##TYPE:                                                      \
937       *array_type = kExternal##Type##Array;                                    \
938       *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS;                    \
939       *fixed_elements_kind = TYPE##_ELEMENTS;                                  \
940       *element_size = size;                                                    \
941       break;
942
943     TYPED_ARRAYS(ARRAY_ID_CASE)
944 #undef ARRAY_ID_CASE
945
946     default:
947       UNREACHABLE();
948   }
949 }
950
951
952 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
953   HandleScope scope(isolate);
954   ASSERT(args.length() == 5);
955   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
956   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
957   CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
958   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
959   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
960
961   ASSERT(holder->GetInternalFieldCount() ==
962       v8::ArrayBufferView::kInternalFieldCount);
963   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
964     holder->SetInternalField(i, Smi::FromInt(0));
965   }
966
967   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
968   size_t element_size = 1;  // Bogus initialization.
969   ElementsKind external_elements_kind = EXTERNAL_INT8_ELEMENTS;
970   ElementsKind fixed_elements_kind = INT8_ELEMENTS;
971   Runtime::ArrayIdToTypeAndSize(arrayId,
972       &array_type,
973       &external_elements_kind,
974       &fixed_elements_kind,
975       &element_size);
976
977   holder->set_byte_offset(*byte_offset_object);
978   holder->set_byte_length(*byte_length_object);
979
980   size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
981   size_t byte_length = NumberToSize(isolate, *byte_length_object);
982
983   CHECK_EQ(0, static_cast<int>(byte_length % element_size));
984   size_t length = byte_length / element_size;
985
986   if (length > static_cast<unsigned>(Smi::kMaxValue)) {
987     return isolate->Throw(*isolate->factory()->
988           NewRangeError("invalid_typed_array_length",
989             HandleVector<Object>(NULL, 0)));
990   }
991
992   Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
993   holder->set_length(*length_obj);
994   if (!maybe_buffer->IsNull()) {
995     Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(*maybe_buffer));
996
997     size_t array_buffer_byte_length =
998         NumberToSize(isolate, buffer->byte_length());
999     CHECK(byte_offset <= array_buffer_byte_length);
1000     CHECK(array_buffer_byte_length - byte_offset >= byte_length);
1001
1002     holder->set_buffer(*buffer);
1003     holder->set_weak_next(buffer->weak_first_view());
1004     buffer->set_weak_first_view(*holder);
1005
1006     Handle<ExternalArray> elements =
1007         isolate->factory()->NewExternalArray(
1008             static_cast<int>(length), array_type,
1009             static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
1010     Handle<Map> map =
1011         JSObject::GetElementsTransitionMap(holder, external_elements_kind);
1012     holder->set_map_and_elements(*map, *elements);
1013     ASSERT(IsExternalArrayElementsKind(holder->map()->elements_kind()));
1014   } else {
1015     holder->set_buffer(Smi::FromInt(0));
1016     holder->set_weak_next(isolate->heap()->undefined_value());
1017     Handle<FixedTypedArrayBase> elements =
1018         isolate->factory()->NewFixedTypedArray(
1019             static_cast<int>(length), array_type);
1020     holder->set_elements(*elements);
1021   }
1022   return isolate->heap()->undefined_value();
1023 }
1024
1025
1026 // Initializes a typed array from an array-like object.
1027 // If an array-like object happens to be a typed array of the same type,
1028 // initializes backing store using memove.
1029 //
1030 // Returns true if backing store was initialized or false otherwise.
1031 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
1032   HandleScope scope(isolate);
1033   ASSERT(args.length() == 4);
1034   CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
1035   CONVERT_SMI_ARG_CHECKED(arrayId, 1);
1036   CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
1037   CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
1038
1039   ASSERT(holder->GetInternalFieldCount() ==
1040       v8::ArrayBufferView::kInternalFieldCount);
1041   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1042     holder->SetInternalField(i, Smi::FromInt(0));
1043   }
1044
1045   ExternalArrayType array_type = kExternalInt8Array;  // Bogus initialization.
1046   size_t element_size = 1;  // Bogus initialization.
1047   ElementsKind external_elements_kind;
1048   ElementsKind fixed_elements_kind;
1049   Runtime::ArrayIdToTypeAndSize(arrayId,
1050       &array_type,
1051       &external_elements_kind,
1052       &fixed_elements_kind,
1053       &element_size);
1054
1055   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
1056   if (source->IsJSTypedArray() &&
1057       JSTypedArray::cast(*source)->type() == array_type) {
1058     length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate);
1059   }
1060   size_t length = NumberToSize(isolate, *length_obj);
1061
1062   if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
1063       (length > (kMaxInt / element_size))) {
1064     return isolate->Throw(*isolate->factory()->
1065           NewRangeError("invalid_typed_array_length",
1066             HandleVector<Object>(NULL, 0)));
1067   }
1068   size_t byte_length = length * element_size;
1069
1070   // NOTE: not initializing backing store.
1071   // We assume that the caller of this function will initialize holder
1072   // with the loop
1073   //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
1074   // We assume that the caller of this function is always a typed array
1075   // constructor.
1076   // If source is a typed array, this loop will always run to completion,
1077   // so we are sure that the backing store will be initialized.
1078   // Otherwise, the indexing operation might throw, so the loop will not
1079   // run to completion and the typed array might remain partly initialized.
1080   // However we further assume that the caller of this function is a typed array
1081   // constructor, and the exception will propagate out of the constructor,
1082   // therefore uninitialized memory will not be accessible by a user program.
1083   //
1084   // TODO(dslomov): revise this once we support subclassing.
1085
1086   if (!Runtime::SetupArrayBufferAllocatingData(
1087         isolate, buffer, byte_length, false)) {
1088     return isolate->Throw(*isolate->factory()->
1089           NewRangeError("invalid_array_buffer_length",
1090             HandleVector<Object>(NULL, 0)));
1091   }
1092
1093   holder->set_buffer(*buffer);
1094   holder->set_byte_offset(Smi::FromInt(0));
1095   Handle<Object> byte_length_obj(
1096       isolate->factory()->NewNumberFromSize(byte_length));
1097   holder->set_byte_length(*byte_length_obj);
1098   holder->set_length(*length_obj);
1099   holder->set_weak_next(buffer->weak_first_view());
1100   buffer->set_weak_first_view(*holder);
1101
1102   Handle<ExternalArray> elements =
1103       isolate->factory()->NewExternalArray(
1104           static_cast<int>(length), array_type,
1105           static_cast<uint8_t*>(buffer->backing_store()));
1106   Handle<Map> map = JSObject::GetElementsTransitionMap(
1107       holder, external_elements_kind);
1108   holder->set_map_and_elements(*map, *elements);
1109
1110   if (source->IsJSTypedArray()) {
1111     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
1112
1113     if (typed_array->type() == holder->type()) {
1114       uint8_t* backing_store =
1115         static_cast<uint8_t*>(
1116           typed_array->GetBuffer()->backing_store());
1117       size_t source_byte_offset =
1118           NumberToSize(isolate, typed_array->byte_offset());
1119       memcpy(
1120           buffer->backing_store(),
1121           backing_store + source_byte_offset,
1122           byte_length);
1123       return *isolate->factory()->true_value();
1124     } else {
1125       return *isolate->factory()->false_value();
1126     }
1127   }
1128
1129   return *isolate->factory()->false_value();
1130 }
1131
1132
1133 #define TYPED_ARRAY_GETTER(getter, accessor) \
1134   RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) {             \
1135     HandleScope scope(isolate);                                               \
1136     ASSERT(args.length() == 1);                                               \
1137     CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0);                            \
1138     if (!holder->IsJSTypedArray())                                            \
1139       return isolate->Throw(*isolate->factory()->NewTypeError(                \
1140           "not_typed_array", HandleVector<Object>(NULL, 0)));                 \
1141     Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder));            \
1142     return typed_array->accessor();                                           \
1143   }
1144
1145 TYPED_ARRAY_GETTER(ByteLength, byte_length)
1146 TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
1147 TYPED_ARRAY_GETTER(Length, length)
1148
1149 #undef TYPED_ARRAY_GETTER
1150
1151 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGetBuffer) {
1152   HandleScope scope(isolate);
1153   ASSERT(args.length() == 1);
1154   CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0);
1155   if (!holder->IsJSTypedArray())
1156     return isolate->Throw(*isolate->factory()->NewTypeError(
1157         "not_typed_array", HandleVector<Object>(NULL, 0)));
1158   Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder));
1159   return *typed_array->GetBuffer();
1160 }
1161
1162
1163 // Return codes for Runtime_TypedArraySetFastCases.
1164 // Should be synchronized with typedarray.js natives.
1165 enum TypedArraySetResultCodes {
1166   // Set from typed array of the same type.
1167   // This is processed by TypedArraySetFastCases
1168   TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
1169   // Set from typed array of the different type, overlapping in memory.
1170   TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
1171   // Set from typed array of the different type, non-overlapping.
1172   TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
1173   // Set from non-typed array.
1174   TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
1175 };
1176
1177
1178 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
1179   HandleScope scope(isolate);
1180   CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
1181   CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
1182   CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
1183
1184   if (!target_obj->IsJSTypedArray())
1185     return isolate->Throw(*isolate->factory()->NewTypeError(
1186         "not_typed_array", HandleVector<Object>(NULL, 0)));
1187
1188   if (!source_obj->IsJSTypedArray())
1189     return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
1190
1191   Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1192   Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1193   size_t offset = NumberToSize(isolate, *offset_obj);
1194   size_t target_length = NumberToSize(isolate, target->length());
1195   size_t source_length = NumberToSize(isolate, source->length());
1196   size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1197   size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1198   if (offset > target_length ||
1199       offset + source_length > target_length ||
1200       offset + source_length < offset)  // overflow
1201     return isolate->Throw(*isolate->factory()->NewRangeError(
1202           "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
1203
1204   size_t target_offset = NumberToSize(isolate, target->byte_offset());
1205   size_t source_offset = NumberToSize(isolate, source->byte_offset());
1206   uint8_t* target_base =
1207       static_cast<uint8_t*>(
1208         target->GetBuffer()->backing_store()) + target_offset;
1209   uint8_t* source_base =
1210       static_cast<uint8_t*>(
1211         source->GetBuffer()->backing_store()) + source_offset;
1212
1213   // Typed arrays of the same type: use memmove.
1214   if (target->type() == source->type()) {
1215     memmove(target_base + offset * target->element_size(),
1216         source_base, source_byte_length);
1217     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
1218   }
1219
1220   // Typed arrays of different types over the same backing store
1221   if ((source_base <= target_base &&
1222         source_base + source_byte_length > target_base) ||
1223       (target_base <= source_base &&
1224         target_base + target_byte_length > source_base)) {
1225     // We do not support overlapping ArrayBuffers
1226     ASSERT(
1227       target->GetBuffer()->backing_store() ==
1228       source->GetBuffer()->backing_store());
1229     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
1230   } else {  // Non-overlapping typed arrays
1231     return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
1232   }
1233 }
1234
1235
1236 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayMaxSizeInHeap) {
1237   ASSERT_OBJECT_SIZE(FLAG_typed_array_max_size_in_heap);
1238   return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
1239 }
1240
1241
1242 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
1243   HandleScope scope(isolate);
1244   ASSERT(args.length() == 4);
1245   CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
1246   CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
1247   CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
1248   CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
1249
1250   ASSERT(holder->GetInternalFieldCount() ==
1251       v8::ArrayBufferView::kInternalFieldCount);
1252   for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1253     holder->SetInternalField(i, Smi::FromInt(0));
1254   }
1255
1256   holder->set_buffer(*buffer);
1257   ASSERT(byte_offset->IsNumber());
1258   ASSERT(
1259       NumberToSize(isolate, buffer->byte_length()) >=
1260         NumberToSize(isolate, *byte_offset)
1261         + NumberToSize(isolate, *byte_length));
1262   holder->set_byte_offset(*byte_offset);
1263   ASSERT(byte_length->IsNumber());
1264   holder->set_byte_length(*byte_length);
1265
1266   holder->set_weak_next(buffer->weak_first_view());
1267   buffer->set_weak_first_view(*holder);
1268
1269   return isolate->heap()->undefined_value();
1270 }
1271
1272
1273 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
1274   HandleScope scope(isolate);
1275   ASSERT(args.length() == 1);
1276   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1277   return data_view->buffer();
1278 }
1279
1280
1281 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
1282   HandleScope scope(isolate);
1283   ASSERT(args.length() == 1);
1284   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1285   return data_view->byte_offset();
1286 }
1287
1288
1289 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
1290   HandleScope scope(isolate);
1291   ASSERT(args.length() == 1);
1292   CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1293   return data_view->byte_length();
1294 }
1295
1296
1297 inline static bool NeedToFlipBytes(bool is_little_endian) {
1298 #ifdef V8_TARGET_LITTLE_ENDIAN
1299   return !is_little_endian;
1300 #else
1301   return is_little_endian;
1302 #endif
1303 }
1304
1305
1306 template<int n>
1307 inline void CopyBytes(uint8_t* target, uint8_t* source) {
1308   for (int i = 0; i < n; i++) {
1309     *(target++) = *(source++);
1310   }
1311 }
1312
1313
1314 template<int n>
1315 inline void FlipBytes(uint8_t* target, uint8_t* source) {
1316   source = source + (n-1);
1317   for (int i = 0; i < n; i++) {
1318     *(target++) = *(source--);
1319   }
1320 }
1321
1322
1323 template<typename T>
1324 inline static bool DataViewGetValue(
1325     Isolate* isolate,
1326     Handle<JSDataView> data_view,
1327     Handle<Object> byte_offset_obj,
1328     bool is_little_endian,
1329     T* result) {
1330   size_t byte_offset = 0;
1331   if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1332     return false;
1333   }
1334   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1335
1336   size_t data_view_byte_offset =
1337       NumberToSize(isolate, data_view->byte_offset());
1338   size_t data_view_byte_length =
1339       NumberToSize(isolate, data_view->byte_length());
1340   if (byte_offset + sizeof(T) > data_view_byte_length ||
1341       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1342     return false;
1343   }
1344
1345   union Value {
1346     T data;
1347     uint8_t bytes[sizeof(T)];
1348   };
1349
1350   Value value;
1351   size_t buffer_offset = data_view_byte_offset + byte_offset;
1352   ASSERT(
1353       NumberToSize(isolate, buffer->byte_length())
1354       >= buffer_offset + sizeof(T));
1355   uint8_t* source =
1356         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1357   if (NeedToFlipBytes(is_little_endian)) {
1358     FlipBytes<sizeof(T)>(value.bytes, source);
1359   } else {
1360     CopyBytes<sizeof(T)>(value.bytes, source);
1361   }
1362   *result = value.data;
1363   return true;
1364 }
1365
1366
1367 template<typename T>
1368 static bool DataViewSetValue(
1369     Isolate* isolate,
1370     Handle<JSDataView> data_view,
1371     Handle<Object> byte_offset_obj,
1372     bool is_little_endian,
1373     T data) {
1374   size_t byte_offset = 0;
1375   if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1376     return false;
1377   }
1378   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1379
1380   size_t data_view_byte_offset =
1381       NumberToSize(isolate, data_view->byte_offset());
1382   size_t data_view_byte_length =
1383       NumberToSize(isolate, data_view->byte_length());
1384   if (byte_offset + sizeof(T) > data_view_byte_length ||
1385       byte_offset + sizeof(T) < byte_offset)  {  // overflow
1386     return false;
1387   }
1388
1389   union Value {
1390     T data;
1391     uint8_t bytes[sizeof(T)];
1392   };
1393
1394   Value value;
1395   value.data = data;
1396   size_t buffer_offset = data_view_byte_offset + byte_offset;
1397   ASSERT(
1398       NumberToSize(isolate, buffer->byte_length())
1399       >= buffer_offset + sizeof(T));
1400   uint8_t* target =
1401         static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1402   if (NeedToFlipBytes(is_little_endian)) {
1403     FlipBytes<sizeof(T)>(target, value.bytes);
1404   } else {
1405     CopyBytes<sizeof(T)>(target, value.bytes);
1406   }
1407   return true;
1408 }
1409
1410
1411 #define DATA_VIEW_GETTER(TypeName, Type, Converter)                           \
1412   RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) {             \
1413     HandleScope scope(isolate);                                               \
1414     ASSERT(args.length() == 3);                                               \
1415     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1416     CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1417     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2);                         \
1418     Type result;                                                              \
1419     if (DataViewGetValue(                                                     \
1420           isolate, holder, offset, is_little_endian, &result)) {              \
1421       return isolate->heap()->Converter(result);                              \
1422     } else {                                                                  \
1423       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1424           "invalid_data_view_accessor_offset",                                \
1425           HandleVector<Object>(NULL, 0)));                                    \
1426     }                                                                         \
1427   }
1428
1429 DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
1430 DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
1431 DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
1432 DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
1433 DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
1434 DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
1435 DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
1436 DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
1437
1438 #undef DATA_VIEW_GETTER
1439
1440
1441 template <typename T>
1442 static T DataViewConvertValue(double value);
1443
1444
1445 template <>
1446 int8_t DataViewConvertValue<int8_t>(double value) {
1447   return static_cast<int8_t>(DoubleToInt32(value));
1448 }
1449
1450
1451 template <>
1452 int16_t DataViewConvertValue<int16_t>(double value) {
1453   return static_cast<int16_t>(DoubleToInt32(value));
1454 }
1455
1456
1457 template <>
1458 int32_t DataViewConvertValue<int32_t>(double value) {
1459   return DoubleToInt32(value);
1460 }
1461
1462
1463 template <>
1464 uint8_t DataViewConvertValue<uint8_t>(double value) {
1465   return static_cast<uint8_t>(DoubleToUint32(value));
1466 }
1467
1468
1469 template <>
1470 uint16_t DataViewConvertValue<uint16_t>(double value) {
1471   return static_cast<uint16_t>(DoubleToUint32(value));
1472 }
1473
1474
1475 template <>
1476 uint32_t DataViewConvertValue<uint32_t>(double value) {
1477   return DoubleToUint32(value);
1478 }
1479
1480
1481 template <>
1482 float DataViewConvertValue<float>(double value) {
1483   return static_cast<float>(value);
1484 }
1485
1486
1487 template <>
1488 double DataViewConvertValue<double>(double value) {
1489   return value;
1490 }
1491
1492
1493 #define DATA_VIEW_SETTER(TypeName, Type)                                      \
1494   RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) {             \
1495     HandleScope scope(isolate);                                               \
1496     ASSERT(args.length() == 4);                                               \
1497     CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1498     CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1499     CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);                             \
1500     CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3);                         \
1501     Type v = DataViewConvertValue<Type>(value->Number());                     \
1502     if (DataViewSetValue(                                                     \
1503           isolate, holder, offset, is_little_endian, v)) {                    \
1504       return isolate->heap()->undefined_value();                              \
1505     } else {                                                                  \
1506       return isolate->Throw(*isolate->factory()->NewRangeError(               \
1507           "invalid_data_view_accessor_offset",                                \
1508           HandleVector<Object>(NULL, 0)));                                    \
1509     }                                                                         \
1510   }
1511
1512 DATA_VIEW_SETTER(Uint8, uint8_t)
1513 DATA_VIEW_SETTER(Int8, int8_t)
1514 DATA_VIEW_SETTER(Uint16, uint16_t)
1515 DATA_VIEW_SETTER(Int16, int16_t)
1516 DATA_VIEW_SETTER(Uint32, uint32_t)
1517 DATA_VIEW_SETTER(Int32, int32_t)
1518 DATA_VIEW_SETTER(Float32, float)
1519 DATA_VIEW_SETTER(Float64, double)
1520
1521 #undef DATA_VIEW_SETTER
1522
1523
1524 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
1525   HandleScope scope(isolate);
1526   ASSERT(args.length() == 1);
1527   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1528   Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
1529   holder->set_table(*table);
1530   return *holder;
1531 }
1532
1533
1534 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
1535   HandleScope scope(isolate);
1536   ASSERT(args.length() == 2);
1537   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1538   Handle<Object> key(args[1], isolate);
1539   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1540   table = ObjectHashSet::Add(table, key);
1541   holder->set_table(*table);
1542   return isolate->heap()->undefined_value();
1543 }
1544
1545
1546 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
1547   HandleScope scope(isolate);
1548   ASSERT(args.length() == 2);
1549   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1550   Handle<Object> key(args[1], isolate);
1551   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1552   return isolate->heap()->ToBoolean(table->Contains(*key));
1553 }
1554
1555
1556 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
1557   HandleScope scope(isolate);
1558   ASSERT(args.length() == 2);
1559   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1560   Handle<Object> key(args[1], isolate);
1561   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1562   table = ObjectHashSet::Remove(table, key);
1563   holder->set_table(*table);
1564   return isolate->heap()->undefined_value();
1565 }
1566
1567
1568 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
1569   HandleScope scope(isolate);
1570   ASSERT(args.length() == 1);
1571   CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1572   Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1573   return Smi::FromInt(table->NumberOfElements());
1574 }
1575
1576
1577 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
1578   HandleScope scope(isolate);
1579   ASSERT(args.length() == 1);
1580   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1581   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1582   holder->set_table(*table);
1583   return *holder;
1584 }
1585
1586
1587 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
1588   HandleScope scope(isolate);
1589   ASSERT(args.length() == 2);
1590   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1591   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1592   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1593   Handle<Object> lookup(table->Lookup(*key), isolate);
1594   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1595 }
1596
1597
1598 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
1599   HandleScope scope(isolate);
1600   ASSERT(args.length() == 2);
1601   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1602   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1603   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1604   Handle<Object> lookup(table->Lookup(*key), isolate);
1605   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1606 }
1607
1608
1609 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
1610   HandleScope scope(isolate);
1611   ASSERT(args.length() == 2);
1612   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1613   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1614   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1615   Handle<Object> lookup(table->Lookup(*key), isolate);
1616   Handle<ObjectHashTable> new_table =
1617       ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
1618   holder->set_table(*new_table);
1619   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1620 }
1621
1622
1623 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
1624   HandleScope scope(isolate);
1625   ASSERT(args.length() == 3);
1626   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1627   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1628   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1629   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1630   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1631   holder->set_table(*new_table);
1632   return isolate->heap()->undefined_value();
1633 }
1634
1635
1636 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
1637   HandleScope scope(isolate);
1638   ASSERT(args.length() == 1);
1639   CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1640   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1641   return Smi::FromInt(table->NumberOfElements());
1642 }
1643
1644
1645 static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
1646     Handle<JSWeakCollection> weak_collection) {
1647   ASSERT(weak_collection->map()->inobject_properties() == 0);
1648   Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1649   weak_collection->set_table(*table);
1650   weak_collection->set_next(Smi::FromInt(0));
1651   return *weak_collection;
1652 }
1653
1654
1655 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
1656   HandleScope scope(isolate);
1657   ASSERT(args.length() == 1);
1658   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1659   return WeakCollectionInitialize(isolate, weak_collection);
1660 }
1661
1662
1663 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
1664   HandleScope scope(isolate);
1665   ASSERT(args.length() == 2);
1666   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1667   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1668   Handle<ObjectHashTable> table(
1669       ObjectHashTable::cast(weak_collection->table()));
1670   Handle<Object> lookup(table->Lookup(*key), isolate);
1671   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1672 }
1673
1674
1675 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
1676   HandleScope scope(isolate);
1677   ASSERT(args.length() == 2);
1678   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1679   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1680   Handle<ObjectHashTable> table(
1681       ObjectHashTable::cast(weak_collection->table()));
1682   Handle<Object> lookup(table->Lookup(*key), isolate);
1683   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1684 }
1685
1686
1687 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
1688   HandleScope scope(isolate);
1689   ASSERT(args.length() == 2);
1690   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1691   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1692   Handle<ObjectHashTable> table(ObjectHashTable::cast(
1693       weak_collection->table()));
1694   Handle<Object> lookup(table->Lookup(*key), isolate);
1695   Handle<ObjectHashTable> new_table =
1696       ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
1697   weak_collection->set_table(*new_table);
1698   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1699 }
1700
1701
1702 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
1703   HandleScope scope(isolate);
1704   ASSERT(args.length() == 3);
1705   CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1706   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1707   Handle<Object> value(args[2], isolate);
1708   Handle<ObjectHashTable> table(
1709       ObjectHashTable::cast(weak_collection->table()));
1710   Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1711   weak_collection->set_table(*new_table);
1712   return isolate->heap()->undefined_value();
1713 }
1714
1715
1716 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
1717   SealHandleScope shs(isolate);
1718   ASSERT(args.length() == 1);
1719   Object* obj = args[0];
1720   if (!obj->IsJSObject()) return isolate->heap()->null_value();
1721   return JSObject::cast(obj)->class_name();
1722 }
1723
1724
1725 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
1726   HandleScope scope(isolate);
1727   ASSERT(args.length() == 1);
1728   CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
1729   // We don't expect access checks to be needed on JSProxy objects.
1730   ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1731   do {
1732     if (obj->IsAccessCheckNeeded() &&
1733         !isolate->MayNamedAccessWrapper(Handle<JSObject>::cast(obj),
1734                                         isolate->factory()->proto_string(),
1735                                         v8::ACCESS_GET)) {
1736       isolate->ReportFailedAccessCheckWrapper(Handle<JSObject>::cast(obj),
1737                                               v8::ACCESS_GET);
1738       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1739       return isolate->heap()->undefined_value();
1740     }
1741     obj = handle(obj->GetPrototype(isolate), isolate);
1742   } while (obj->IsJSObject() &&
1743            JSObject::cast(*obj)->map()->is_hidden_prototype());
1744   return *obj;
1745 }
1746
1747
1748 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
1749                                                        Object* receiver) {
1750   Object* current = receiver->GetPrototype(isolate);
1751   while (current->IsJSObject() &&
1752          JSObject::cast(current)->map()->is_hidden_prototype()) {
1753     current = current->GetPrototype(isolate);
1754   }
1755   return current;
1756 }
1757
1758
1759 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
1760   HandleScope scope(isolate);
1761   ASSERT(args.length() == 2);
1762   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1763   CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1764   if (obj->IsAccessCheckNeeded() &&
1765       !isolate->MayNamedAccessWrapper(obj,
1766                                       isolate->factory()->proto_string(),
1767                                       v8::ACCESS_SET)) {
1768     isolate->ReportFailedAccessCheckWrapper(obj, v8::ACCESS_SET);
1769     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1770     return isolate->heap()->undefined_value();
1771   }
1772   if (obj->map()->is_observed()) {
1773     Handle<Object> old_value(
1774         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1775
1776     Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1777     RETURN_IF_EMPTY_HANDLE(isolate, result);
1778
1779     Handle<Object> new_value(
1780         GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1781     if (!new_value->SameValue(*old_value)) {
1782       JSObject::EnqueueChangeRecord(obj, "setPrototype",
1783                                     isolate->factory()->proto_string(),
1784                                     old_value);
1785     }
1786     return *result;
1787   }
1788   Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1789   RETURN_IF_EMPTY_HANDLE(isolate, result);
1790   return *result;
1791 }
1792
1793
1794 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
1795   SealHandleScope shs(isolate);
1796   ASSERT(args.length() == 2);
1797   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1798   Object* O = args[0];
1799   Object* V = args[1];
1800   while (true) {
1801     Object* prototype = V->GetPrototype(isolate);
1802     if (prototype->IsNull()) return isolate->heap()->false_value();
1803     if (O == prototype) return isolate->heap()->true_value();
1804     V = prototype;
1805   }
1806 }
1807
1808
1809 static bool CheckAccessException(Object* callback,
1810                                  v8::AccessType access_type) {
1811   DisallowHeapAllocation no_gc;
1812   if (callback->IsAccessorInfo()) {
1813     AccessorInfo* info = AccessorInfo::cast(callback);
1814     return
1815         (access_type == v8::ACCESS_HAS &&
1816            (info->all_can_read() || info->all_can_write())) ||
1817         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1818         (access_type == v8::ACCESS_SET && info->all_can_write());
1819   }
1820   if (callback->IsAccessorPair()) {
1821     AccessorPair* info = AccessorPair::cast(callback);
1822     return
1823         (access_type == v8::ACCESS_HAS &&
1824            (info->all_can_read() || info->all_can_write())) ||
1825         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1826         (access_type == v8::ACCESS_SET && info->all_can_write());
1827   }
1828   return false;
1829 }
1830
1831
1832 template<class Key>
1833 static bool CheckGenericAccess(
1834     Handle<JSObject> receiver,
1835     Handle<JSObject> holder,
1836     Key key,
1837     v8::AccessType access_type,
1838     bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) {
1839   Isolate* isolate = receiver->GetIsolate();
1840   for (Handle<JSObject> current = receiver;
1841        true;
1842        current = handle(JSObject::cast(current->GetPrototype()), isolate)) {
1843     if (current->IsAccessCheckNeeded() &&
1844         !(isolate->*mayAccess)(current, key, access_type)) {
1845       return false;
1846     }
1847     if (current.is_identical_to(holder)) break;
1848   }
1849   return true;
1850 }
1851
1852
1853 enum AccessCheckResult {
1854   ACCESS_FORBIDDEN,
1855   ACCESS_ALLOWED,
1856   ACCESS_ABSENT
1857 };
1858
1859
1860 static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
1861                                              Handle<Name> name,
1862                                              v8::AccessType access_type) {
1863   uint32_t index;
1864   if (name->AsArrayIndex(&index)) {
1865     // TODO(1095): we should traverse hidden prototype hierachy as well.
1866     if (CheckGenericAccess(
1867             obj, obj, index, access_type, &Isolate::MayIndexedAccessWrapper)) {
1868       return ACCESS_ALLOWED;
1869     }
1870
1871     obj->GetIsolate()->ReportFailedAccessCheckWrapper(obj, access_type);
1872     return ACCESS_FORBIDDEN;
1873   }
1874
1875   Isolate* isolate = obj->GetIsolate();
1876   LookupResult lookup(isolate);
1877   obj->LocalLookup(*name, &lookup, true);
1878
1879   if (!lookup.IsProperty()) return ACCESS_ABSENT;
1880   Handle<JSObject> holder(lookup.holder(), isolate);
1881   if (CheckGenericAccess<Handle<Object> >(
1882           obj, holder, name, access_type, &Isolate::MayNamedAccessWrapper)) {
1883     return ACCESS_ALLOWED;
1884   }
1885
1886   // Access check callback denied the access, but some properties
1887   // can have a special permissions which override callbacks descision
1888   // (currently see v8::AccessControl).
1889   // API callbacks can have per callback access exceptions.
1890   switch (lookup.type()) {
1891     case CALLBACKS:
1892       if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1893         return ACCESS_ALLOWED;
1894       }
1895       break;
1896     case INTERCEPTOR:
1897       // If the object has an interceptor, try real named properties.
1898       // Overwrite the result to fetch the correct property later.
1899       holder->LookupRealNamedProperty(*name, &lookup);
1900       if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1901         if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1902           return ACCESS_ALLOWED;
1903         }
1904       }
1905       break;
1906     default:
1907       break;
1908   }
1909
1910   isolate->ReportFailedAccessCheckWrapper(obj, access_type);
1911   return ACCESS_FORBIDDEN;
1912 }
1913
1914
1915 // Enumerator used as indices into the array returned from GetOwnProperty
1916 enum PropertyDescriptorIndices {
1917   IS_ACCESSOR_INDEX,
1918   VALUE_INDEX,
1919   GETTER_INDEX,
1920   SETTER_INDEX,
1921   WRITABLE_INDEX,
1922   ENUMERABLE_INDEX,
1923   CONFIGURABLE_INDEX,
1924   DESCRIPTOR_SIZE
1925 };
1926
1927
1928 static Handle<Object> GetOwnProperty(Isolate* isolate,
1929                                      Handle<JSObject> obj,
1930                                      Handle<Name> name) {
1931   Heap* heap = isolate->heap();
1932   Factory* factory = isolate->factory();
1933   // Due to some WebKit tests, we want to make sure that we do not log
1934   // more than one access failure here.
1935   AccessCheckResult access_check_result =
1936       CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
1937   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1938   switch (access_check_result) {
1939     case ACCESS_FORBIDDEN: return factory->false_value();
1940     case ACCESS_ALLOWED: break;
1941     case ACCESS_ABSENT: return factory->undefined_value();
1942   }
1943
1944   PropertyAttributes attrs = JSReceiver::GetLocalPropertyAttribute(obj, name);
1945   if (attrs == ABSENT) {
1946     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1947     return factory->undefined_value();
1948   }
1949   ASSERT(!isolate->has_scheduled_exception());
1950   AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
1951   Handle<AccessorPair> accessors(raw_accessors, isolate);
1952   Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1953   elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
1954   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
1955   elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
1956
1957   if (raw_accessors == NULL) {
1958     elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
1959     // GetProperty does access check.
1960     Handle<Object> value = GetProperty(isolate, obj, name);
1961     RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<Object>::null());
1962     elms->set(VALUE_INDEX, *value);
1963   } else {
1964     // Access checks are performed for both accessors separately.
1965     // When they fail, the respective field is not set in the descriptor.
1966     Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
1967     Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
1968
1969     if (!getter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_GET)) {
1970       ASSERT(!isolate->has_scheduled_exception());
1971       elms->set(GETTER_INDEX, *getter);
1972     } else {
1973       RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1974     }
1975
1976     if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) {
1977       ASSERT(!isolate->has_scheduled_exception());
1978       elms->set(SETTER_INDEX, *setter);
1979     } else {
1980       RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1981     }
1982   }
1983
1984   return isolate->factory()->NewJSArrayWithElements(elms);
1985 }
1986
1987
1988 // Returns an array with the property description:
1989 //  if args[1] is not a property on args[0]
1990 //          returns undefined
1991 //  if args[1] is a data property on args[0]
1992 //         [false, value, Writeable, Enumerable, Configurable]
1993 //  if args[1] is an accessor on args[0]
1994 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
1995 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1996   HandleScope scope(isolate);
1997   ASSERT(args.length() == 2);
1998   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1999   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2000   Handle<Object> result = GetOwnProperty(isolate, obj, name);
2001   RETURN_IF_EMPTY_HANDLE(isolate, result);
2002   return *result;
2003 }
2004
2005
2006 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
2007   HandleScope scope(isolate);
2008   ASSERT(args.length() == 1);
2009   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
2010   Handle<Object> result = JSObject::PreventExtensions(obj);
2011   RETURN_IF_EMPTY_HANDLE(isolate, result);
2012   return *result;
2013 }
2014
2015
2016 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
2017   SealHandleScope shs(isolate);
2018   ASSERT(args.length() == 1);
2019   CONVERT_ARG_CHECKED(JSObject, obj, 0);
2020   if (obj->IsJSGlobalProxy()) {
2021     Object* proto = obj->GetPrototype();
2022     if (proto->IsNull()) return isolate->heap()->false_value();
2023     ASSERT(proto->IsJSGlobalObject());
2024     obj = JSObject::cast(proto);
2025   }
2026   return isolate->heap()->ToBoolean(obj->map()->is_extensible());
2027 }
2028
2029
2030 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
2031   HandleScope scope(isolate);
2032   ASSERT(args.length() == 3);
2033   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
2034   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
2035   CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
2036   Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
2037   RETURN_IF_EMPTY_HANDLE(isolate, result);
2038   return *result;
2039 }
2040
2041
2042 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
2043   HandleScope scope(isolate);
2044   ASSERT(args.length() == 1);
2045   CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
2046   return *isolate->factory()->CreateApiFunction(data);
2047 }
2048
2049
2050 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
2051   SealHandleScope shs(isolate);
2052   ASSERT(args.length() == 1);
2053   Object* arg = args[0];
2054   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
2055   return isolate->heap()->ToBoolean(result);
2056 }
2057
2058
2059 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
2060   SealHandleScope shs(isolate);
2061   ASSERT(args.length() == 2);
2062   CONVERT_ARG_CHECKED(HeapObject, templ, 0);
2063   CONVERT_SMI_ARG_CHECKED(index, 1)
2064   int offset = index * kPointerSize + HeapObject::kHeaderSize;
2065   InstanceType type = templ->map()->instance_type();
2066   RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
2067                  type ==  OBJECT_TEMPLATE_INFO_TYPE);
2068   RUNTIME_ASSERT(offset > 0);
2069   if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
2070     RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
2071   } else {
2072     RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
2073   }
2074   return *HeapObject::RawField(templ, offset);
2075 }
2076
2077
2078 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
2079   SealHandleScope shs(isolate);
2080   ASSERT(args.length() == 1);
2081   CONVERT_ARG_CHECKED(HeapObject, object, 0);
2082   Map* old_map = object->map();
2083   bool needs_access_checks = old_map->is_access_check_needed();
2084   if (needs_access_checks) {
2085     // Copy map so it won't interfere constructor's initial map.
2086     Map* new_map;
2087     MaybeObject* maybe_new_map = old_map->Copy();
2088     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2089
2090     new_map->set_is_access_check_needed(false);
2091     object->set_map(new_map);
2092   }
2093   return isolate->heap()->ToBoolean(needs_access_checks);
2094 }
2095
2096
2097 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
2098   SealHandleScope shs(isolate);
2099   ASSERT(args.length() == 1);
2100   CONVERT_ARG_CHECKED(HeapObject, object, 0);
2101   Map* old_map = object->map();
2102   if (!old_map->is_access_check_needed()) {
2103     // Copy map so it won't interfere constructor's initial map.
2104     Map* new_map;
2105     MaybeObject* maybe_new_map = old_map->Copy();
2106     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2107
2108     new_map->set_is_access_check_needed(true);
2109     object->set_map(new_map);
2110   }
2111   return isolate->heap()->undefined_value();
2112 }
2113
2114
2115 // Transform getter or setter into something DefineAccessor can handle.
2116 static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
2117                                                    Handle<Object> component) {
2118   if (component->IsUndefined()) return isolate->factory()->null_value();
2119   Handle<FunctionTemplateInfo> info =
2120       Handle<FunctionTemplateInfo>::cast(component);
2121   return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
2122 }
2123
2124
2125 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
2126   HandleScope scope(isolate);
2127   ASSERT(args.length() == 6);
2128   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2129   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2130   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
2131   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
2132   CONVERT_SMI_ARG_CHECKED(attribute, 4);
2133   CONVERT_SMI_ARG_CHECKED(access_control, 5);
2134   RUNTIME_ASSERT(getter->IsUndefined() || getter->IsFunctionTemplateInfo());
2135   RUNTIME_ASSERT(setter->IsUndefined() || setter->IsFunctionTemplateInfo());
2136   JSObject::DefineAccessor(object,
2137                            name,
2138                            InstantiateAccessorComponent(isolate, getter),
2139                            InstantiateAccessorComponent(isolate, setter),
2140                            static_cast<PropertyAttributes>(attribute),
2141                            static_cast<v8::AccessControl>(access_control));
2142   return isolate->heap()->undefined_value();
2143 }
2144
2145
2146 static Failure* ThrowRedeclarationError(Isolate* isolate,
2147                                         const char* type,
2148                                         Handle<String> name) {
2149   HandleScope scope(isolate);
2150   Handle<Object> type_handle =
2151       isolate->factory()->NewStringFromAscii(CStrVector(type));
2152   Handle<Object> args[2] = { type_handle, name };
2153   Handle<Object> error =
2154       isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
2155   return isolate->Throw(*error);
2156 }
2157
2158
2159 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareGlobals) {
2160   HandleScope scope(isolate);
2161   ASSERT(args.length() == 3);
2162   Handle<GlobalObject> global = Handle<GlobalObject>(
2163       isolate->context()->global_object());
2164
2165   Handle<Context> context = args.at<Context>(0);
2166   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
2167   CONVERT_SMI_ARG_CHECKED(flags, 2);
2168
2169   // Traverse the name/value pairs and set the properties.
2170   int length = pairs->length();
2171   for (int i = 0; i < length; i += 2) {
2172     HandleScope scope(isolate);
2173     Handle<String> name(String::cast(pairs->get(i)));
2174     Handle<Object> value(pairs->get(i + 1), isolate);
2175
2176     // We have to declare a global const property. To capture we only
2177     // assign to it when evaluating the assignment for "const x =
2178     // <expr>" the initial value is the hole.
2179     bool is_var = value->IsUndefined();
2180     bool is_const = value->IsTheHole();
2181     bool is_function = value->IsSharedFunctionInfo();
2182     ASSERT(is_var + is_const + is_function == 1);
2183
2184     if (is_var || is_const) {
2185       // Lookup the property in the global object, and don't set the
2186       // value of the variable if the property is already there.
2187       // Do the lookup locally only, see ES5 erratum.
2188       LookupResult lookup(isolate);
2189       global->LocalLookup(*name, &lookup, true);
2190       if (lookup.IsFound()) {
2191         // We found an existing property. Unless it was an interceptor
2192         // that claims the property is absent, skip this declaration.
2193         if (!lookup.IsInterceptor()) continue;
2194         if (JSReceiver::GetPropertyAttribute(global, name) != ABSENT) continue;
2195         // Fall-through and introduce the absent property by using
2196         // SetProperty.
2197       }
2198     } else if (is_function) {
2199       // Copy the function and update its context. Use it as value.
2200       Handle<SharedFunctionInfo> shared =
2201           Handle<SharedFunctionInfo>::cast(value);
2202       Handle<JSFunction> function =
2203           isolate->factory()->NewFunctionFromSharedFunctionInfo(
2204               shared, context, TENURED);
2205       value = function;
2206     }
2207
2208     LookupResult lookup(isolate);
2209     global->LocalLookup(*name, &lookup, true);
2210
2211     // Compute the property attributes. According to ECMA-262,
2212     // the property must be non-configurable except in eval.
2213     int attr = NONE;
2214     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2215     if (!is_eval) {
2216       attr |= DONT_DELETE;
2217     }
2218     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2219     if (is_const || (is_native && is_function)) {
2220       attr |= READ_ONLY;
2221     }
2222
2223     StrictMode strict_mode = DeclareGlobalsStrictMode::decode(flags);
2224
2225     if (!lookup.IsFound() || is_function) {
2226       // If the local property exists, check that we can reconfigure it
2227       // as required for function declarations.
2228       if (lookup.IsFound() && lookup.IsDontDelete()) {
2229         if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2230             lookup.IsPropertyCallbacks()) {
2231           return ThrowRedeclarationError(isolate, "function", name);
2232         }
2233         // If the existing property is not configurable, keep its attributes.
2234         attr = lookup.GetAttributes();
2235       }
2236       // Define or redefine own property.
2237       RETURN_IF_EMPTY_HANDLE(isolate,
2238           JSObject::SetLocalPropertyIgnoreAttributes(
2239               global, name, value, static_cast<PropertyAttributes>(attr)));
2240     } else {
2241       // Do a [[Put]] on the existing (own) property.
2242       RETURN_IF_EMPTY_HANDLE(isolate,
2243           JSObject::SetProperty(
2244               global, name, value, static_cast<PropertyAttributes>(attr),
2245               strict_mode));
2246     }
2247   }
2248
2249   ASSERT(!isolate->has_pending_exception());
2250   return isolate->heap()->undefined_value();
2251 }
2252
2253
2254 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareContextSlot) {
2255   HandleScope scope(isolate);
2256   ASSERT(args.length() == 4);
2257
2258   // Declarations are always made in a function or native context.  In the
2259   // case of eval code, the context passed is the context of the caller,
2260   // which may be some nested context and not the declaration context.
2261   RUNTIME_ASSERT(args[0]->IsContext());
2262   Handle<Context> context(Context::cast(args[0])->declaration_context());
2263
2264   Handle<String> name(String::cast(args[1]));
2265   PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
2266   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2267   Handle<Object> initial_value(args[3], isolate);
2268
2269   int index;
2270   PropertyAttributes attributes;
2271   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2272   BindingFlags binding_flags;
2273   Handle<Object> holder =
2274       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2275
2276   if (attributes != ABSENT) {
2277     // The name was declared before; check for conflicting re-declarations.
2278     // Note: this is actually inconsistent with what happens for globals (where
2279     // we silently ignore such declarations).
2280     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2281       // Functions are not read-only.
2282       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2283       const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
2284       return ThrowRedeclarationError(isolate, type, name);
2285     }
2286
2287     // Initialize it if necessary.
2288     if (*initial_value != NULL) {
2289       if (index >= 0) {
2290         ASSERT(holder.is_identical_to(context));
2291         if (((attributes & READ_ONLY) == 0) ||
2292             context->get(index)->IsTheHole()) {
2293           context->set(index, *initial_value);
2294         }
2295       } else {
2296         // Slow case: The property is in the context extension object of a
2297         // function context or the global object of a native context.
2298         Handle<JSObject> object = Handle<JSObject>::cast(holder);
2299         RETURN_IF_EMPTY_HANDLE(
2300             isolate,
2301             JSReceiver::SetProperty(object, name, initial_value, mode, SLOPPY));
2302       }
2303     }
2304
2305   } else {
2306     // The property is not in the function context. It needs to be
2307     // "declared" in the function context's extension context or as a
2308     // property of the the global object.
2309     Handle<JSObject> object;
2310     if (context->has_extension()) {
2311       object = Handle<JSObject>(JSObject::cast(context->extension()));
2312     } else {
2313       // Context extension objects are allocated lazily.
2314       ASSERT(context->IsFunctionContext());
2315       object = isolate->factory()->NewJSObject(
2316           isolate->context_extension_function());
2317       context->set_extension(*object);
2318     }
2319     ASSERT(*object != NULL);
2320
2321     // Declare the property by setting it to the initial value if provided,
2322     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2323     // constant declarations).
2324     ASSERT(!JSReceiver::HasLocalProperty(object, name));
2325     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2326     if (*initial_value != NULL) value = initial_value;
2327     // Declaring a const context slot is a conflicting declaration if
2328     // there is a callback with that name in a prototype. It is
2329     // allowed to introduce const variables in
2330     // JSContextExtensionObjects. They are treated specially in
2331     // SetProperty and no setters are invoked for those since they are
2332     // not real JSObjects.
2333     if (initial_value->IsTheHole() &&
2334         !object->IsJSContextExtensionObject()) {
2335       LookupResult lookup(isolate);
2336       object->Lookup(*name, &lookup);
2337       if (lookup.IsPropertyCallbacks()) {
2338         return ThrowRedeclarationError(isolate, "const", name);
2339       }
2340     }
2341     if (object->IsJSGlobalObject()) {
2342       // Define own property on the global object.
2343       RETURN_IF_EMPTY_HANDLE(isolate,
2344          JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
2345     } else {
2346       RETURN_IF_EMPTY_HANDLE(isolate,
2347          JSReceiver::SetProperty(object, name, value, mode, SLOPPY));
2348     }
2349   }
2350
2351   return isolate->heap()->undefined_value();
2352 }
2353
2354
2355 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
2356   HandleScope scope(isolate);
2357   // args[0] == name
2358   // args[1] == language_mode
2359   // args[2] == value (optional)
2360
2361   // Determine if we need to assign to the variable if it already
2362   // exists (based on the number of arguments).
2363   RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
2364   bool assign = args.length() == 3;
2365
2366   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2367   RUNTIME_ASSERT(args[1]->IsSmi());
2368   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
2369
2370   // According to ECMA-262, section 12.2, page 62, the property must
2371   // not be deletable.
2372   PropertyAttributes attributes = DONT_DELETE;
2373
2374   // Lookup the property locally in the global object. If it isn't
2375   // there, there is a property with this name in the prototype chain.
2376   // We follow Safari and Firefox behavior and only set the property
2377   // locally if there is an explicit initialization value that we have
2378   // to assign to the property.
2379   // Note that objects can have hidden prototypes, so we need to traverse
2380   // the whole chain of hidden prototypes to do a 'local' lookup.
2381   LookupResult lookup(isolate);
2382   isolate->context()->global_object()->LocalLookup(*name, &lookup, true);
2383   if (lookup.IsInterceptor()) {
2384     Handle<JSObject> holder(lookup.holder());
2385     PropertyAttributes intercepted =
2386         JSReceiver::GetPropertyAttribute(holder, name);
2387     if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2388       // Found an interceptor that's not read only.
2389       if (assign) {
2390         CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2391         Handle<Object> result = JSObject::SetPropertyForResult(
2392             holder, &lookup, name, value, attributes, strict_mode);
2393         RETURN_IF_EMPTY_HANDLE(isolate, result);
2394         return *result;
2395       } else {
2396         return isolate->heap()->undefined_value();
2397       }
2398     }
2399   }
2400
2401   if (assign) {
2402     CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2403     Handle<GlobalObject> global(isolate->context()->global_object());
2404     Handle<Object> result = JSReceiver::SetProperty(
2405         global, name, value, attributes, strict_mode);
2406     RETURN_IF_EMPTY_HANDLE(isolate, result);
2407     return *result;
2408   }
2409   return isolate->heap()->undefined_value();
2410 }
2411
2412
2413 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InitializeConstGlobal) {
2414   SealHandleScope shs(isolate);
2415   // All constants are declared with an initial value. The name
2416   // of the constant is the first argument and the initial value
2417   // is the second.
2418   RUNTIME_ASSERT(args.length() == 2);
2419   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2420   Handle<Object> value = args.at<Object>(1);
2421
2422   // Get the current global object from top.
2423   GlobalObject* global = isolate->context()->global_object();
2424
2425   // According to ECMA-262, section 12.2, page 62, the property must
2426   // not be deletable. Since it's a const, it must be READ_ONLY too.
2427   PropertyAttributes attributes =
2428       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2429
2430   // Lookup the property locally in the global object. If it isn't
2431   // there, we add the property and take special precautions to always
2432   // add it as a local property even in case of callbacks in the
2433   // prototype chain (this rules out using SetProperty).
2434   // We use SetLocalPropertyIgnoreAttributes instead
2435   LookupResult lookup(isolate);
2436   global->LocalLookup(*name, &lookup);
2437   if (!lookup.IsFound()) {
2438     HandleScope handle_scope(isolate);
2439     Handle<GlobalObject> global(isolate->context()->global_object());
2440     RETURN_IF_EMPTY_HANDLE(
2441         isolate,
2442         JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
2443                                                    attributes));
2444     return *value;
2445   }
2446
2447   if (!lookup.IsReadOnly()) {
2448     // Restore global object from context (in case of GC) and continue
2449     // with setting the value.
2450     HandleScope handle_scope(isolate);
2451     Handle<GlobalObject> global(isolate->context()->global_object());
2452
2453     // BUG 1213575: Handle the case where we have to set a read-only
2454     // property through an interceptor and only do it if it's
2455     // uninitialized, e.g. the hole. Nirk...
2456     // Passing sloppy mode because the property is writable.
2457     RETURN_IF_EMPTY_HANDLE(
2458         isolate,
2459         JSReceiver::SetProperty(global, name, value, attributes, SLOPPY));
2460     return *value;
2461   }
2462
2463   // Set the value, but only if we're assigning the initial value to a
2464   // constant. For now, we determine this by checking if the
2465   // current value is the hole.
2466   // Strict mode handling not needed (const is disallowed in strict mode).
2467   if (lookup.IsField()) {
2468     FixedArray* properties = global->properties();
2469     int index = lookup.GetFieldIndex().field_index();
2470     if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2471       properties->set(index, *value);
2472     }
2473   } else if (lookup.IsNormal()) {
2474     if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2475         !lookup.IsReadOnly()) {
2476       HandleScope scope(isolate);
2477       JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2478     }
2479   } else {
2480     // Ignore re-initialization of constants that have already been
2481     // assigned a constant value.
2482     ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2483   }
2484
2485   // Use the set value as the result of the operation.
2486   return *value;
2487 }
2488
2489
2490 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InitializeConstContextSlot) {
2491   HandleScope scope(isolate);
2492   ASSERT(args.length() == 3);
2493
2494   Handle<Object> value(args[0], isolate);
2495   ASSERT(!value->IsTheHole());
2496
2497   // Initializations are always done in a function or native context.
2498   RUNTIME_ASSERT(args[1]->IsContext());
2499   Handle<Context> context(Context::cast(args[1])->declaration_context());
2500
2501   Handle<String> name(String::cast(args[2]));
2502
2503   int index;
2504   PropertyAttributes attributes;
2505   ContextLookupFlags flags = FOLLOW_CHAINS;
2506   BindingFlags binding_flags;
2507   Handle<Object> holder =
2508       context->Lookup(name, flags, &index, &attributes, &binding_flags);
2509
2510   if (index >= 0) {
2511     ASSERT(holder->IsContext());
2512     // Property was found in a context.  Perform the assignment if we
2513     // found some non-constant or an uninitialized constant.
2514     Handle<Context> context = Handle<Context>::cast(holder);
2515     if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
2516       context->set(index, *value);
2517     }
2518     return *value;
2519   }
2520
2521   // The property could not be found, we introduce it as a property of the
2522   // global object.
2523   if (attributes == ABSENT) {
2524     Handle<JSObject> global = Handle<JSObject>(
2525         isolate->context()->global_object());
2526     // Strict mode not needed (const disallowed in strict mode).
2527     RETURN_IF_EMPTY_HANDLE(
2528         isolate,
2529         JSReceiver::SetProperty(global, name, value, NONE, SLOPPY));
2530     return *value;
2531   }
2532
2533   // The property was present in some function's context extension object,
2534   // as a property on the subject of a with, or as a property of the global
2535   // object.
2536   //
2537   // In most situations, eval-introduced consts should still be present in
2538   // the context extension object.  However, because declaration and
2539   // initialization are separate, the property might have been deleted
2540   // before we reach the initialization point.
2541   //
2542   // Example:
2543   //
2544   //    function f() { eval("delete x; const x;"); }
2545   //
2546   // In that case, the initialization behaves like a normal assignment.
2547   Handle<JSObject> object = Handle<JSObject>::cast(holder);
2548
2549   if (*object == context->extension()) {
2550     // This is the property that was introduced by the const declaration.
2551     // Set it if it hasn't been set before.  NOTE: We cannot use
2552     // GetProperty() to get the current value as it 'unholes' the value.
2553     LookupResult lookup(isolate);
2554     object->LocalLookupRealNamedProperty(*name, &lookup);
2555     ASSERT(lookup.IsFound());  // the property was declared
2556     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
2557
2558     if (lookup.IsField()) {
2559       FixedArray* properties = object->properties();
2560       int index = lookup.GetFieldIndex().field_index();
2561       if (properties->get(index)->IsTheHole()) {
2562         properties->set(index, *value);
2563       }
2564     } else if (lookup.IsNormal()) {
2565       if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2566         JSObject::SetNormalizedProperty(object, &lookup, value);
2567       }
2568     } else {
2569       // We should not reach here. Any real, named property should be
2570       // either a field or a dictionary slot.
2571       UNREACHABLE();
2572     }
2573   } else {
2574     // The property was found on some other object.  Set it if it is not a
2575     // read-only property.
2576     if ((attributes & READ_ONLY) == 0) {
2577       // Strict mode not needed (const disallowed in strict mode).
2578       RETURN_IF_EMPTY_HANDLE(
2579           isolate,
2580           JSReceiver::SetProperty(object, name, value, attributes, SLOPPY));
2581     }
2582   }
2583
2584   return *value;
2585 }
2586
2587
2588 RUNTIME_FUNCTION(MaybeObject*,
2589                  Runtime_OptimizeObjectForAddingMultipleProperties) {
2590   HandleScope scope(isolate);
2591   ASSERT(args.length() == 2);
2592   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2593   CONVERT_SMI_ARG_CHECKED(properties, 1);
2594   if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
2595     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
2596   }
2597   return *object;
2598 }
2599
2600
2601 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_RegExpExec) {
2602   HandleScope scope(isolate);
2603   ASSERT(args.length() == 4);
2604   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2605   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2606   // Due to the way the JS calls are constructed this must be less than the
2607   // length of a string, i.e. it is always a Smi.  We check anyway for security.
2608   CONVERT_SMI_ARG_CHECKED(index, 2);
2609   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2610   RUNTIME_ASSERT(index >= 0);
2611   RUNTIME_ASSERT(index <= subject->length());
2612   isolate->counters()->regexp_entry_runtime()->Increment();
2613   Handle<Object> result = RegExpImpl::Exec(regexp,
2614                                            subject,
2615                                            index,
2616                                            last_match_info);
2617   RETURN_IF_EMPTY_HANDLE(isolate, result);
2618   return *result;
2619 }
2620
2621
2622 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_RegExpConstructResult) {
2623   SealHandleScope shs(isolate);
2624   ASSERT(args.length() == 3);
2625   CONVERT_SMI_ARG_CHECKED(elements_count, 0);
2626   if (elements_count < 0 ||
2627       elements_count > FixedArray::kMaxLength ||
2628       !Smi::IsValid(elements_count)) {
2629     return isolate->ThrowIllegalOperation();
2630   }
2631   Object* new_object;
2632   { MaybeObject* maybe_new_object =
2633         isolate->heap()->AllocateFixedArray(elements_count);
2634     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2635   }
2636   FixedArray* elements = FixedArray::cast(new_object);
2637   { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
2638       JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
2639     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2640   }
2641   {
2642     DisallowHeapAllocation no_gc;
2643     HandleScope scope(isolate);
2644     reinterpret_cast<HeapObject*>(new_object)->
2645         set_map(isolate->native_context()->regexp_result_map());
2646   }
2647   JSArray* array = JSArray::cast(new_object);
2648   array->set_properties(isolate->heap()->empty_fixed_array());
2649   array->set_elements(elements);
2650   array->set_length(Smi::FromInt(elements_count));
2651   // Write in-object properties after the length of the array.
2652   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
2653   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
2654   return array;
2655 }
2656
2657
2658 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
2659   HandleScope scope(isolate);
2660   ASSERT(args.length() == 5);
2661   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2662   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2663   // If source is the empty string we set it to "(?:)" instead as
2664   // suggested by ECMA-262, 5th, section 15.10.4.1.
2665   if (source->length() == 0) source = isolate->factory()->query_colon_string();
2666
2667   CONVERT_ARG_HANDLE_CHECKED(Object, global, 2);
2668   if (!global->IsTrue()) global = isolate->factory()->false_value();
2669
2670   CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3);
2671   if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value();
2672
2673   CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4);
2674   if (!multiline->IsTrue()) multiline = isolate->factory()->false_value();
2675
2676   Map* map = regexp->map();
2677   Object* constructor = map->constructor();
2678   if (constructor->IsJSFunction() &&
2679       JSFunction::cast(constructor)->initial_map() == map) {
2680     // If we still have the original map, set in-object properties directly.
2681     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source);
2682     // Both true and false are immovable immortal objects so no need for write
2683     // barrier.
2684     regexp->InObjectPropertyAtPut(
2685         JSRegExp::kGlobalFieldIndex, *global, SKIP_WRITE_BARRIER);
2686     regexp->InObjectPropertyAtPut(
2687         JSRegExp::kIgnoreCaseFieldIndex, *ignoreCase, SKIP_WRITE_BARRIER);
2688     regexp->InObjectPropertyAtPut(
2689         JSRegExp::kMultilineFieldIndex, *multiline, SKIP_WRITE_BARRIER);
2690     regexp->InObjectPropertyAtPut(
2691         JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
2692     return *regexp;
2693   }
2694
2695   // Map has changed, so use generic, but slower, method.
2696   PropertyAttributes final =
2697       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2698   PropertyAttributes writable =
2699       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2700   Handle<Object> zero(Smi::FromInt(0), isolate);
2701   Factory* factory = isolate->factory();
2702   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2703       regexp, factory->source_string(), source, final));
2704   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2705       regexp, factory->global_string(), global, final));
2706   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2707       regexp, factory->ignore_case_string(), ignoreCase, final));
2708   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2709       regexp, factory->multiline_string(), multiline, final));
2710   CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2711       regexp, factory->last_index_string(), zero, writable));
2712   return *regexp;
2713 }
2714
2715
2716 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
2717   HandleScope scope(isolate);
2718   ASSERT(args.length() == 1);
2719   CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2720   // This is necessary to enable fast checks for absence of elements
2721   // on Array.prototype and below.
2722   prototype->set_elements(isolate->heap()->empty_fixed_array());
2723   return Smi::FromInt(0);
2724 }
2725
2726
2727 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
2728                                          Handle<JSObject> holder,
2729                                          const char* name,
2730                                          Builtins::Name builtin_name) {
2731   Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2732   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2733   Handle<JSFunction> optimized =
2734       isolate->factory()->NewFunction(key,
2735                                       JS_OBJECT_TYPE,
2736                                       JSObject::kHeaderSize,
2737                                       code,
2738                                       false);
2739   optimized->shared()->DontAdaptArguments();
2740   JSReceiver::SetProperty(holder, key, optimized, NONE, STRICT);
2741   return optimized;
2742 }
2743
2744
2745 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
2746   HandleScope scope(isolate);
2747   ASSERT(args.length() == 1);
2748   CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
2749
2750   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2751   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2752   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2753   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2754   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2755   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2756   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2757
2758   return *holder;
2759 }
2760
2761
2762 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsSloppyModeFunction) {
2763   SealHandleScope shs(isolate);
2764   ASSERT(args.length() == 1);
2765   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2766   if (!callable->IsJSFunction()) {
2767     HandleScope scope(isolate);
2768     bool threw = false;
2769     Handle<Object> delegate = Execution::TryGetFunctionDelegate(
2770         isolate, Handle<JSReceiver>(callable), &threw);
2771     if (threw) return Failure::Exception();
2772     callable = JSFunction::cast(*delegate);
2773   }
2774   JSFunction* function = JSFunction::cast(callable);
2775   SharedFunctionInfo* shared = function->shared();
2776   return isolate->heap()->ToBoolean(shared->strict_mode() == SLOPPY);
2777 }
2778
2779
2780 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
2781   SealHandleScope shs(isolate);
2782   ASSERT(args.length() == 1);
2783   CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2784
2785   if (!callable->IsJSFunction()) {
2786     HandleScope scope(isolate);
2787     bool threw = false;
2788     Handle<Object> delegate = Execution::TryGetFunctionDelegate(
2789         isolate, Handle<JSReceiver>(callable), &threw);
2790     if (threw) return Failure::Exception();
2791     callable = JSFunction::cast(*delegate);
2792   }
2793   JSFunction* function = JSFunction::cast(callable);
2794
2795   SharedFunctionInfo* shared = function->shared();
2796   if (shared->native() || shared->strict_mode() == STRICT) {
2797     return isolate->heap()->undefined_value();
2798   }
2799   // Returns undefined for strict or native functions, or
2800   // the associated global receiver for "normal" functions.
2801
2802   Context* native_context =
2803       function->context()->global_object()->native_context();
2804   return native_context->global_object()->global_receiver();
2805 }
2806
2807
2808 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_MaterializeRegExpLiteral) {
2809   HandleScope scope(isolate);
2810   ASSERT(args.length() == 4);
2811   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2812   int index = args.smi_at(1);
2813   Handle<String> pattern = args.at<String>(2);
2814   Handle<String> flags = args.at<String>(3);
2815
2816   // Get the RegExp function from the context in the literals array.
2817   // This is the RegExp function from the context in which the
2818   // function was created.  We do not use the RegExp function from the
2819   // current native context because this might be the RegExp function
2820   // from another context which we should not have access to.
2821   Handle<JSFunction> constructor =
2822       Handle<JSFunction>(
2823           JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2824   // Compute the regular expression literal.
2825   bool has_pending_exception;
2826   Handle<Object> regexp =
2827       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2828                                       &has_pending_exception);
2829   if (has_pending_exception) {
2830     ASSERT(isolate->has_pending_exception());
2831     return Failure::Exception();
2832   }
2833   literals->set(index, *regexp);
2834   return *regexp;
2835 }
2836
2837
2838 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2839   SealHandleScope shs(isolate);
2840   ASSERT(args.length() == 1);
2841
2842   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2843   return f->shared()->name();
2844 }
2845
2846
2847 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2848   SealHandleScope shs(isolate);
2849   ASSERT(args.length() == 2);
2850
2851   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2852   CONVERT_ARG_CHECKED(String, name, 1);
2853   f->shared()->set_name(name);
2854   return isolate->heap()->undefined_value();
2855 }
2856
2857
2858 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2859   SealHandleScope shs(isolate);
2860   ASSERT(args.length() == 1);
2861   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2862   return isolate->heap()->ToBoolean(
2863       f->shared()->name_should_print_as_anonymous());
2864 }
2865
2866
2867 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2868   SealHandleScope shs(isolate);
2869   ASSERT(args.length() == 1);
2870   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2871   f->shared()->set_name_should_print_as_anonymous(true);
2872   return isolate->heap()->undefined_value();
2873 }
2874
2875
2876 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
2877   SealHandleScope shs(isolate);
2878   ASSERT(args.length() == 1);
2879   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2880   return isolate->heap()->ToBoolean(f->shared()->is_generator());
2881 }
2882
2883
2884 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2885   SealHandleScope shs(isolate);
2886   ASSERT(args.length() == 1);
2887
2888   CONVERT_ARG_CHECKED(JSFunction, f, 0);
2889   f->RemovePrototype();
2890
2891   return isolate->heap()->undefined_value();
2892 }
2893
2894
2895 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2896   HandleScope scope(isolate);
2897   ASSERT(args.length() == 1);
2898
2899   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2900   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2901   if (!script->IsScript()) return isolate->heap()->undefined_value();
2902
2903   return *GetScriptWrapper(Handle<Script>::cast(script));
2904 }
2905
2906
2907 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2908   HandleScope scope(isolate);
2909   ASSERT(args.length() == 1);
2910
2911   CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2912   Handle<SharedFunctionInfo> shared(f->shared());
2913   return *shared->GetSourceCode();
2914 }
2915
2916
2917 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2918   SealHandleScope shs(isolate);
2919   ASSERT(args.length() == 1);
2920
2921   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2922   int pos = fun->shared()->start_position();
2923   return Smi::FromInt(pos);
2924 }
2925
2926
2927 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2928   SealHandleScope shs(isolate);
2929   ASSERT(args.length() == 2);
2930
2931   CONVERT_ARG_CHECKED(Code, code, 0);
2932   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2933
2934   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2935
2936   Address pc = code->address() + offset;
2937   return Smi::FromInt(code->SourcePosition(pc));
2938 }
2939
2940
2941 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2942   SealHandleScope shs(isolate);
2943   ASSERT(args.length() == 2);
2944
2945   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2946   CONVERT_ARG_CHECKED(String, name, 1);
2947   fun->SetInstanceClassName(name);
2948   return isolate->heap()->undefined_value();
2949 }
2950
2951
2952 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2953   SealHandleScope shs(isolate);
2954   ASSERT(args.length() == 2);
2955
2956   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2957   CONVERT_SMI_ARG_CHECKED(length, 1);
2958   fun->shared()->set_length(length);
2959   return isolate->heap()->undefined_value();
2960 }
2961
2962
2963 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2964   HandleScope scope(isolate);
2965   ASSERT(args.length() == 2);
2966
2967   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
2968   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
2969   ASSERT(fun->should_have_prototype());
2970   Accessors::FunctionSetPrototype(fun, value);
2971   return args[0];  // return TOS
2972 }
2973
2974
2975 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2976   SealHandleScope shs(isolate);
2977   RUNTIME_ASSERT(args.length() == 1);
2978   CONVERT_ARG_CHECKED(JSFunction, function, 0);
2979
2980   String* name = isolate->heap()->prototype_string();
2981
2982   if (function->HasFastProperties()) {
2983     // Construct a new field descriptor with updated attributes.
2984     DescriptorArray* instance_desc = function->map()->instance_descriptors();
2985
2986     int index = instance_desc->SearchWithCache(name, function->map());
2987     ASSERT(index != DescriptorArray::kNotFound);
2988     PropertyDetails details = instance_desc->GetDetails(index);
2989
2990     CallbacksDescriptor new_desc(name,
2991         instance_desc->GetValue(index),
2992         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
2993
2994     // Create a new map featuring the new field descriptors array.
2995     Map* new_map;
2996     MaybeObject* maybe_map =
2997         function->map()->CopyReplaceDescriptor(
2998             instance_desc, &new_desc, index, OMIT_TRANSITION);
2999     if (!maybe_map->To(&new_map)) return maybe_map;
3000
3001     function->set_map(new_map);
3002   } else {  // Dictionary properties.
3003     // Directly manipulate the property details.
3004     int entry = function->property_dictionary()->FindEntry(name);
3005     ASSERT(entry != NameDictionary::kNotFound);
3006     PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
3007     PropertyDetails new_details(
3008         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
3009         details.type(),
3010         details.dictionary_index());
3011     function->property_dictionary()->DetailsAtPut(entry, new_details);
3012   }
3013   return function;
3014 }
3015
3016
3017 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
3018   SealHandleScope shs(isolate);
3019   ASSERT(args.length() == 1);
3020
3021   CONVERT_ARG_CHECKED(JSFunction, f, 0);
3022   return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
3023 }
3024
3025
3026 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
3027   SealHandleScope shs(isolate);
3028   ASSERT(args.length() == 1);
3029
3030   CONVERT_ARG_CHECKED(JSFunction, f, 0);
3031   return isolate->heap()->ToBoolean(f->IsBuiltin());
3032 }
3033
3034
3035 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
3036   HandleScope scope(isolate);
3037   ASSERT(args.length() == 2);
3038
3039   CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
3040   Handle<Object> code = args.at<Object>(1);
3041
3042   if (code->IsNull()) return *target;
3043   RUNTIME_ASSERT(code->IsJSFunction());
3044   Handle<JSFunction> source = Handle<JSFunction>::cast(code);
3045   Handle<SharedFunctionInfo> target_shared(target->shared());
3046   Handle<SharedFunctionInfo> source_shared(source->shared());
3047
3048   if (!Compiler::EnsureCompiled(source, KEEP_EXCEPTION)) {
3049     return Failure::Exception();
3050   }
3051
3052   // Mark both, the source and the target, as un-flushable because the
3053   // shared unoptimized code makes them impossible to enqueue in a list.
3054   ASSERT(target_shared->code()->gc_metadata() == NULL);
3055   ASSERT(source_shared->code()->gc_metadata() == NULL);
3056   target_shared->set_dont_flush(true);
3057   source_shared->set_dont_flush(true);
3058
3059   // Set the code, scope info, formal parameter count, and the length
3060   // of the target shared function info.
3061   target_shared->ReplaceCode(source_shared->code());
3062   target_shared->set_scope_info(source_shared->scope_info());
3063   target_shared->set_length(source_shared->length());
3064   target_shared->set_formal_parameter_count(
3065       source_shared->formal_parameter_count());
3066   target_shared->set_script(source_shared->script());
3067   target_shared->set_start_position_and_type(
3068       source_shared->start_position_and_type());
3069   target_shared->set_end_position(source_shared->end_position());
3070   bool was_native = target_shared->native();
3071   target_shared->set_compiler_hints(source_shared->compiler_hints());
3072   target_shared->set_native(was_native);
3073
3074   // Set the code of the target function.
3075   target->ReplaceCode(source_shared->code());
3076   ASSERT(target->next_function_link()->IsUndefined());
3077
3078   // Make sure we get a fresh copy of the literal vector to avoid cross
3079   // context contamination.
3080   Handle<Context> context(source->context());
3081   int number_of_literals = source->NumberOfLiterals();
3082   Handle<FixedArray> literals =
3083       isolate->factory()->NewFixedArray(number_of_literals, TENURED);
3084   if (number_of_literals > 0) {
3085     literals->set(JSFunction::kLiteralNativeContextIndex,
3086                   context->native_context());
3087   }
3088   target->set_context(*context);
3089   target->set_literals(*literals);
3090
3091   if (isolate->logger()->is_logging_code_events() ||
3092       isolate->cpu_profiler()->is_profiling()) {
3093     isolate->logger()->LogExistingFunction(
3094         source_shared, Handle<Code>(source_shared->code()));
3095   }
3096
3097   return *target;
3098 }
3099
3100
3101 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
3102   HandleScope scope(isolate);
3103   ASSERT(args.length() == 2);
3104   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
3105   CONVERT_SMI_ARG_CHECKED(num, 1);
3106   RUNTIME_ASSERT(num >= 0);
3107   // If objects constructed from this function exist then changing
3108   // 'estimated_nof_properties' is dangerous since the previous value might
3109   // have been compiled into the fast construct stub. Moreover, the inobject
3110   // slack tracking logic might have adjusted the previous value, so even
3111   // passing the same value is risky.
3112   if (!func->shared()->live_objects_may_exist()) {
3113     func->shared()->set_expected_nof_properties(num);
3114     if (func->has_initial_map()) {
3115       Handle<Map> new_initial_map =
3116           func->GetIsolate()->factory()->CopyMap(
3117               Handle<Map>(func->initial_map()));
3118       new_initial_map->set_unused_property_fields(num);
3119       func->set_initial_map(*new_initial_map);
3120     }
3121   }
3122   return isolate->heap()->undefined_value();
3123 }
3124
3125
3126 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateJSGeneratorObject) {
3127   HandleScope scope(isolate);
3128   ASSERT(args.length() == 0);
3129
3130   JavaScriptFrameIterator it(isolate);
3131   JavaScriptFrame* frame = it.frame();
3132   Handle<JSFunction> function(frame->function());
3133   RUNTIME_ASSERT(function->shared()->is_generator());
3134
3135   Handle<JSGeneratorObject> generator;
3136   if (frame->IsConstructor()) {
3137     generator = handle(JSGeneratorObject::cast(frame->receiver()));
3138   } else {
3139     generator = isolate->factory()->NewJSGeneratorObject(function);
3140   }
3141   generator->set_function(*function);
3142   generator->set_context(Context::cast(frame->context()));
3143   generator->set_receiver(frame->receiver());
3144   generator->set_continuation(0);
3145   generator->set_operand_stack(isolate->heap()->empty_fixed_array());
3146   generator->set_stack_handler_index(-1);
3147
3148   return *generator;
3149 }
3150
3151
3152 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SuspendJSGeneratorObject) {
3153   SealHandleScope shs(isolate);
3154   ASSERT(args.length() == 1);
3155   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3156
3157   JavaScriptFrameIterator stack_iterator(isolate);
3158   JavaScriptFrame* frame = stack_iterator.frame();
3159   RUNTIME_ASSERT(frame->function()->shared()->is_generator());
3160   ASSERT_EQ(frame->function(), generator_object->function());
3161
3162   // The caller should have saved the context and continuation already.
3163   ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
3164   ASSERT_LT(0, generator_object->continuation());
3165
3166   // We expect there to be at least two values on the operand stack: the return
3167   // value of the yield expression, and the argument to this runtime call.
3168   // Neither of those should be saved.
3169   int operands_count = frame->ComputeOperandsCount();
3170   ASSERT_GE(operands_count, 2);
3171   operands_count -= 2;
3172
3173   if (operands_count == 0) {
3174     // Although it's semantically harmless to call this function with an
3175     // operands_count of zero, it is also unnecessary.
3176     ASSERT_EQ(generator_object->operand_stack(),
3177               isolate->heap()->empty_fixed_array());
3178     ASSERT_EQ(generator_object->stack_handler_index(), -1);
3179     // If there are no operands on the stack, there shouldn't be a handler
3180     // active either.
3181     ASSERT(!frame->HasHandler());
3182   } else {
3183     int stack_handler_index = -1;
3184     MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
3185     FixedArray* operand_stack;
3186     if (!alloc->To(&operand_stack)) return alloc;
3187     frame->SaveOperandStack(operand_stack, &stack_handler_index);
3188     generator_object->set_operand_stack(operand_stack);
3189     generator_object->set_stack_handler_index(stack_handler_index);
3190   }
3191
3192   return isolate->heap()->undefined_value();
3193 }
3194
3195
3196 // Note that this function is the slow path for resuming generators.  It is only
3197 // called if the suspended activation had operands on the stack, stack handlers
3198 // needing rewinding, or if the resume should throw an exception.  The fast path
3199 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3200 // inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
3201 // called in any case, as it needs to reconstruct the stack frame and make space
3202 // for arguments and operands.
3203 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ResumeJSGeneratorObject) {
3204   SealHandleScope shs(isolate);
3205   ASSERT(args.length() == 3);
3206   CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3207   CONVERT_ARG_CHECKED(Object, value, 1);
3208   CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3209   JavaScriptFrameIterator stack_iterator(isolate);
3210   JavaScriptFrame* frame = stack_iterator.frame();
3211
3212   ASSERT_EQ(frame->function(), generator_object->function());
3213   ASSERT(frame->function()->is_compiled());
3214
3215   STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
3216   STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
3217
3218   Address pc = generator_object->function()->code()->instruction_start();
3219   int offset = generator_object->continuation();
3220   ASSERT(offset > 0);
3221   frame->set_pc(pc + offset);
3222   if (FLAG_enable_ool_constant_pool) {
3223     frame->set_constant_pool(
3224         generator_object->function()->code()->constant_pool());
3225   }
3226   generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3227
3228   FixedArray* operand_stack = generator_object->operand_stack();
3229   int operands_count = operand_stack->length();
3230   if (operands_count != 0) {
3231     frame->RestoreOperandStack(operand_stack,
3232                                generator_object->stack_handler_index());
3233     generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3234     generator_object->set_stack_handler_index(-1);
3235   }
3236
3237   JSGeneratorObject::ResumeMode resume_mode =
3238       static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3239   switch (resume_mode) {
3240     case JSGeneratorObject::NEXT:
3241       return value;
3242     case JSGeneratorObject::THROW:
3243       return isolate->Throw(value);
3244   }
3245
3246   UNREACHABLE();
3247   return isolate->ThrowIllegalOperation();
3248 }
3249
3250
3251 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowGeneratorStateError) {
3252   HandleScope scope(isolate);
3253   ASSERT(args.length() == 1);
3254   CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
3255   int continuation = generator->continuation();
3256   const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3257       "generator_finished" : "generator_running";
3258   Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3259   Handle<Object> error = isolate->factory()->NewError(message, argv);
3260   return isolate->Throw(*error);
3261 }
3262
3263
3264 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
3265   HandleScope scope(isolate);
3266   ASSERT(args.length() == 1);
3267   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
3268   Handle<Object> result = JSObject::Freeze(object);
3269   RETURN_IF_EMPTY_HANDLE(isolate, result);
3270   return *result;
3271 }
3272
3273
3274 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
3275                                                  Object* char_code) {
3276   if (char_code->IsNumber()) {
3277     return isolate->heap()->LookupSingleCharacterStringFromCode(
3278         NumberToUint32(char_code) & 0xffff);
3279   }
3280   return isolate->heap()->empty_string();
3281 }
3282
3283
3284 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCharCodeAt) {
3285   SealHandleScope shs(isolate);
3286   ASSERT(args.length() == 2);
3287
3288   CONVERT_ARG_CHECKED(String, subject, 0);
3289   CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3290
3291   // Flatten the string.  If someone wants to get a char at an index
3292   // in a cons string, it is likely that more indices will be
3293   // accessed.
3294   Object* flat;
3295   { MaybeObject* maybe_flat = subject->TryFlatten();
3296     if (!maybe_flat->ToObject(&flat)) return maybe_flat;
3297   }
3298   subject = String::cast(flat);
3299
3300   if (i >= static_cast<uint32_t>(subject->length())) {
3301     return isolate->heap()->nan_value();
3302   }
3303
3304   return Smi::FromInt(subject->Get(i));
3305 }
3306
3307
3308 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
3309   SealHandleScope shs(isolate);
3310   ASSERT(args.length() == 1);
3311   return CharFromCode(isolate, args[0]);
3312 }
3313
3314
3315 class FixedArrayBuilder {
3316  public:
3317   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3318       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3319         length_(0),
3320         has_non_smi_elements_(false) {
3321     // Require a non-zero initial size. Ensures that doubling the size to
3322     // extend the array will work.
3323     ASSERT(initial_capacity > 0);
3324   }
3325
3326   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3327       : array_(backing_store),
3328         length_(0),
3329         has_non_smi_elements_(false) {
3330     // Require a non-zero initial size. Ensures that doubling the size to
3331     // extend the array will work.
3332     ASSERT(backing_store->length() > 0);
3333   }
3334
3335   bool HasCapacity(int elements) {
3336     int length = array_->length();
3337     int required_length = length_ + elements;
3338     return (length >= required_length);
3339   }
3340
3341   void EnsureCapacity(int elements) {
3342     int length = array_->length();
3343     int required_length = length_ + elements;
3344     if (length < required_length) {
3345       int new_length = length;
3346       do {
3347         new_length *= 2;
3348       } while (new_length < required_length);
3349       Handle<FixedArray> extended_array =
3350           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3351       array_->CopyTo(0, *extended_array, 0, length_);
3352       array_ = extended_array;
3353     }
3354   }
3355
3356   void Add(Object* value) {
3357     ASSERT(!value->IsSmi());
3358     ASSERT(length_ < capacity());
3359     array_->set(length_, value);
3360     length_++;
3361     has_non_smi_elements_ = true;
3362   }
3363
3364   void Add(Smi* value) {
3365     ASSERT(value->IsSmi());
3366     ASSERT(length_ < capacity());
3367     array_->set(length_, value);
3368     length_++;
3369   }
3370
3371   Handle<FixedArray> array() {
3372     return array_;
3373   }
3374
3375   int length() {
3376     return length_;
3377   }
3378
3379   int capacity() {
3380     return array_->length();
3381   }
3382
3383   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
3384     JSArray::SetContent(target_array, array_);
3385     target_array->set_length(Smi::FromInt(length_));
3386     return target_array;
3387   }
3388
3389
3390  private:
3391   Handle<FixedArray> array_;
3392   int length_;
3393   bool has_non_smi_elements_;
3394 };
3395
3396
3397 // Forward declarations.
3398 const int kStringBuilderConcatHelperLengthBits = 11;
3399 const int kStringBuilderConcatHelperPositionBits = 19;
3400
3401 template <typename schar>
3402 static inline void StringBuilderConcatHelper(String*,
3403                                              schar*,
3404                                              FixedArray*,
3405                                              int);
3406
3407 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
3408     StringBuilderSubstringLength;
3409 typedef BitField<int,
3410                  kStringBuilderConcatHelperLengthBits,
3411                  kStringBuilderConcatHelperPositionBits>
3412     StringBuilderSubstringPosition;
3413
3414
3415 class ReplacementStringBuilder {
3416  public:
3417   ReplacementStringBuilder(Heap* heap,
3418                            Handle<String> subject,
3419                            int estimated_part_count)
3420       : heap_(heap),
3421         array_builder_(heap->isolate(), estimated_part_count),
3422         subject_(subject),
3423         character_count_(0),
3424         is_ascii_(subject->IsOneByteRepresentation()) {
3425     // Require a non-zero initial size. Ensures that doubling the size to
3426     // extend the array will work.
3427     ASSERT(estimated_part_count > 0);
3428   }
3429
3430   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3431                                      int from,
3432                                      int to) {
3433     ASSERT(from >= 0);
3434     int length = to - from;
3435     ASSERT(length > 0);
3436     if (StringBuilderSubstringLength::is_valid(length) &&
3437         StringBuilderSubstringPosition::is_valid(from)) {
3438       int encoded_slice = StringBuilderSubstringLength::encode(length) |
3439           StringBuilderSubstringPosition::encode(from);
3440       builder->Add(Smi::FromInt(encoded_slice));
3441     } else {
3442       // Otherwise encode as two smis.
3443       builder->Add(Smi::FromInt(-length));
3444       builder->Add(Smi::FromInt(from));
3445     }
3446   }
3447
3448
3449   void EnsureCapacity(int elements) {
3450     array_builder_.EnsureCapacity(elements);
3451   }
3452
3453
3454   void AddSubjectSlice(int from, int to) {
3455     AddSubjectSlice(&array_builder_, from, to);
3456     IncrementCharacterCount(to - from);
3457   }
3458
3459
3460   void AddString(Handle<String> string) {
3461     int length = string->length();
3462     ASSERT(length > 0);
3463     AddElement(*string);
3464     if (!string->IsOneByteRepresentation()) {
3465       is_ascii_ = false;
3466     }
3467     IncrementCharacterCount(length);
3468   }
3469
3470
3471   Handle<String> ToString() {
3472     if (array_builder_.length() == 0) {
3473       return heap_->isolate()->factory()->empty_string();
3474     }
3475
3476     Handle<String> joined_string;
3477     if (is_ascii_) {
3478       Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3479       RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
3480       DisallowHeapAllocation no_gc;
3481       uint8_t* char_buffer = seq->GetChars();
3482       StringBuilderConcatHelper(*subject_,
3483                                 char_buffer,
3484                                 *array_builder_.array(),
3485                                 array_builder_.length());
3486       joined_string = Handle<String>::cast(seq);
3487     } else {
3488       // Non-ASCII.
3489       Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3490       RETURN_IF_EMPTY_HANDLE_VALUE(heap_->isolate(), seq, Handle<String>());
3491       DisallowHeapAllocation no_gc;
3492       uc16* char_buffer = seq->GetChars();
3493       StringBuilderConcatHelper(*subject_,
3494                                 char_buffer,
3495                                 *array_builder_.array(),
3496                                 array_builder_.length());
3497       joined_string = Handle<String>::cast(seq);
3498     }
3499     return joined_string;
3500   }
3501
3502
3503   void IncrementCharacterCount(int by) {
3504     if (character_count_ > String::kMaxLength - by) {
3505       STATIC_ASSERT(String::kMaxLength < kMaxInt);
3506       character_count_ = kMaxInt;
3507     } else {
3508       character_count_ += by;
3509     }
3510   }
3511
3512  private:
3513   Handle<SeqOneByteString> NewRawOneByteString(int length) {
3514     return heap_->isolate()->factory()->NewRawOneByteString(length);
3515   }
3516
3517
3518   Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3519     return heap_->isolate()->factory()->NewRawTwoByteString(length);
3520   }
3521
3522
3523   void AddElement(Object* element) {
3524     ASSERT(element->IsSmi() || element->IsString());
3525     ASSERT(array_builder_.capacity() > array_builder_.length());
3526     array_builder_.Add(element);
3527   }
3528
3529   Heap* heap_;
3530   FixedArrayBuilder array_builder_;
3531   Handle<String> subject_;
3532   int character_count_;
3533   bool is_ascii_;
3534 };
3535
3536
3537 class CompiledReplacement {
3538  public:
3539   explicit CompiledReplacement(Zone* zone)
3540       : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3541
3542   // Return whether the replacement is simple.
3543   bool Compile(Handle<String> replacement,
3544                int capture_count,
3545                int subject_length);
3546
3547   // Use Apply only if Compile returned false.
3548   void Apply(ReplacementStringBuilder* builder,
3549              int match_from,
3550              int match_to,
3551              int32_t* match);
3552
3553   // Number of distinct parts of the replacement pattern.
3554   int parts() {
3555     return parts_.length();
3556   }
3557
3558   Zone* zone() const { return zone_; }
3559
3560  private:
3561   enum PartType {
3562     SUBJECT_PREFIX = 1,
3563     SUBJECT_SUFFIX,
3564     SUBJECT_CAPTURE,
3565     REPLACEMENT_SUBSTRING,
3566     REPLACEMENT_STRING,
3567
3568     NUMBER_OF_PART_TYPES
3569   };
3570
3571   struct ReplacementPart {
3572     static inline ReplacementPart SubjectMatch() {
3573       return ReplacementPart(SUBJECT_CAPTURE, 0);
3574     }
3575     static inline ReplacementPart SubjectCapture(int capture_index) {
3576       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3577     }
3578     static inline ReplacementPart SubjectPrefix() {
3579       return ReplacementPart(SUBJECT_PREFIX, 0);
3580     }
3581     static inline ReplacementPart SubjectSuffix(int subject_length) {
3582       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3583     }
3584     static inline ReplacementPart ReplacementString() {
3585       return ReplacementPart(REPLACEMENT_STRING, 0);
3586     }
3587     static inline ReplacementPart ReplacementSubString(int from, int to) {
3588       ASSERT(from >= 0);
3589       ASSERT(to > from);
3590       return ReplacementPart(-from, to);
3591     }
3592
3593     // If tag <= 0 then it is the negation of a start index of a substring of
3594     // the replacement pattern, otherwise it's a value from PartType.
3595     ReplacementPart(int tag, int data)
3596         : tag(tag), data(data) {
3597       // Must be non-positive or a PartType value.
3598       ASSERT(tag < NUMBER_OF_PART_TYPES);
3599     }
3600     // Either a value of PartType or a non-positive number that is
3601     // the negation of an index into the replacement string.
3602     int tag;
3603     // The data value's interpretation depends on the value of tag:
3604     // tag == SUBJECT_PREFIX ||
3605     // tag == SUBJECT_SUFFIX:  data is unused.
3606     // tag == SUBJECT_CAPTURE: data is the number of the capture.
3607     // tag == REPLACEMENT_SUBSTRING ||
3608     // tag == REPLACEMENT_STRING:    data is index into array of substrings
3609     //                               of the replacement string.
3610     // tag <= 0: Temporary representation of the substring of the replacement
3611     //           string ranging over -tag .. data.
3612     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3613     //           substring objects.
3614     int data;
3615   };
3616
3617   template<typename Char>
3618   bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3619                                Vector<Char> characters,
3620                                int capture_count,
3621                                int subject_length,
3622                                Zone* zone) {
3623     int length = characters.length();
3624     int last = 0;
3625     for (int i = 0; i < length; i++) {
3626       Char c = characters[i];
3627       if (c == '$') {
3628         int next_index = i + 1;
3629         if (next_index == length) {  // No next character!
3630           break;
3631         }
3632         Char c2 = characters[next_index];
3633         switch (c2) {
3634         case '$':
3635           if (i > last) {
3636             // There is a substring before. Include the first "$".
3637             parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3638                        zone);
3639             last = next_index + 1;  // Continue after the second "$".
3640           } else {
3641             // Let the next substring start with the second "$".
3642             last = next_index;
3643           }
3644           i = next_index;
3645           break;
3646         case '`':
3647           if (i > last) {
3648             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3649           }
3650           parts->Add(ReplacementPart::SubjectPrefix(), zone);
3651           i = next_index;
3652           last = i + 1;
3653           break;
3654         case '\'':
3655           if (i > last) {
3656             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3657           }
3658           parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3659           i = next_index;
3660           last = i + 1;
3661           break;
3662         case '&':
3663           if (i > last) {
3664             parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3665           }
3666           parts->Add(ReplacementPart::SubjectMatch(), zone);
3667           i = next_index;
3668           last = i + 1;
3669           break;
3670         case '0':
3671         case '1':
3672         case '2':
3673         case '3':
3674         case '4':
3675         case '5':
3676         case '6':
3677         case '7':
3678         case '8':
3679         case '9': {
3680           int capture_ref = c2 - '0';
3681           if (capture_ref > capture_count) {
3682             i = next_index;
3683             continue;
3684           }
3685           int second_digit_index = next_index + 1;
3686           if (second_digit_index < length) {
3687             // Peek ahead to see if we have two digits.
3688             Char c3 = characters[second_digit_index];
3689             if ('0' <= c3 && c3 <= '9') {  // Double digits.
3690               int double_digit_ref = capture_ref * 10 + c3 - '0';
3691               if (double_digit_ref <= capture_count) {
3692                 next_index = second_digit_index;
3693                 capture_ref = double_digit_ref;
3694               }
3695             }
3696           }
3697           if (capture_ref > 0) {
3698             if (i > last) {
3699               parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3700             }
3701             ASSERT(capture_ref <= capture_count);
3702             parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3703             last = next_index + 1;
3704           }
3705           i = next_index;
3706           break;
3707         }
3708         default:
3709           i = next_index;
3710           break;
3711         }
3712       }
3713     }
3714     if (length > last) {
3715       if (last == 0) {
3716         // Replacement is simple.  Do not use Apply to do the replacement.
3717         return true;
3718       } else {
3719         parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3720       }
3721     }
3722     return false;
3723   }
3724
3725   ZoneList<ReplacementPart> parts_;
3726   ZoneList<Handle<String> > replacement_substrings_;
3727   Zone* zone_;
3728 };
3729
3730
3731 bool CompiledReplacement::Compile(Handle<String> replacement,
3732                                   int capture_count,
3733                                   int subject_length) {
3734   {
3735     DisallowHeapAllocation no_gc;
3736     String::FlatContent content = replacement->GetFlatContent();
3737     ASSERT(content.IsFlat());
3738     bool simple = false;
3739     if (content.IsAscii()) {
3740       simple = ParseReplacementPattern(&parts_,
3741                                        content.ToOneByteVector(),
3742                                        capture_count,
3743                                        subject_length,
3744                                        zone());
3745     } else {
3746       ASSERT(content.IsTwoByte());
3747       simple = ParseReplacementPattern(&parts_,
3748                                        content.ToUC16Vector(),
3749                                        capture_count,
3750                                        subject_length,
3751                                        zone());
3752     }
3753     if (simple) return true;
3754   }
3755
3756   Isolate* isolate = replacement->GetIsolate();
3757   // Find substrings of replacement string and create them as String objects.
3758   int substring_index = 0;
3759   for (int i = 0, n = parts_.length(); i < n; i++) {
3760     int tag = parts_[i].tag;
3761     if (tag <= 0) {  // A replacement string slice.
3762       int from = -tag;
3763       int to = parts_[i].data;
3764       replacement_substrings_.Add(
3765           isolate->factory()->NewSubString(replacement, from, to), zone());
3766       parts_[i].tag = REPLACEMENT_SUBSTRING;
3767       parts_[i].data = substring_index;
3768       substring_index++;
3769     } else if (tag == REPLACEMENT_STRING) {
3770       replacement_substrings_.Add(replacement, zone());
3771       parts_[i].data = substring_index;
3772       substring_index++;
3773     }
3774   }
3775   return false;
3776 }
3777
3778
3779 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
3780                                 int match_from,
3781                                 int match_to,
3782                                 int32_t* match) {
3783   ASSERT_LT(0, parts_.length());
3784   for (int i = 0, n = parts_.length(); i < n; i++) {
3785     ReplacementPart part = parts_[i];
3786     switch (part.tag) {
3787       case SUBJECT_PREFIX:
3788         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3789         break;
3790       case SUBJECT_SUFFIX: {
3791         int subject_length = part.data;
3792         if (match_to < subject_length) {
3793           builder->AddSubjectSlice(match_to, subject_length);
3794         }
3795         break;
3796       }
3797       case SUBJECT_CAPTURE: {
3798         int capture = part.data;
3799         int from = match[capture * 2];
3800         int to = match[capture * 2 + 1];
3801         if (from >= 0 && to > from) {
3802           builder->AddSubjectSlice(from, to);
3803         }
3804         break;
3805       }
3806       case REPLACEMENT_SUBSTRING:
3807       case REPLACEMENT_STRING:
3808         builder->AddString(replacement_substrings_[part.data]);
3809         break;
3810       default:
3811         UNREACHABLE();
3812     }
3813   }
3814 }
3815
3816
3817 void FindAsciiStringIndices(Vector<const uint8_t> subject,
3818                             char pattern,
3819                             ZoneList<int>* indices,
3820                             unsigned int limit,
3821                             Zone* zone) {
3822   ASSERT(limit > 0);
3823   // Collect indices of pattern in subject using memchr.
3824   // Stop after finding at most limit values.
3825   const uint8_t* subject_start = subject.start();
3826   const uint8_t* subject_end = subject_start + subject.length();
3827   const uint8_t* pos = subject_start;
3828   while (limit > 0) {
3829     pos = reinterpret_cast<const uint8_t*>(
3830         memchr(pos, pattern, subject_end - pos));
3831     if (pos == NULL) return;
3832     indices->Add(static_cast<int>(pos - subject_start), zone);
3833     pos++;
3834     limit--;
3835   }
3836 }
3837
3838
3839 void FindTwoByteStringIndices(const Vector<const uc16> subject,
3840                               uc16 pattern,
3841                               ZoneList<int>* indices,
3842                               unsigned int limit,
3843                               Zone* zone) {
3844   ASSERT(limit > 0);
3845   const uc16* subject_start = subject.start();
3846   const uc16* subject_end = subject_start + subject.length();
3847   for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3848     if (*pos == pattern) {
3849       indices->Add(static_cast<int>(pos - subject_start), zone);
3850       limit--;
3851     }
3852   }
3853 }
3854
3855
3856 template <typename SubjectChar, typename PatternChar>
3857 void FindStringIndices(Isolate* isolate,
3858                        Vector<const SubjectChar> subject,
3859                        Vector<const PatternChar> pattern,
3860                        ZoneList<int>* indices,
3861                        unsigned int limit,
3862                        Zone* zone) {
3863   ASSERT(limit > 0);
3864   // Collect indices of pattern in subject.
3865   // Stop after finding at most limit values.
3866   int pattern_length = pattern.length();
3867   int index = 0;
3868   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3869   while (limit > 0) {
3870     index = search.Search(subject, index);
3871     if (index < 0) return;
3872     indices->Add(index, zone);
3873     index += pattern_length;
3874     limit--;
3875   }
3876 }
3877
3878
3879 void FindStringIndicesDispatch(Isolate* isolate,
3880                                String* subject,
3881                                String* pattern,
3882                                ZoneList<int>* indices,
3883                                unsigned int limit,
3884                                Zone* zone) {
3885   {
3886     DisallowHeapAllocation no_gc;
3887     String::FlatContent subject_content = subject->GetFlatContent();
3888     String::FlatContent pattern_content = pattern->GetFlatContent();
3889     ASSERT(subject_content.IsFlat());
3890     ASSERT(pattern_content.IsFlat());
3891     if (subject_content.IsAscii()) {
3892       Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3893       if (pattern_content.IsAscii()) {
3894         Vector<const uint8_t> pattern_vector =
3895             pattern_content.ToOneByteVector();
3896         if (pattern_vector.length() == 1) {
3897           FindAsciiStringIndices(subject_vector,
3898                                  pattern_vector[0],
3899                                  indices,
3900                                  limit,
3901                                  zone);
3902         } else {
3903           FindStringIndices(isolate,
3904                             subject_vector,
3905                             pattern_vector,
3906                             indices,
3907                             limit,
3908                             zone);
3909         }
3910       } else {
3911         FindStringIndices(isolate,
3912                           subject_vector,
3913                           pattern_content.ToUC16Vector(),
3914                           indices,
3915                           limit,
3916                           zone);
3917       }
3918     } else {
3919       Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3920       if (pattern_content.IsAscii()) {
3921         Vector<const uint8_t> pattern_vector =
3922             pattern_content.ToOneByteVector();
3923         if (pattern_vector.length() == 1) {
3924           FindTwoByteStringIndices(subject_vector,
3925                                    pattern_vector[0],
3926                                    indices,
3927                                    limit,
3928                                    zone);
3929         } else {
3930           FindStringIndices(isolate,
3931                             subject_vector,
3932                             pattern_vector,
3933                             indices,
3934                             limit,
3935                             zone);
3936         }
3937       } else {
3938         Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3939         if (pattern_vector.length() == 1) {
3940           FindTwoByteStringIndices(subject_vector,
3941                                    pattern_vector[0],
3942                                    indices,
3943                                    limit,
3944                                    zone);
3945         } else {
3946           FindStringIndices(isolate,
3947                             subject_vector,
3948                             pattern_vector,
3949                             indices,
3950                             limit,
3951                             zone);
3952         }
3953       }
3954     }
3955   }
3956 }
3957
3958
3959 template<typename ResultSeqString>
3960 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
3961     Isolate* isolate,
3962     Handle<String> subject,
3963     Handle<JSRegExp> pattern_regexp,
3964     Handle<String> replacement,
3965     Handle<JSArray> last_match_info) {
3966   ASSERT(subject->IsFlat());
3967   ASSERT(replacement->IsFlat());
3968
3969   ZoneScope zone_scope(isolate->runtime_zone());
3970   ZoneList<int> indices(8, zone_scope.zone());
3971   ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3972   String* pattern =
3973       String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
3974   int subject_len = subject->length();
3975   int pattern_len = pattern->length();
3976   int replacement_len = replacement->length();
3977
3978   FindStringIndicesDispatch(
3979       isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3980
3981   int matches = indices.length();
3982   if (matches == 0) return *subject;
3983
3984   // Detect integer overflow.
3985   int64_t result_len_64 =
3986       (static_cast<int64_t>(replacement_len) -
3987        static_cast<int64_t>(pattern_len)) *
3988       static_cast<int64_t>(matches) +
3989       static_cast<int64_t>(subject_len);
3990   int result_len;
3991   if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
3992     STATIC_ASSERT(String::kMaxLength < kMaxInt);
3993     result_len = kMaxInt;  // Provoke exception.
3994   } else {
3995     result_len = static_cast<int>(result_len_64);
3996   }
3997
3998   int subject_pos = 0;
3999   int result_pos = 0;
4000
4001   Handle<String> result_seq;
4002   if (ResultSeqString::kHasAsciiEncoding) {
4003     result_seq = isolate->factory()->NewRawOneByteString(result_len);
4004   } else {
4005     result_seq = isolate->factory()->NewRawTwoByteString(result_len);
4006   }
4007   RETURN_IF_EMPTY_HANDLE(isolate, result_seq);
4008   Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(result_seq);
4009
4010   for (int i = 0; i < matches; i++) {
4011     // Copy non-matched subject content.
4012     if (subject_pos < indices.at(i)) {
4013       String::WriteToFlat(*subject,
4014                           result->GetChars() + result_pos,
4015                           subject_pos,
4016                           indices.at(i));
4017       result_pos += indices.at(i) - subject_pos;
4018     }
4019
4020     // Replace match.
4021     if (replacement_len > 0) {
4022       String::WriteToFlat(*replacement,
4023                           result->GetChars() + result_pos,
4024                           0,
4025                           replacement_len);
4026       result_pos += replacement_len;
4027     }
4028
4029     subject_pos = indices.at(i) + pattern_len;
4030   }
4031   // Add remaining subject content at the end.
4032   if (subject_pos < subject_len) {
4033     String::WriteToFlat(*subject,
4034                         result->GetChars() + result_pos,
4035                         subject_pos,
4036                         subject_len);
4037   }
4038
4039   int32_t match_indices[] = { indices.at(matches - 1),
4040                               indices.at(matches - 1) + pattern_len };
4041   RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
4042
4043   return *result;
4044 }
4045
4046
4047 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
4048     Isolate* isolate,
4049     Handle<String> subject,
4050     Handle<JSRegExp> regexp,
4051     Handle<String> replacement,
4052     Handle<JSArray> last_match_info) {
4053   ASSERT(subject->IsFlat());
4054   ASSERT(replacement->IsFlat());
4055
4056   int capture_count = regexp->CaptureCount();
4057   int subject_length = subject->length();
4058
4059   // CompiledReplacement uses zone allocation.
4060   ZoneScope zone_scope(isolate->runtime_zone());
4061   CompiledReplacement compiled_replacement(zone_scope.zone());
4062   bool simple_replace = compiled_replacement.Compile(replacement,
4063                                                      capture_count,
4064                                                      subject_length);
4065
4066   // Shortcut for simple non-regexp global replacements
4067   if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
4068     if (subject->HasOnlyOneByteChars() &&
4069         replacement->HasOnlyOneByteChars()) {
4070       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4071           isolate, subject, regexp, replacement, last_match_info);
4072     } else {
4073       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4074           isolate, subject, regexp, replacement, last_match_info);
4075     }
4076   }
4077
4078   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4079   if (global_cache.HasException()) return Failure::Exception();
4080
4081   int32_t* current_match = global_cache.FetchNext();
4082   if (current_match == NULL) {
4083     if (global_cache.HasException()) return Failure::Exception();
4084     return *subject;
4085   }
4086
4087   // Guessing the number of parts that the final result string is built
4088   // from. Global regexps can match any number of times, so we guess
4089   // conservatively.
4090   int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
4091   ReplacementStringBuilder builder(isolate->heap(),
4092                                    subject,
4093                                    expected_parts);
4094
4095   // Number of parts added by compiled replacement plus preceeding
4096   // string and possibly suffix after last match.  It is possible for
4097   // all components to use two elements when encoded as two smis.
4098   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
4099
4100   int prev = 0;
4101
4102   do {
4103     builder.EnsureCapacity(parts_added_per_loop);
4104
4105     int start = current_match[0];
4106     int end = current_match[1];
4107
4108     if (prev < start) {
4109       builder.AddSubjectSlice(prev, start);
4110     }
4111
4112     if (simple_replace) {
4113       builder.AddString(replacement);
4114     } else {
4115       compiled_replacement.Apply(&builder,
4116                                  start,
4117                                  end,
4118                                  current_match);
4119     }
4120     prev = end;
4121
4122     current_match = global_cache.FetchNext();
4123   } while (current_match != NULL);
4124
4125   if (global_cache.HasException()) return Failure::Exception();
4126
4127   if (prev < subject_length) {
4128     builder.EnsureCapacity(2);
4129     builder.AddSubjectSlice(prev, subject_length);
4130   }
4131
4132   RegExpImpl::SetLastMatchInfo(last_match_info,
4133                                subject,
4134                                capture_count,
4135                                global_cache.LastSuccessfulMatch());
4136
4137   Handle<String> result = builder.ToString();
4138   RETURN_IF_EMPTY_HANDLE(isolate, result);
4139   return *result;
4140 }
4141
4142
4143 template <typename ResultSeqString>
4144 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
4145     Isolate* isolate,
4146     Handle<String> subject,
4147     Handle<JSRegExp> regexp,
4148     Handle<JSArray> last_match_info) {
4149   ASSERT(subject->IsFlat());
4150
4151   // Shortcut for simple non-regexp global replacements
4152   if (regexp->TypeTag() == JSRegExp::ATOM) {
4153     Handle<String> empty_string = isolate->factory()->empty_string();
4154     if (subject->IsOneByteRepresentation()) {
4155       return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4156           isolate, subject, regexp, empty_string, last_match_info);
4157     } else {
4158       return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4159           isolate, subject, regexp, empty_string, last_match_info);
4160     }
4161   }
4162
4163   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4164   if (global_cache.HasException()) return Failure::Exception();
4165
4166   int32_t* current_match = global_cache.FetchNext();
4167   if (current_match == NULL) {
4168     if (global_cache.HasException()) return Failure::Exception();
4169     return *subject;
4170   }
4171
4172   int start = current_match[0];
4173   int end = current_match[1];
4174   int capture_count = regexp->CaptureCount();
4175   int subject_length = subject->length();
4176
4177   int new_length = subject_length - (end - start);
4178   if (new_length == 0) return isolate->heap()->empty_string();
4179
4180   Handle<ResultSeqString> answer;
4181   if (ResultSeqString::kHasAsciiEncoding) {
4182     answer = Handle<ResultSeqString>::cast(
4183         isolate->factory()->NewRawOneByteString(new_length));
4184   } else {
4185     answer = Handle<ResultSeqString>::cast(
4186         isolate->factory()->NewRawTwoByteString(new_length));
4187   }
4188   ASSERT(!answer.is_null());
4189
4190   int prev = 0;
4191   int position = 0;
4192
4193   do {
4194     start = current_match[0];
4195     end = current_match[1];
4196     if (prev < start) {
4197       // Add substring subject[prev;start] to answer string.
4198       String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
4199       position += start - prev;
4200     }
4201     prev = end;
4202
4203     current_match = global_cache.FetchNext();
4204   } while (current_match != NULL);
4205
4206   if (global_cache.HasException()) return Failure::Exception();
4207
4208   RegExpImpl::SetLastMatchInfo(last_match_info,
4209                                subject,
4210                                capture_count,
4211                                global_cache.LastSuccessfulMatch());
4212
4213   if (prev < subject_length) {
4214     // Add substring subject[prev;length] to answer string.
4215     String::WriteToFlat(
4216         *subject, answer->GetChars() + position, prev, subject_length);
4217     position += subject_length - prev;
4218   }
4219
4220   if (position == 0) return isolate->heap()->empty_string();
4221
4222   // Shorten string and fill
4223   int string_size = ResultSeqString::SizeFor(position);
4224   int allocated_string_size = ResultSeqString::SizeFor(new_length);
4225   int delta = allocated_string_size - string_size;
4226
4227   answer->set_length(position);
4228   if (delta == 0) return *answer;
4229
4230   Address end_of_string = answer->address() + string_size;
4231   Heap* heap = isolate->heap();
4232   heap->CreateFillerObjectAt(end_of_string, delta);
4233   heap->AdjustLiveBytes(answer->address(), -delta, Heap::FROM_MUTATOR);
4234   return *answer;
4235 }
4236
4237
4238 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
4239   HandleScope scope(isolate);
4240   ASSERT(args.length() == 4);
4241
4242   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4243   CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4244   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4245   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4246
4247   ASSERT(regexp->GetFlags().is_global());
4248
4249   if (!subject->IsFlat()) subject = FlattenGetString(subject);
4250
4251   if (replacement->length() == 0) {
4252     if (subject->HasOnlyOneByteChars()) {
4253       return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4254           isolate, subject, regexp, last_match_info);
4255     } else {
4256       return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4257           isolate, subject, regexp, last_match_info);
4258     }
4259   }
4260
4261   if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
4262
4263   return StringReplaceGlobalRegExpWithString(
4264       isolate, subject, regexp, replacement, last_match_info);
4265 }
4266
4267
4268 Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
4269                                               Handle<String> subject,
4270                                               Handle<String> search,
4271                                               Handle<String> replace,
4272                                               bool* found,
4273                                               int recursion_limit) {
4274   if (recursion_limit == 0) return Handle<String>::null();
4275   if (subject->IsConsString()) {
4276     ConsString* cons = ConsString::cast(*subject);
4277     Handle<String> first = Handle<String>(cons->first());
4278     Handle<String> second = Handle<String>(cons->second());
4279     Handle<String> new_first =
4280         StringReplaceOneCharWithString(isolate,
4281                                        first,
4282                                        search,
4283                                        replace,
4284                                        found,
4285                                        recursion_limit - 1);
4286     if (new_first.is_null()) return new_first;
4287     if (*found) return isolate->factory()->NewConsString(new_first, second);
4288
4289     Handle<String> new_second =
4290         StringReplaceOneCharWithString(isolate,
4291                                        second,
4292                                        search,
4293                                        replace,
4294                                        found,
4295                                        recursion_limit - 1);
4296     if (new_second.is_null()) return new_second;
4297     if (*found) return isolate->factory()->NewConsString(first, new_second);
4298
4299     return subject;
4300   } else {
4301     int index = Runtime::StringMatch(isolate, subject, search, 0);
4302     if (index == -1) return subject;
4303     *found = true;
4304     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4305     Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
4306     RETURN_IF_EMPTY_HANDLE_VALUE(isolate, cons1, Handle<String>());
4307     Handle<String> second =
4308         isolate->factory()->NewSubString(subject, index + 1, subject->length());
4309     return isolate->factory()->NewConsString(cons1, second);
4310   }
4311 }
4312
4313
4314 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
4315   HandleScope scope(isolate);
4316   ASSERT(args.length() == 3);
4317   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4318   CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4319   CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4320
4321   // If the cons string tree is too deep, we simply abort the recursion and
4322   // retry with a flattened subject string.
4323   const int kRecursionLimit = 0x1000;
4324   bool found = false;
4325   Handle<String> result = StringReplaceOneCharWithString(isolate,
4326                                                          subject,
4327                                                          search,
4328                                                          replace,
4329                                                          &found,
4330                                                          kRecursionLimit);
4331   if (!result.is_null()) return *result;
4332   if (isolate->has_pending_exception()) return Failure::Exception();
4333   return *StringReplaceOneCharWithString(isolate,
4334                                          FlattenGetString(subject),
4335                                          search,
4336                                          replace,
4337                                          &found,
4338                                          kRecursionLimit);
4339 }
4340
4341
4342 // Perform string match of pattern on subject, starting at start index.
4343 // Caller must ensure that 0 <= start_index <= sub->length(),
4344 // and should check that pat->length() + start_index <= sub->length().
4345 int Runtime::StringMatch(Isolate* isolate,
4346                          Handle<String> sub,
4347                          Handle<String> pat,
4348                          int start_index) {
4349   ASSERT(0 <= start_index);
4350   ASSERT(start_index <= sub->length());
4351
4352   int pattern_length = pat->length();
4353   if (pattern_length == 0) return start_index;
4354
4355   int subject_length = sub->length();
4356   if (start_index + pattern_length > subject_length) return -1;
4357
4358   if (!sub->IsFlat()) FlattenString(sub);
4359   if (!pat->IsFlat()) FlattenString(pat);
4360
4361   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4362   // Extract flattened substrings of cons strings before determining asciiness.
4363   String::FlatContent seq_sub = sub->GetFlatContent();
4364   String::FlatContent seq_pat = pat->GetFlatContent();
4365
4366   // dispatch on type of strings
4367   if (seq_pat.IsAscii()) {
4368     Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4369     if (seq_sub.IsAscii()) {
4370       return SearchString(isolate,
4371                           seq_sub.ToOneByteVector(),
4372                           pat_vector,
4373                           start_index);
4374     }
4375     return SearchString(isolate,
4376                         seq_sub.ToUC16Vector(),
4377                         pat_vector,
4378                         start_index);
4379   }
4380   Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4381   if (seq_sub.IsAscii()) {
4382     return SearchString(isolate,
4383                         seq_sub.ToOneByteVector(),
4384                         pat_vector,
4385                         start_index);
4386   }
4387   return SearchString(isolate,
4388                       seq_sub.ToUC16Vector(),
4389                       pat_vector,
4390                       start_index);
4391 }
4392
4393
4394 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
4395   HandleScope scope(isolate);
4396   ASSERT(args.length() == 3);
4397
4398   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4399   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4400
4401   Object* index = args[2];
4402   uint32_t start_index;
4403   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4404
4405   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4406   int position =
4407       Runtime::StringMatch(isolate, sub, pat, start_index);
4408   return Smi::FromInt(position);
4409 }
4410
4411
4412 template <typename schar, typename pchar>
4413 static int StringMatchBackwards(Vector<const schar> subject,
4414                                 Vector<const pchar> pattern,
4415                                 int idx) {
4416   int pattern_length = pattern.length();
4417   ASSERT(pattern_length >= 1);
4418   ASSERT(idx + pattern_length <= subject.length());
4419
4420   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4421     for (int i = 0; i < pattern_length; i++) {
4422       uc16 c = pattern[i];
4423       if (c > String::kMaxOneByteCharCode) {
4424         return -1;
4425       }
4426     }
4427   }
4428
4429   pchar pattern_first_char = pattern[0];
4430   for (int i = idx; i >= 0; i--) {
4431     if (subject[i] != pattern_first_char) continue;
4432     int j = 1;
4433     while (j < pattern_length) {
4434       if (pattern[j] != subject[i+j]) {
4435         break;
4436       }
4437       j++;
4438     }
4439     if (j == pattern_length) {
4440       return i;
4441     }
4442   }
4443   return -1;
4444 }
4445
4446
4447 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
4448   HandleScope scope(isolate);
4449   ASSERT(args.length() == 3);
4450
4451   CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4452   CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4453
4454   Object* index = args[2];
4455   uint32_t start_index;
4456   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4457
4458   uint32_t pat_length = pat->length();
4459   uint32_t sub_length = sub->length();
4460
4461   if (start_index + pat_length > sub_length) {
4462     start_index = sub_length - pat_length;
4463   }
4464
4465   if (pat_length == 0) {
4466     return Smi::FromInt(start_index);
4467   }
4468
4469   if (!sub->IsFlat()) FlattenString(sub);
4470   if (!pat->IsFlat()) FlattenString(pat);
4471
4472   int position = -1;
4473   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4474
4475   String::FlatContent sub_content = sub->GetFlatContent();
4476   String::FlatContent pat_content = pat->GetFlatContent();
4477
4478   if (pat_content.IsAscii()) {
4479     Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4480     if (sub_content.IsAscii()) {
4481       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4482                                       pat_vector,
4483                                       start_index);
4484     } else {
4485       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4486                                       pat_vector,
4487                                       start_index);
4488     }
4489   } else {
4490     Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4491     if (sub_content.IsAscii()) {
4492       position = StringMatchBackwards(sub_content.ToOneByteVector(),
4493                                       pat_vector,
4494                                       start_index);
4495     } else {
4496       position = StringMatchBackwards(sub_content.ToUC16Vector(),
4497                                       pat_vector,
4498                                       start_index);
4499     }
4500   }
4501
4502   return Smi::FromInt(position);
4503 }
4504
4505
4506 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
4507   SealHandleScope shs(isolate);
4508   ASSERT(args.length() == 2);
4509
4510   CONVERT_ARG_CHECKED(String, str1, 0);
4511   CONVERT_ARG_CHECKED(String, str2, 1);
4512
4513   if (str1 == str2) return Smi::FromInt(0);  // Equal.
4514   int str1_length = str1->length();
4515   int str2_length = str2->length();
4516
4517   // Decide trivial cases without flattening.
4518   if (str1_length == 0) {
4519     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
4520     return Smi::FromInt(-str2_length);
4521   } else {
4522     if (str2_length == 0) return Smi::FromInt(str1_length);
4523   }
4524
4525   int end = str1_length < str2_length ? str1_length : str2_length;
4526
4527   // No need to flatten if we are going to find the answer on the first
4528   // character.  At this point we know there is at least one character
4529   // in each string, due to the trivial case handling above.
4530   int d = str1->Get(0) - str2->Get(0);
4531   if (d != 0) return Smi::FromInt(d);
4532
4533   str1->TryFlatten();
4534   str2->TryFlatten();
4535
4536   ConsStringIteratorOp* op1 =
4537       isolate->runtime_state()->string_locale_compare_it1();
4538   ConsStringIteratorOp* op2 =
4539       isolate->runtime_state()->string_locale_compare_it2();
4540   // TODO(dcarney) Can do array compares here more efficiently.
4541   StringCharacterStream stream1(str1, op1);
4542   StringCharacterStream stream2(str2, op2);
4543
4544   for (int i = 0; i < end; i++) {
4545     uint16_t char1 = stream1.GetNext();
4546     uint16_t char2 = stream2.GetNext();
4547     if (char1 != char2) return Smi::FromInt(char1 - char2);
4548   }
4549
4550   return Smi::FromInt(str1_length - str2_length);
4551 }
4552
4553
4554 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SubString) {
4555   HandleScope scope(isolate);
4556   ASSERT(args.length() == 3);
4557
4558   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
4559   int start, end;
4560   // We have a fast integer-only case here to avoid a conversion to double in
4561   // the common case where from and to are Smis.
4562   if (args[1]->IsSmi() && args[2]->IsSmi()) {
4563     CONVERT_SMI_ARG_CHECKED(from_number, 1);
4564     CONVERT_SMI_ARG_CHECKED(to_number, 2);
4565     start = from_number;
4566     end = to_number;
4567   } else {
4568     CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4569     CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4570     start = FastD2IChecked(from_number);
4571     end = FastD2IChecked(to_number);
4572   }
4573   RUNTIME_ASSERT(end >= start);
4574   RUNTIME_ASSERT(start >= 0);
4575   RUNTIME_ASSERT(end <= string->length());
4576   isolate->counters()->sub_string_runtime()->Increment();
4577
4578   return *isolate->factory()->NewSubString(string, start, end);
4579 }
4580
4581
4582 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
4583   HandleScope handles(isolate);
4584   ASSERT_EQ(3, args.length());
4585
4586   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4587   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4588   CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4589
4590   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4591   if (global_cache.HasException()) return Failure::Exception();
4592
4593   int capture_count = regexp->CaptureCount();
4594
4595   ZoneScope zone_scope(isolate->runtime_zone());
4596   ZoneList<int> offsets(8, zone_scope.zone());
4597
4598   while (true) {
4599     int32_t* match = global_cache.FetchNext();
4600     if (match == NULL) break;
4601     offsets.Add(match[0], zone_scope.zone());  // start
4602     offsets.Add(match[1], zone_scope.zone());  // end
4603   }
4604
4605   if (global_cache.HasException()) return Failure::Exception();
4606
4607   if (offsets.length() == 0) {
4608     // Not a single match.
4609     return isolate->heap()->null_value();
4610   }
4611
4612   RegExpImpl::SetLastMatchInfo(regexp_info,
4613                                subject,
4614                                capture_count,
4615                                global_cache.LastSuccessfulMatch());
4616
4617   int matches = offsets.length() / 2;
4618   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4619   Handle<String> substring =
4620       isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4621   elements->set(0, *substring);
4622   for (int i = 1; i < matches; i++) {
4623     HandleScope temp_scope(isolate);
4624     int from = offsets.at(i * 2);
4625     int to = offsets.at(i * 2 + 1);
4626     Handle<String> substring =
4627         isolate->factory()->NewProperSubString(subject, from, to);
4628     elements->set(i, *substring);
4629   }
4630   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4631   result->set_length(Smi::FromInt(matches));
4632   return *result;
4633 }
4634
4635
4636 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4637 // separate last match info.  See comment on that function.
4638 template<bool has_capture>
4639 static MaybeObject* SearchRegExpMultiple(
4640     Isolate* isolate,
4641     Handle<String> subject,
4642     Handle<JSRegExp> regexp,
4643     Handle<JSArray> last_match_array,
4644     Handle<JSArray> result_array) {
4645   ASSERT(subject->IsFlat());
4646   ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
4647
4648   int capture_count = regexp->CaptureCount();
4649   int subject_length = subject->length();
4650
4651   static const int kMinLengthToCache = 0x1000;
4652
4653   if (subject_length > kMinLengthToCache) {
4654     Handle<Object> cached_answer(RegExpResultsCache::Lookup(
4655         isolate->heap(),
4656         *subject,
4657         regexp->data(),
4658         RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
4659     if (*cached_answer != Smi::FromInt(0)) {
4660       Handle<FixedArray> cached_fixed_array =
4661           Handle<FixedArray>(FixedArray::cast(*cached_answer));
4662       // The cache FixedArray is a COW-array and can therefore be reused.
4663       JSArray::SetContent(result_array, cached_fixed_array);
4664       // The actual length of the result array is stored in the last element of
4665       // the backing store (the backing FixedArray may have a larger capacity).
4666       Object* cached_fixed_array_last_element =
4667           cached_fixed_array->get(cached_fixed_array->length() - 1);
4668       Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4669       result_array->set_length(js_array_length);
4670       RegExpImpl::SetLastMatchInfo(
4671           last_match_array, subject, capture_count, NULL);
4672       return *result_array;
4673     }
4674   }
4675
4676   RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4677   if (global_cache.HasException()) return Failure::Exception();
4678
4679   Handle<FixedArray> result_elements;
4680   if (result_array->HasFastObjectElements()) {
4681     result_elements =
4682         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4683   }
4684   if (result_elements.is_null() || result_elements->length() < 16) {
4685     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4686   }
4687
4688   FixedArrayBuilder builder(result_elements);
4689
4690   // Position to search from.
4691   int match_start = -1;
4692   int match_end = 0;
4693   bool first = true;
4694
4695   // Two smis before and after the match, for very long strings.
4696   static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4697
4698   while (true) {
4699     int32_t* current_match = global_cache.FetchNext();
4700     if (current_match == NULL) break;
4701     match_start = current_match[0];
4702     builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4703     if (match_end < match_start) {
4704       ReplacementStringBuilder::AddSubjectSlice(&builder,
4705                                                 match_end,
4706                                                 match_start);
4707     }
4708     match_end = current_match[1];
4709     {
4710       // Avoid accumulating new handles inside loop.
4711       HandleScope temp_scope(isolate);
4712       Handle<String> match;
4713       if (!first) {
4714         match = isolate->factory()->NewProperSubString(subject,
4715                                                        match_start,
4716                                                        match_end);
4717       } else {
4718         match = isolate->factory()->NewSubString(subject,
4719                                                  match_start,
4720                                                  match_end);
4721         first = false;
4722       }
4723
4724       if (has_capture) {
4725         // Arguments array to replace function is match, captures, index and
4726         // subject, i.e., 3 + capture count in total.
4727         Handle<FixedArray> elements =
4728             isolate->factory()->NewFixedArray(3 + capture_count);
4729
4730         elements->set(0, *match);
4731         for (int i = 1; i <= capture_count; i++) {
4732           int start = current_match[i * 2];
4733           if (start >= 0) {
4734             int end = current_match[i * 2 + 1];
4735             ASSERT(start <= end);
4736             Handle<String> substring =
4737                 isolate->factory()->NewSubString(subject, start, end);
4738             elements->set(i, *substring);
4739           } else {
4740             ASSERT(current_match[i * 2 + 1] < 0);
4741             elements->set(i, isolate->heap()->undefined_value());
4742           }
4743         }
4744         elements->set(capture_count + 1, Smi::FromInt(match_start));
4745         elements->set(capture_count + 2, *subject);
4746         builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4747       } else {
4748         builder.Add(*match);
4749       }
4750     }
4751   }
4752
4753   if (global_cache.HasException()) return Failure::Exception();
4754
4755   if (match_start >= 0) {
4756     // Finished matching, with at least one match.
4757     if (match_end < subject_length) {
4758       ReplacementStringBuilder::AddSubjectSlice(&builder,
4759                                                 match_end,
4760                                                 subject_length);
4761     }
4762
4763     RegExpImpl::SetLastMatchInfo(
4764         last_match_array, subject, capture_count, NULL);
4765
4766     if (subject_length > kMinLengthToCache) {
4767       // Store the length of the result array into the last element of the
4768       // backing FixedArray.
4769       builder.EnsureCapacity(1);
4770       Handle<FixedArray> fixed_array = builder.array();
4771       fixed_array->set(fixed_array->length() - 1,
4772                        Smi::FromInt(builder.length()));
4773       // Cache the result and turn the FixedArray into a COW array.
4774       RegExpResultsCache::Enter(isolate->heap(),
4775                                 *subject,
4776                                 regexp->data(),
4777                                 *fixed_array,
4778                                 RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
4779     }
4780     return *builder.ToJSArray(result_array);
4781   } else {
4782     return isolate->heap()->null_value();  // No matches at all.
4783   }
4784 }
4785
4786
4787 // This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4788 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4789 // set any other last match array info.
4790 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4791   HandleScope handles(isolate);
4792   ASSERT(args.length() == 4);
4793
4794   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4795   if (!subject->IsFlat()) FlattenString(subject);
4796   CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4797   CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4798   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4799
4800   ASSERT(regexp->GetFlags().is_global());
4801
4802   if (regexp->CaptureCount() == 0) {
4803     return SearchRegExpMultiple<false>(
4804         isolate, subject, regexp, last_match_info, result_array);
4805   } else {
4806     return SearchRegExpMultiple<true>(
4807         isolate, subject, regexp, last_match_info, result_array);
4808   }
4809 }
4810
4811
4812 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4813   SealHandleScope shs(isolate);
4814   ASSERT(args.length() == 2);
4815   CONVERT_SMI_ARG_CHECKED(radix, 1);
4816   RUNTIME_ASSERT(2 <= radix && radix <= 36);
4817
4818   // Fast case where the result is a one character string.
4819   if (args[0]->IsSmi()) {
4820     int value = args.smi_at(0);
4821     if (value >= 0 && value < radix) {
4822       // Character array used for conversion.
4823       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4824       return isolate->heap()->
4825           LookupSingleCharacterStringFromCode(kCharTable[value]);
4826     }
4827   }
4828
4829   // Slow case.
4830   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4831   if (std::isnan(value)) {
4832     return *isolate->factory()->nan_string();
4833   }
4834   if (std::isinf(value)) {
4835     if (value < 0) {
4836       return *isolate->factory()->minus_infinity_string();
4837     }
4838     return *isolate->factory()->infinity_string();
4839   }
4840   char* str = DoubleToRadixCString(value, radix);
4841   MaybeObject* result =
4842       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4843   DeleteArray(str);
4844   return result;
4845 }
4846
4847
4848 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4849   SealHandleScope shs(isolate);
4850   ASSERT(args.length() == 2);
4851
4852   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4853   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4854   int f = FastD2IChecked(f_number);
4855   RUNTIME_ASSERT(f >= 0);
4856   char* str = DoubleToFixedCString(value, f);
4857   MaybeObject* res =
4858       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4859   DeleteArray(str);
4860   return res;
4861 }
4862
4863
4864 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4865   SealHandleScope shs(isolate);
4866   ASSERT(args.length() == 2);
4867
4868   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4869   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4870   int f = FastD2IChecked(f_number);
4871   RUNTIME_ASSERT(f >= -1 && f <= 20);
4872   char* str = DoubleToExponentialCString(value, f);
4873   MaybeObject* res =
4874       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4875   DeleteArray(str);
4876   return res;
4877 }
4878
4879
4880 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4881   SealHandleScope shs(isolate);
4882   ASSERT(args.length() == 2);
4883
4884   CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4885   CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4886   int f = FastD2IChecked(f_number);
4887   RUNTIME_ASSERT(f >= 1 && f <= 21);
4888   char* str = DoubleToPrecisionCString(value, f);
4889   MaybeObject* res =
4890       isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4891   DeleteArray(str);
4892   return res;
4893 }
4894
4895
4896 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) {
4897   HandleScope shs(isolate);
4898   ASSERT(args.length() == 1);
4899
4900   CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
4901   if (Smi::IsValid(number)) {
4902     return isolate->heap()->true_value();
4903   } else {
4904     return isolate->heap()->false_value();
4905   }
4906 }
4907
4908
4909 // Returns a single character string where first character equals
4910 // string->Get(index).
4911 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4912   if (index < static_cast<uint32_t>(string->length())) {
4913     string->TryFlatten();
4914     return LookupSingleCharacterStringFromCode(
4915         string->GetIsolate(),
4916         string->Get(index));
4917   }
4918   return Execution::CharAt(string, index);
4919 }
4920
4921
4922 Handle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
4923                                            Handle<Object> object,
4924                                            uint32_t index) {
4925   // Handle [] indexing on Strings
4926   if (object->IsString()) {
4927     Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4928     if (!result->IsUndefined()) return result;
4929   }
4930
4931   // Handle [] indexing on String objects
4932   if (object->IsStringObjectWithCharacterAt(index)) {
4933     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4934     Handle<Object> result =
4935         GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4936     if (!result->IsUndefined()) return result;
4937   }
4938
4939   Handle<Object> result;
4940   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4941     Handle<Object> proto(object->GetPrototype(isolate), isolate);
4942     return Object::GetElement(isolate, proto, index);
4943   } else {
4944     return Object::GetElement(isolate, object, index);
4945   }
4946 }
4947
4948
4949 static Handle<Name> ToName(Isolate* isolate, Handle<Object> key) {
4950   if (key->IsName()) {
4951     return Handle<Name>::cast(key);
4952   } else {
4953     bool has_pending_exception = false;
4954     Handle<Object> converted =
4955         Execution::ToString(isolate, key, &has_pending_exception);
4956     if (has_pending_exception) return Handle<Name>();
4957     return Handle<Name>::cast(converted);
4958   }
4959 }
4960
4961
4962 MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
4963                                         Handle<JSReceiver> object,
4964                                         Handle<Object> key) {
4965   HandleScope scope(isolate);
4966
4967   // Check if the given key is an array index.
4968   uint32_t index;
4969   if (key->ToArrayIndex(&index)) {
4970     return isolate->heap()->ToBoolean(JSReceiver::HasElement(object, index));
4971   }
4972
4973   // Convert the key to a name - possibly by calling back into JavaScript.
4974   Handle<Name> name = ToName(isolate, key);
4975   RETURN_IF_EMPTY_HANDLE(isolate, name);
4976
4977   return isolate->heap()->ToBoolean(JSReceiver::HasProperty(object, name));
4978 }
4979
4980 MaybeObject* Runtime::GetObjectPropertyOrFail(
4981     Isolate* isolate,
4982     Handle<Object> object,
4983     Handle<Object> key) {
4984   CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4985       GetObjectProperty(isolate, object, key));
4986 }
4987
4988 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4989                                         Handle<Object> object,
4990                                         Handle<Object> key) {
4991   HandleScope scope(isolate);
4992
4993   if (object->IsUndefined() || object->IsNull()) {
4994     Handle<Object> args[2] = { key, object };
4995     Handle<Object> error =
4996         isolate->factory()->NewTypeError("non_object_property_load",
4997                                          HandleVector(args, 2));
4998     return isolate->Throw(*error);
4999   }
5000
5001   // Check if the given key is an array index.
5002   uint32_t index;
5003   if (key->ToArrayIndex(&index)) {
5004     Handle<Object> result = GetElementOrCharAt(isolate, object, index);
5005     RETURN_IF_EMPTY_HANDLE(isolate, result);
5006     return *result;
5007   }
5008
5009   // Convert the key to a name - possibly by calling back into JavaScript.
5010   Handle<Name> name = ToName(isolate, key);
5011   RETURN_IF_EMPTY_HANDLE(isolate, name);
5012
5013   // Check if the name is trivially convertible to an index and get
5014   // the element if so.
5015   if (name->AsArrayIndex(&index)) {
5016     Handle<Object> result = GetElementOrCharAt(isolate, object, index);
5017     RETURN_IF_EMPTY_HANDLE(isolate, result);
5018     return *result;
5019   } else {
5020     return object->GetProperty(*name);
5021   }
5022 }
5023
5024
5025 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
5026   SealHandleScope shs(isolate);
5027   ASSERT(args.length() == 2);
5028
5029   Handle<Object> object = args.at<Object>(0);
5030   Handle<Object> key = args.at<Object>(1);
5031
5032   return Runtime::GetObjectProperty(isolate, object, key);
5033 }
5034
5035
5036 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
5037 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
5038   SealHandleScope shs(isolate);
5039   ASSERT(args.length() == 2);
5040
5041   // Fast cases for getting named properties of the receiver JSObject
5042   // itself.
5043   //
5044   // The global proxy objects has to be excluded since LocalLookup on
5045   // the global proxy object can return a valid result even though the
5046   // global proxy object never has properties.  This is the case
5047   // because the global proxy object forwards everything to its hidden
5048   // prototype including local lookups.
5049   //
5050   // Additionally, we need to make sure that we do not cache results
5051   // for objects that require access checks.
5052   if (args[0]->IsJSObject()) {
5053     if (!args[0]->IsJSGlobalProxy() &&
5054         !args[0]->IsAccessCheckNeeded() &&
5055         args[1]->IsName()) {
5056       JSObject* receiver = JSObject::cast(args[0]);
5057       Name* key = Name::cast(args[1]);
5058       if (receiver->HasFastProperties()) {
5059         // Attempt to use lookup cache.
5060         Map* receiver_map = receiver->map();
5061         KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
5062         int offset = keyed_lookup_cache->Lookup(receiver_map, key);
5063         if (offset != -1) {
5064           // Doubles are not cached, so raw read the value.
5065           Object* value = receiver->RawFastPropertyAt(offset);
5066           return value->IsTheHole()
5067               ? isolate->heap()->undefined_value()
5068               : value;
5069         }
5070         // Lookup cache miss.  Perform lookup and update the cache if
5071         // appropriate.
5072         LookupResult result(isolate);
5073         receiver->LocalLookup(key, &result);
5074         if (result.IsField()) {
5075           int offset = result.GetFieldIndex().field_index();
5076           // Do not track double fields in the keyed lookup cache. Reading
5077           // double values requires boxing.
5078           if (!result.representation().IsDouble()) {
5079             keyed_lookup_cache->Update(receiver_map, key, offset);
5080           }
5081           return receiver->FastPropertyAt(result.representation(), offset);
5082         }
5083       } else {
5084         // Attempt dictionary lookup.
5085         NameDictionary* dictionary = receiver->property_dictionary();
5086         int entry = dictionary->FindEntry(key);
5087         if ((entry != NameDictionary::kNotFound) &&
5088             (dictionary->DetailsAt(entry).type() == NORMAL)) {
5089           Object* value = dictionary->ValueAt(entry);
5090           if (!receiver->IsGlobalObject()) return value;
5091           value = PropertyCell::cast(value)->value();
5092           if (!value->IsTheHole()) return value;
5093           // If value is the hole do the general lookup.
5094         }
5095       }
5096     } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
5097       // JSObject without a name key. If the key is a Smi, check for a
5098       // definite out-of-bounds access to elements, which is a strong indicator
5099       // that subsequent accesses will also call the runtime. Proactively
5100       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
5101       // doubles for those future calls in the case that the elements would
5102       // become FAST_DOUBLE_ELEMENTS.
5103       Handle<JSObject> js_object(args.at<JSObject>(0));
5104       ElementsKind elements_kind = js_object->GetElementsKind();
5105       if (IsFastDoubleElementsKind(elements_kind)) {
5106         FixedArrayBase* elements = js_object->elements();
5107         if (args.at<Smi>(1)->value() >= elements->length()) {
5108           if (IsFastHoleyElementsKind(elements_kind)) {
5109             elements_kind = FAST_HOLEY_ELEMENTS;
5110           } else {
5111             elements_kind = FAST_ELEMENTS;
5112           }
5113           MaybeObject* maybe_object = TransitionElements(js_object,
5114                                                          elements_kind,
5115                                                          isolate);
5116           if (maybe_object->IsFailure()) return maybe_object;
5117         }
5118       } else {
5119         ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
5120                !IsFastElementsKind(elements_kind));
5121       }
5122     }
5123   } else if (args[0]->IsString() && args[1]->IsSmi()) {
5124     // Fast case for string indexing using [] with a smi index.
5125     HandleScope scope(isolate);
5126     Handle<String> str = args.at<String>(0);
5127     int index = args.smi_at(1);
5128     if (index >= 0 && index < str->length()) {
5129       Handle<Object> result = GetCharAt(str, index);
5130       return *result;
5131     }
5132   }
5133
5134   // Fall back to GetObjectProperty.
5135   return Runtime::GetObjectProperty(isolate,
5136                                     args.at<Object>(0),
5137                                     args.at<Object>(1));
5138 }
5139
5140
5141 static bool IsValidAccessor(Handle<Object> obj) {
5142   return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
5143 }
5144
5145
5146 // Implements part of 8.12.9 DefineOwnProperty.
5147 // There are 3 cases that lead here:
5148 // Step 4b - define a new accessor property.
5149 // Steps 9c & 12 - replace an existing data property with an accessor property.
5150 // Step 12 - update an existing accessor property with an accessor or generic
5151 //           descriptor.
5152 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
5153   HandleScope scope(isolate);
5154   ASSERT(args.length() == 5);
5155   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5156   RUNTIME_ASSERT(!obj->IsNull());
5157   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5158   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
5159   RUNTIME_ASSERT(IsValidAccessor(getter));
5160   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
5161   RUNTIME_ASSERT(IsValidAccessor(setter));
5162   CONVERT_SMI_ARG_CHECKED(unchecked, 4);
5163   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5164   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5165
5166   bool fast = obj->HasFastProperties();
5167   JSObject::DefineAccessor(obj, name, getter, setter, attr);
5168   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5169   if (fast) JSObject::TransformToFastProperties(obj, 0);
5170   return isolate->heap()->undefined_value();
5171 }
5172
5173
5174 // Implements part of 8.12.9 DefineOwnProperty.
5175 // There are 3 cases that lead here:
5176 // Step 4a - define a new data property.
5177 // Steps 9b & 12 - replace an existing accessor property with a data property.
5178 // Step 12 - update an existing data property with a data or generic
5179 //           descriptor.
5180 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
5181   HandleScope scope(isolate);
5182   ASSERT(args.length() == 4);
5183   CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
5184   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5185   CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
5186   CONVERT_SMI_ARG_CHECKED(unchecked, 3);
5187   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5188   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5189
5190   LookupResult lookup(isolate);
5191   js_object->LocalLookupRealNamedProperty(*name, &lookup);
5192
5193   // Special case for callback properties.
5194   if (lookup.IsPropertyCallbacks()) {
5195     Handle<Object> callback(lookup.GetCallbackObject(), isolate);
5196     // To be compatible with Safari we do not change the value on API objects
5197     // in Object.defineProperty(). Firefox disagrees here, and actually changes
5198     // the value.
5199     if (callback->IsAccessorInfo()) {
5200       return isolate->heap()->undefined_value();
5201     }
5202     // Avoid redefining foreign callback as data property, just use the stored
5203     // setter to update the value instead.
5204     // TODO(mstarzinger): So far this only works if property attributes don't
5205     // change, this should be fixed once we cleanup the underlying code.
5206     if (callback->IsForeign() && lookup.GetAttributes() == attr) {
5207       Handle<Object> result_object =
5208           JSObject::SetPropertyWithCallback(js_object,
5209                                             callback,
5210                                             name,
5211                                             obj_value,
5212                                             handle(lookup.holder()),
5213                                             STRICT);
5214       RETURN_IF_EMPTY_HANDLE(isolate, result_object);
5215       return *result_object;
5216     }
5217   }
5218
5219   // Take special care when attributes are different and there is already
5220   // a property. For simplicity we normalize the property which enables us
5221   // to not worry about changing the instance_descriptor and creating a new
5222   // map. The current version of SetObjectProperty does not handle attributes
5223   // correctly in the case where a property is a field and is reset with
5224   // new attributes.
5225   if (lookup.IsFound() &&
5226       (attr != lookup.GetAttributes() || lookup.IsPropertyCallbacks())) {
5227     // New attributes - normalize to avoid writing to instance descriptor
5228     if (js_object->IsJSGlobalProxy()) {
5229       // Since the result is a property, the prototype will exist so
5230       // we don't have to check for null.
5231       js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5232     }
5233     JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
5234     // Use IgnoreAttributes version since a readonly property may be
5235     // overridden and SetProperty does not allow this.
5236     Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5237         js_object, name, obj_value, attr);
5238     RETURN_IF_EMPTY_HANDLE(isolate, result);
5239     return *result;
5240   }
5241
5242   Handle<Object> result = Runtime::ForceSetObjectProperty(isolate, js_object,
5243                                                           name,
5244                                                           obj_value,
5245                                                           attr);
5246   RETURN_IF_EMPTY_HANDLE(isolate, result);
5247   return *result;
5248 }
5249
5250
5251 // Return property without being observable by accessors or interceptors.
5252 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
5253   SealHandleScope shs(isolate);
5254   ASSERT(args.length() == 2);
5255   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5256   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5257   LookupResult lookup(isolate);
5258   object->LookupRealNamedProperty(*key, &lookup);
5259   if (!lookup.IsFound()) return isolate->heap()->undefined_value();
5260   switch (lookup.type()) {
5261     case NORMAL:
5262       return lookup.holder()->GetNormalizedProperty(&lookup);
5263     case FIELD:
5264       return lookup.holder()->FastPropertyAt(
5265           lookup.representation(),
5266           lookup.GetFieldIndex().field_index());
5267     case CONSTANT:
5268       return lookup.GetConstant();
5269     case CALLBACKS:
5270     case HANDLER:
5271     case INTERCEPTOR:
5272     case TRANSITION:
5273       return isolate->heap()->undefined_value();
5274     case NONEXISTENT:
5275       UNREACHABLE();
5276   }
5277   return isolate->heap()->undefined_value();
5278 }
5279
5280
5281 Handle<Object> Runtime::SetObjectProperty(Isolate* isolate,
5282                                           Handle<Object> object,
5283                                           Handle<Object> key,
5284                                           Handle<Object> value,
5285                                           PropertyAttributes attr,
5286                                           StrictMode strict_mode) {
5287   SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5288
5289   if (object->IsUndefined() || object->IsNull()) {
5290     Handle<Object> args[2] = { key, object };
5291     Handle<Object> error =
5292         isolate->factory()->NewTypeError("non_object_property_store",
5293                                          HandleVector(args, 2));
5294     isolate->Throw(*error);
5295     return Handle<Object>();
5296   }
5297
5298   if (object->IsJSProxy()) {
5299     bool has_pending_exception = false;
5300     Handle<Object> name_object = key->IsSymbol()
5301         ? key : Execution::ToString(isolate, key, &has_pending_exception);
5302     if (has_pending_exception) return Handle<Object>();  // exception
5303     Handle<Name> name = Handle<Name>::cast(name_object);
5304     return JSReceiver::SetProperty(Handle<JSProxy>::cast(object), name, value,
5305                                    attr,
5306                                    strict_mode);
5307   }
5308
5309   // If the object isn't a JavaScript object, we ignore the store.
5310   if (!object->IsJSObject()) return value;
5311
5312   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5313
5314   // Check if the given key is an array index.
5315   uint32_t index;
5316   if (key->ToArrayIndex(&index)) {
5317     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5318     // of a string using [] notation.  We need to support this too in
5319     // JavaScript.
5320     // In the case of a String object we just need to redirect the assignment to
5321     // the underlying string if the index is in range.  Since the underlying
5322     // string does nothing with the assignment then we can ignore such
5323     // assignments.
5324     if (js_object->IsStringObjectWithCharacterAt(index)) {
5325       return value;
5326     }
5327
5328     js_object->ValidateElements();
5329     if (js_object->HasExternalArrayElements() ||
5330         js_object->HasFixedTypedArrayElements()) {
5331       // TODO(ningxin): Throw an error if setting a Float32x4Array element
5332       // while the value is not Float32x4Object.
5333       if (!value->IsNumber() && !value->IsFloat32x4() &&
5334           !value->IsInt32x4() && !value->IsUndefined()) {
5335         bool has_exception;
5336         Handle<Object> number =
5337             Execution::ToNumber(isolate, value, &has_exception);
5338         if (has_exception) return Handle<Object>();  // exception
5339         value = number;
5340       }
5341     }
5342     Handle<Object> result = JSObject::SetElement(js_object, index, value, attr,
5343                                                  strict_mode,
5344                                                  true,
5345                                                  set_mode);
5346     js_object->ValidateElements();
5347     return result.is_null() ? result : value;
5348   }
5349
5350   if (key->IsName()) {
5351     Handle<Name> name = Handle<Name>::cast(key);
5352     if (name->AsArrayIndex(&index)) {
5353       if (js_object->HasExternalArrayElements()) {
5354         // TODO(ningxin): Throw an error if setting a Float32x4Array element
5355         // while the value is not Float32x4Object.
5356         if (!value->IsNumber() && !value->IsFloat32x4() &&
5357             !value->IsInt32x4() && !value->IsUndefined()) {
5358           bool has_exception;
5359           Handle<Object> number =
5360               Execution::ToNumber(isolate, value, &has_exception);
5361           if (has_exception) return Handle<Object>();  // exception
5362           value = number;
5363         }
5364       }
5365       return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5366                                   true,
5367                                   set_mode);
5368     } else {
5369       if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5370       return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5371     }
5372   }
5373
5374   // Call-back into JavaScript to convert the key to a string.
5375   bool has_pending_exception = false;
5376   Handle<Object> converted =
5377       Execution::ToString(isolate, key, &has_pending_exception);
5378   if (has_pending_exception) return Handle<Object>();  // exception
5379   Handle<String> name = Handle<String>::cast(converted);
5380
5381   if (name->AsArrayIndex(&index)) {
5382     return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5383                                 true,
5384                                 set_mode);
5385   } else {
5386     return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5387   }
5388 }
5389
5390
5391 Handle<Object> Runtime::ForceSetObjectProperty(Isolate* isolate,
5392                                                Handle<JSObject> js_object,
5393                                                Handle<Object> key,
5394                                                Handle<Object> value,
5395                                                PropertyAttributes attr) {
5396   // Check if the given key is an array index.
5397   uint32_t index;
5398   if (key->ToArrayIndex(&index)) {
5399     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5400     // of a string using [] notation.  We need to support this too in
5401     // JavaScript.
5402     // In the case of a String object we just need to redirect the assignment to
5403     // the underlying string if the index is in range.  Since the underlying
5404     // string does nothing with the assignment then we can ignore such
5405     // assignments.
5406     if (js_object->IsStringObjectWithCharacterAt(index)) {
5407       return value;
5408     }
5409
5410     return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
5411                                 false,
5412                                 DEFINE_PROPERTY);
5413   }
5414
5415   if (key->IsName()) {
5416     Handle<Name> name = Handle<Name>::cast(key);
5417     if (name->AsArrayIndex(&index)) {
5418       return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
5419                                   false,
5420                                   DEFINE_PROPERTY);
5421     } else {
5422       if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5423       return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name,
5424                                                         value, attr);
5425     }
5426   }
5427
5428   // Call-back into JavaScript to convert the key to a string.
5429   bool has_pending_exception = false;
5430   Handle<Object> converted =
5431       Execution::ToString(isolate, key, &has_pending_exception);
5432   if (has_pending_exception) return Handle<Object>();  // exception
5433   Handle<String> name = Handle<String>::cast(converted);
5434
5435   if (name->AsArrayIndex(&index)) {
5436     return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
5437                                 false,
5438                                 DEFINE_PROPERTY);
5439   } else {
5440     return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name, value,
5441                                                       attr);
5442   }
5443 }
5444
5445
5446 MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
5447                                            Handle<JSReceiver> receiver,
5448                                            Handle<Object> key,
5449                                            JSReceiver::DeleteMode mode) {
5450   HandleScope scope(isolate);
5451
5452   // Check if the given key is an array index.
5453   uint32_t index;
5454   if (key->ToArrayIndex(&index)) {
5455     // In Firefox/SpiderMonkey, Safari and Opera you can access the
5456     // characters of a string using [] notation.  In the case of a
5457     // String object we just need to redirect the deletion to the
5458     // underlying string if the index is in range.  Since the
5459     // underlying string does nothing with the deletion, we can ignore
5460     // such deletions.
5461     if (receiver->IsStringObjectWithCharacterAt(index)) {
5462       return isolate->heap()->true_value();
5463     }
5464
5465     Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
5466     RETURN_IF_EMPTY_HANDLE(isolate, result);
5467     return *result;
5468   }
5469
5470   Handle<Name> name;
5471   if (key->IsName()) {
5472     name = Handle<Name>::cast(key);
5473   } else {
5474     // Call-back into JavaScript to convert the key to a string.
5475     bool has_pending_exception = false;
5476     Handle<Object> converted = Execution::ToString(
5477         isolate, key, &has_pending_exception);
5478     if (has_pending_exception) return Failure::Exception();
5479     name = Handle<String>::cast(converted);
5480   }
5481
5482   if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5483   Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
5484   RETURN_IF_EMPTY_HANDLE(isolate, result);
5485   return *result;
5486 }
5487
5488
5489 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHiddenProperty) {
5490   HandleScope scope(isolate);
5491   RUNTIME_ASSERT(args.length() == 3);
5492
5493   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5494   CONVERT_ARG_HANDLE_CHECKED(String, key, 1);
5495   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5496   return *JSObject::SetHiddenProperty(object, key, value);
5497 }
5498
5499
5500 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
5501   HandleScope scope(isolate);
5502   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5503
5504   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5505   CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
5506   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5507   CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5508   RUNTIME_ASSERT(
5509       (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5510   // Compute attributes.
5511   PropertyAttributes attributes =
5512       static_cast<PropertyAttributes>(unchecked_attributes);
5513
5514   StrictMode strict_mode = SLOPPY;
5515   if (args.length() == 5) {
5516     CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_arg, 4);
5517     strict_mode = strict_mode_arg;
5518   }
5519
5520   Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
5521                                                      value,
5522                                                      attributes,
5523                                                      strict_mode);
5524   RETURN_IF_EMPTY_HANDLE(isolate, result);
5525   return *result;
5526 }
5527
5528
5529 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
5530   HandleScope scope(isolate);
5531   RUNTIME_ASSERT(args.length() == 2);
5532   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5533   CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5534   JSObject::TransitionElementsKind(array, map->elements_kind());
5535   return *array;
5536 }
5537
5538
5539 // Set the native flag on the function.
5540 // This is used to decide if we should transform null and undefined
5541 // into the global object when doing call and apply.
5542 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
5543   SealHandleScope shs(isolate);
5544   RUNTIME_ASSERT(args.length() == 1);
5545
5546   CONVERT_ARG_CHECKED(Object, object, 0);
5547
5548   if (object->IsJSFunction()) {
5549     JSFunction* func = JSFunction::cast(object);
5550     func->shared()->set_native(true);
5551   }
5552   return isolate->heap()->undefined_value();
5553 }
5554
5555
5556 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInlineBuiltinFlag) {
5557   SealHandleScope shs(isolate);
5558   RUNTIME_ASSERT(args.length() == 1);
5559
5560   Handle<Object> object = args.at<Object>(0);
5561
5562   if (object->IsJSFunction()) {
5563     JSFunction* func = JSFunction::cast(*object);
5564     func->shared()->set_inline_builtin(true);
5565   }
5566   return isolate->heap()->undefined_value();
5567 }
5568
5569
5570 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
5571   HandleScope scope(isolate);
5572   RUNTIME_ASSERT(args.length() == 5);
5573   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5574   CONVERT_SMI_ARG_CHECKED(store_index, 1);
5575   Handle<Object> value = args.at<Object>(2);
5576   CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5577   CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5578
5579   Object* raw_literal_cell = literals->get(literal_index);
5580   JSArray* boilerplate = NULL;
5581   if (raw_literal_cell->IsAllocationSite()) {
5582     AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5583     boilerplate = JSArray::cast(site->transition_info());
5584   } else {
5585     boilerplate = JSArray::cast(raw_literal_cell);
5586   }
5587   Handle<JSArray> boilerplate_object(boilerplate);
5588   ElementsKind elements_kind = object->GetElementsKind();
5589   ASSERT(IsFastElementsKind(elements_kind));
5590   // Smis should never trigger transitions.
5591   ASSERT(!value->IsSmi());
5592
5593   if (value->IsNumber()) {
5594     ASSERT(IsFastSmiElementsKind(elements_kind));
5595     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5596         ? FAST_HOLEY_DOUBLE_ELEMENTS
5597         : FAST_DOUBLE_ELEMENTS;
5598     if (IsMoreGeneralElementsKindTransition(
5599             boilerplate_object->GetElementsKind(),
5600             transitioned_kind)) {
5601       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5602     }
5603     JSObject::TransitionElementsKind(object, transitioned_kind);
5604     ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
5605     FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5606     HeapNumber* number = HeapNumber::cast(*value);
5607     double_array->set(store_index, number->Number());
5608   } else {
5609     ASSERT(IsFastSmiElementsKind(elements_kind) ||
5610            IsFastDoubleElementsKind(elements_kind));
5611     ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5612         ? FAST_HOLEY_ELEMENTS
5613         : FAST_ELEMENTS;
5614     JSObject::TransitionElementsKind(object, transitioned_kind);
5615     if (IsMoreGeneralElementsKindTransition(
5616             boilerplate_object->GetElementsKind(),
5617             transitioned_kind)) {
5618       JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5619     }
5620     FixedArray* object_array = FixedArray::cast(object->elements());
5621     object_array->set(store_index, *value);
5622   }
5623   return *object;
5624 }
5625
5626
5627 // Check whether debugger and is about to step into the callback that is passed
5628 // to a built-in function such as Array.forEach.
5629 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
5630   SealHandleScope shs(isolate);
5631 #ifdef ENABLE_DEBUGGER_SUPPORT
5632   if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
5633     return isolate->heap()->false_value();
5634   }
5635   CONVERT_ARG_CHECKED(Object, callback, 0);
5636   // We do not step into the callback if it's a builtin or not even a function.
5637   if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
5638     return isolate->heap()->false_value();
5639   }
5640   return isolate->heap()->true_value();
5641 #else
5642   return isolate->heap()->false_value();
5643 #endif  // ENABLE_DEBUGGER_SUPPORT
5644 }
5645
5646
5647 // Set one shot breakpoints for the callback function that is passed to a
5648 // built-in function such as Array.forEach to enable stepping into the callback.
5649 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
5650   SealHandleScope shs(isolate);
5651 #ifdef ENABLE_DEBUGGER_SUPPORT
5652   Debug* debug = isolate->debug();
5653   if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5654   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
5655   HandleScope scope(isolate);
5656   // When leaving the callback, step out has been activated, but not performed
5657   // if we do not leave the builtin.  To be able to step into the callback
5658   // again, we need to clear the step out at this point.
5659   debug->ClearStepOut();
5660   debug->FloodWithOneShot(callback);
5661 #endif  // ENABLE_DEBUGGER_SUPPORT
5662   return isolate->heap()->undefined_value();
5663 }
5664
5665
5666 // Set a local property, even if it is READ_ONLY.  If the property does not
5667 // exist, it will be added with attributes NONE.
5668 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
5669   HandleScope scope(isolate);
5670   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
5671   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5672   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5673   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5674   // Compute attributes.
5675   PropertyAttributes attributes = NONE;
5676   if (args.length() == 4) {
5677     CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
5678     // Only attribute bits should be set.
5679     RUNTIME_ASSERT(
5680         (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5681     attributes = static_cast<PropertyAttributes>(unchecked_value);
5682   }
5683   Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5684       object, name, value, attributes);
5685   RETURN_IF_EMPTY_HANDLE(isolate, result);
5686   return *result;
5687 }
5688
5689
5690 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
5691   HandleScope scope(isolate);
5692   ASSERT(args.length() == 3);
5693   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5694   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5695   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5696   JSReceiver::DeleteMode delete_mode = strict_mode == STRICT
5697       ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
5698   Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
5699   RETURN_IF_EMPTY_HANDLE(isolate, result);
5700   return *result;
5701 }
5702
5703
5704 static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
5705                                                    Handle<JSObject> object,
5706                                                    Handle<Name> key) {
5707   if (JSReceiver::HasLocalProperty(object, key)) {
5708     return isolate->heap()->true_value();
5709   }
5710   // Handle hidden prototypes.  If there's a hidden prototype above this thing
5711   // then we have to check it for properties, because they are supposed to
5712   // look like they are on this object.
5713   Handle<Object> proto(object->GetPrototype(), isolate);
5714   if (proto->IsJSObject() &&
5715       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
5716     return HasLocalPropertyImplementation(isolate,
5717                                           Handle<JSObject>::cast(proto),
5718                                           key);
5719   }
5720   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5721   return isolate->heap()->false_value();
5722 }
5723
5724
5725 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
5726   HandleScope scope(isolate);
5727   ASSERT(args.length() == 2);
5728   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5729   Handle<Object> object = args.at<Object>(0);
5730
5731   uint32_t index;
5732   const bool key_is_array_index = key->AsArrayIndex(&index);
5733
5734   // Only JS objects can have properties.
5735   if (object->IsJSObject()) {
5736     Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
5737     // Fast case: either the key is a real named property or it is not
5738     // an array index and there are no interceptors or hidden
5739     // prototypes.
5740     if (JSObject::HasRealNamedProperty(js_obj, key)) {
5741       ASSERT(!isolate->has_scheduled_exception());
5742       return isolate->heap()->true_value();
5743     } else {
5744       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5745     }
5746     Map* map = js_obj->map();
5747     if (!key_is_array_index &&
5748         !map->has_named_interceptor() &&
5749         !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5750       return isolate->heap()->false_value();
5751     }
5752     // Slow case.
5753     return HasLocalPropertyImplementation(isolate,
5754                                           Handle<JSObject>(js_obj),
5755                                           Handle<Name>(key));
5756   } else if (object->IsString() && key_is_array_index) {
5757     // Well, there is one exception:  Handle [] on strings.
5758     Handle<String> string = Handle<String>::cast(object);
5759     if (index < static_cast<uint32_t>(string->length())) {
5760       return isolate->heap()->true_value();
5761     }
5762   }
5763   return isolate->heap()->false_value();
5764 }
5765
5766
5767 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
5768   HandleScope scope(isolate);
5769   ASSERT(args.length() == 2);
5770   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5771   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5772
5773   bool result = JSReceiver::HasProperty(receiver, key);
5774   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5775   if (isolate->has_pending_exception()) return Failure::Exception();
5776   return isolate->heap()->ToBoolean(result);
5777 }
5778
5779
5780 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
5781   HandleScope scope(isolate);
5782   ASSERT(args.length() == 2);
5783   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5784   CONVERT_SMI_ARG_CHECKED(index, 1);
5785
5786   bool result = JSReceiver::HasElement(receiver, index);
5787   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5788   if (isolate->has_pending_exception()) return Failure::Exception();
5789   return isolate->heap()->ToBoolean(result);
5790 }
5791
5792
5793 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
5794   HandleScope scope(isolate);
5795   ASSERT(args.length() == 2);
5796
5797   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5798   CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5799
5800   PropertyAttributes att = JSReceiver::GetLocalPropertyAttribute(object, key);
5801   if (att == ABSENT || (att & DONT_ENUM) != 0) {
5802     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5803     return isolate->heap()->false_value();
5804   }
5805   ASSERT(!isolate->has_scheduled_exception());
5806   return isolate->heap()->true_value();
5807 }
5808
5809
5810 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
5811   HandleScope scope(isolate);
5812   ASSERT(args.length() == 1);
5813   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5814   bool threw = false;
5815   Handle<JSArray> result = GetKeysFor(object, &threw);
5816   if (threw) return Failure::Exception();
5817   return *result;
5818 }
5819
5820
5821 // Returns either a FixedArray as Runtime_GetPropertyNames,
5822 // or, if the given object has an enum cache that contains
5823 // all enumerable properties of the object and its prototypes
5824 // have none, the map of the object. This is used to speed up
5825 // the check for deletions during a for-in.
5826 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
5827   SealHandleScope shs(isolate);
5828   ASSERT(args.length() == 1);
5829
5830   CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5831
5832   if (raw_object->IsSimpleEnum()) return raw_object->map();
5833
5834   HandleScope scope(isolate);
5835   Handle<JSReceiver> object(raw_object);
5836   bool threw = false;
5837   Handle<FixedArray> content =
5838       GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
5839   if (threw) return Failure::Exception();
5840
5841   // Test again, since cache may have been built by preceding call.
5842   if (object->IsSimpleEnum()) return object->map();
5843
5844   return *content;
5845 }
5846
5847
5848 // Find the length of the prototype chain that is to to handled as one. If a
5849 // prototype object is hidden it is to be viewed as part of the the object it
5850 // is prototype for.
5851 static int LocalPrototypeChainLength(JSObject* obj) {
5852   int count = 1;
5853   Object* proto = obj->GetPrototype();
5854   while (proto->IsJSObject() &&
5855          JSObject::cast(proto)->map()->is_hidden_prototype()) {
5856     count++;
5857     proto = JSObject::cast(proto)->GetPrototype();
5858   }
5859   return count;
5860 }
5861
5862
5863 // Return the names of the local named properties.
5864 // args[0]: object
5865 // args[1]: PropertyAttributes as int
5866 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
5867   HandleScope scope(isolate);
5868   ASSERT(args.length() == 2);
5869   if (!args[0]->IsJSObject()) {
5870     return isolate->heap()->undefined_value();
5871   }
5872   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5873   CONVERT_SMI_ARG_CHECKED(filter_value, 1);
5874   PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
5875
5876   // Skip the global proxy as it has no properties and always delegates to the
5877   // real global object.
5878   if (obj->IsJSGlobalProxy()) {
5879     // Only collect names if access is permitted.
5880     if (obj->IsAccessCheckNeeded() &&
5881         !isolate->MayNamedAccessWrapper(obj,
5882                                         isolate->factory()->undefined_value(),
5883                                         v8::ACCESS_KEYS)) {
5884       isolate->ReportFailedAccessCheckWrapper(obj, v8::ACCESS_KEYS);
5885       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5886       return *isolate->factory()->NewJSArray(0);
5887     }
5888     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5889   }
5890
5891   // Find the number of objects making up this.
5892   int length = LocalPrototypeChainLength(*obj);
5893
5894   // Find the number of local properties for each of the objects.
5895   ScopedVector<int> local_property_count(length);
5896   int total_property_count = 0;
5897   Handle<JSObject> jsproto = obj;
5898   for (int i = 0; i < length; i++) {
5899     // Only collect names if access is permitted.
5900     if (jsproto->IsAccessCheckNeeded() &&
5901         !isolate->MayNamedAccessWrapper(jsproto,
5902                                         isolate->factory()->undefined_value(),
5903                                         v8::ACCESS_KEYS)) {
5904       isolate->ReportFailedAccessCheckWrapper(jsproto, v8::ACCESS_KEYS);
5905       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5906       return *isolate->factory()->NewJSArray(0);
5907     }
5908     int n;
5909     n = jsproto->NumberOfLocalProperties(filter);
5910     local_property_count[i] = n;
5911     total_property_count += n;
5912     if (i < length - 1) {
5913       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5914     }
5915   }
5916
5917   // Allocate an array with storage for all the property names.
5918   Handle<FixedArray> names =
5919       isolate->factory()->NewFixedArray(total_property_count);
5920
5921   // Get the property names.
5922   jsproto = obj;
5923   int next_copy_index = 0;
5924   int hidden_strings = 0;
5925   for (int i = 0; i < length; i++) {
5926     jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
5927     if (i > 0) {
5928       // Names from hidden prototypes may already have been added
5929       // for inherited function template instances. Count the duplicates
5930       // and stub them out; the final copy pass at the end ignores holes.
5931       for (int j = next_copy_index;
5932            j < next_copy_index + local_property_count[i];
5933            j++) {
5934         Object* name_from_hidden_proto = names->get(j);
5935         for (int k = 0; k < next_copy_index; k++) {
5936           if (names->get(k) != isolate->heap()->hidden_string()) {
5937             Object* name = names->get(k);
5938             if (name_from_hidden_proto == name) {
5939               names->set(j, isolate->heap()->hidden_string());
5940               hidden_strings++;
5941               break;
5942             }
5943           }
5944         }
5945       }
5946     }
5947     next_copy_index += local_property_count[i];
5948
5949     // Hidden properties only show up if the filter does not skip strings.
5950     if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
5951       hidden_strings++;
5952     }
5953     if (i < length - 1) {
5954       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5955     }
5956   }
5957
5958   // Filter out name of hidden properties object and
5959   // hidden prototype duplicates.
5960   if (hidden_strings > 0) {
5961     Handle<FixedArray> old_names = names;
5962     names = isolate->factory()->NewFixedArray(
5963         names->length() - hidden_strings);
5964     int dest_pos = 0;
5965     for (int i = 0; i < total_property_count; i++) {
5966       Object* name = old_names->get(i);
5967       if (name == isolate->heap()->hidden_string()) {
5968         hidden_strings--;
5969         continue;
5970       }
5971       names->set(dest_pos++, name);
5972     }
5973     ASSERT_EQ(0, hidden_strings);
5974   }
5975
5976   return *isolate->factory()->NewJSArrayWithElements(names);
5977 }
5978
5979
5980 // Return the names of the local indexed properties.
5981 // args[0]: object
5982 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5983   HandleScope scope(isolate);
5984   ASSERT(args.length() == 1);
5985   if (!args[0]->IsJSObject()) {
5986     return isolate->heap()->undefined_value();
5987   }
5988   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5989
5990   int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5991   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5992   obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5993   return *isolate->factory()->NewJSArrayWithElements(names);
5994 }
5995
5996
5997 // Return information on whether an object has a named or indexed interceptor.
5998 // args[0]: object
5999 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
6000   HandleScope scope(isolate);
6001   ASSERT(args.length() == 1);
6002   if (!args[0]->IsJSObject()) {
6003     return Smi::FromInt(0);
6004   }
6005   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
6006
6007   int result = 0;
6008   if (obj->HasNamedInterceptor()) result |= 2;
6009   if (obj->HasIndexedInterceptor()) result |= 1;
6010
6011   return Smi::FromInt(result);
6012 }
6013
6014
6015 // Return property names from named interceptor.
6016 // args[0]: object
6017 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
6018   HandleScope scope(isolate);
6019   ASSERT(args.length() == 1);
6020   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
6021
6022   if (obj->HasNamedInterceptor()) {
6023     v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
6024     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
6025   }
6026   return isolate->heap()->undefined_value();
6027 }
6028
6029
6030 // Return element names from indexed interceptor.
6031 // args[0]: object
6032 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
6033   HandleScope scope(isolate);
6034   ASSERT(args.length() == 1);
6035   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
6036
6037   if (obj->HasIndexedInterceptor()) {
6038     v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
6039     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
6040   }
6041   return isolate->heap()->undefined_value();
6042 }
6043
6044
6045 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
6046   HandleScope scope(isolate);
6047   ASSERT_EQ(args.length(), 1);
6048   CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
6049   Handle<JSObject> object(raw_object);
6050
6051   if (object->IsJSGlobalProxy()) {
6052     // Do access checks before going to the global object.
6053     if (object->IsAccessCheckNeeded() &&
6054         !isolate->MayNamedAccessWrapper(object,
6055                                         isolate->factory()->undefined_value(),
6056                                         v8::ACCESS_KEYS)) {
6057       isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
6058       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
6059       return *isolate->factory()->NewJSArray(0);
6060     }
6061
6062     Handle<Object> proto(object->GetPrototype(), isolate);
6063     // If proxy is detached we simply return an empty array.
6064     if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
6065     object = Handle<JSObject>::cast(proto);
6066   }
6067
6068   bool threw = false;
6069   Handle<FixedArray> contents =
6070       GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
6071   if (threw) return Failure::Exception();
6072
6073   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
6074   // property array and since the result is mutable we have to create
6075   // a fresh clone on each invocation.
6076   int length = contents->length();
6077   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
6078   for (int i = 0; i < length; i++) {
6079     Object* entry = contents->get(i);
6080     if (entry->IsString()) {
6081       copy->set(i, entry);
6082     } else {
6083       ASSERT(entry->IsNumber());
6084       HandleScope scope(isolate);
6085       Handle<Object> entry_handle(entry, isolate);
6086       Handle<Object> entry_str =
6087           isolate->factory()->NumberToString(entry_handle);
6088       copy->set(i, *entry_str);
6089     }
6090   }
6091   return *isolate->factory()->NewJSArrayWithElements(copy);
6092 }
6093
6094
6095 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
6096   SealHandleScope shs(isolate);
6097   ASSERT(args.length() == 1);
6098
6099   // Compute the frame holding the arguments.
6100   JavaScriptFrameIterator it(isolate);
6101   it.AdvanceToArgumentsFrame();
6102   JavaScriptFrame* frame = it.frame();
6103
6104   // Get the actual number of provided arguments.
6105   const uint32_t n = frame->ComputeParametersCount();
6106
6107   // Try to convert the key to an index. If successful and within
6108   // index return the the argument from the frame.
6109   uint32_t index;
6110   if (args[0]->ToArrayIndex(&index) && index < n) {
6111     return frame->GetParameter(index);
6112   }
6113
6114   if (args[0]->IsSymbol()) {
6115     // Lookup in the initial Object.prototype object.
6116     return isolate->initial_object_prototype()->GetProperty(
6117         Symbol::cast(args[0]));
6118   }
6119
6120   // Convert the key to a string.
6121   HandleScope scope(isolate);
6122   bool exception = false;
6123   Handle<Object> converted =
6124       Execution::ToString(isolate, args.at<Object>(0), &exception);
6125   if (exception) return Failure::Exception();
6126   Handle<String> key = Handle<String>::cast(converted);
6127
6128   // Try to convert the string key into an array index.
6129   if (key->AsArrayIndex(&index)) {
6130     if (index < n) {
6131       return frame->GetParameter(index);
6132     } else {
6133       Handle<Object> initial_prototype(isolate->initial_object_prototype());
6134       Handle<Object> result =
6135           Object::GetElement(isolate, initial_prototype, index);
6136       RETURN_IF_EMPTY_HANDLE(isolate, result);
6137       return *result;
6138     }
6139   }
6140
6141   // Handle special arguments properties.
6142   if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
6143   if (key->Equals(isolate->heap()->callee_string())) {
6144     JSFunction* function = frame->function();
6145     if (function->shared()->strict_mode() == STRICT) {
6146       return isolate->Throw(*isolate->factory()->NewTypeError(
6147           "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
6148     }
6149     return function;
6150   }
6151
6152   // Lookup in the initial Object.prototype object.
6153   return isolate->initial_object_prototype()->GetProperty(*key);
6154 }
6155
6156
6157 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
6158   HandleScope scope(isolate);
6159   ASSERT(args.length() == 1);
6160   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
6161   if (object->IsJSObject() && !object->IsGlobalObject()) {
6162     JSObject::TransformToFastProperties(Handle<JSObject>::cast(object), 0);
6163   }
6164   return *object;
6165 }
6166
6167
6168 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
6169   SealHandleScope shs(isolate);
6170   ASSERT(args.length() == 1);
6171
6172   return isolate->heap()->ToBoolean(args[0]->BooleanValue());
6173 }
6174
6175
6176 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
6177 // Possible optimizations: put the type string into the oddballs.
6178 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
6179   SealHandleScope shs(isolate);
6180
6181   Object* obj = args[0];
6182   if (obj->IsNumber()) return isolate->heap()->number_string();
6183   if (obj->IsFloat32x4()) return isolate->heap()->float32x4_string();
6184   if (obj->IsInt32x4()) return isolate->heap()->int32x4_string();
6185   HeapObject* heap_obj = HeapObject::cast(obj);
6186
6187   // typeof an undetectable object is 'undefined'
6188   if (heap_obj->map()->is_undetectable()) {
6189     return isolate->heap()->undefined_string();
6190   }
6191
6192   InstanceType instance_type = heap_obj->map()->instance_type();
6193   if (instance_type < FIRST_NONSTRING_TYPE) {
6194     return isolate->heap()->string_string();
6195   }
6196
6197   switch (instance_type) {
6198     case ODDBALL_TYPE:
6199       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
6200         return isolate->heap()->boolean_string();
6201       }
6202       if (heap_obj->IsNull()) {
6203         return FLAG_harmony_typeof
6204             ? isolate->heap()->null_string()
6205             : isolate->heap()->object_string();
6206       }
6207       ASSERT(heap_obj->IsUndefined());
6208       return isolate->heap()->undefined_string();
6209     case SYMBOL_TYPE:
6210       return isolate->heap()->symbol_string();
6211     case JS_FUNCTION_TYPE:
6212     case JS_FUNCTION_PROXY_TYPE:
6213       return isolate->heap()->function_string();
6214     default:
6215       // For any kind of object not handled above, the spec rule for
6216       // host objects gives that it is okay to return "object"
6217       return isolate->heap()->object_string();
6218   }
6219 }
6220
6221
6222 static bool AreDigits(const uint8_t*s, int from, int to) {
6223   for (int i = from; i < to; i++) {
6224     if (s[i] < '0' || s[i] > '9') return false;
6225   }
6226
6227   return true;
6228 }
6229
6230
6231 static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
6232   ASSERT(to - from < 10);  // Overflow is not possible.
6233   ASSERT(from < to);
6234   int d = s[from] - '0';
6235
6236   for (int i = from + 1; i < to; i++) {
6237     d = 10 * d + (s[i] - '0');
6238   }
6239
6240   return d;
6241 }
6242
6243
6244 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
6245   SealHandleScope shs(isolate);
6246   ASSERT(args.length() == 1);
6247   CONVERT_ARG_CHECKED(String, subject, 0);
6248   subject->TryFlatten();
6249
6250   // Fast case: short integer or some sorts of junk values.
6251   int len = subject->length();
6252   if (subject->IsSeqOneByteString()) {
6253     if (len == 0) return Smi::FromInt(0);
6254
6255     uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
6256     bool minus = (data[0] == '-');
6257     int start_pos = (minus ? 1 : 0);
6258
6259     if (start_pos == len) {
6260       return isolate->heap()->nan_value();
6261     } else if (data[start_pos] > '9') {
6262       // Fast check for a junk value. A valid string may start from a
6263       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
6264       // the 'I' character ('Infinity'). All of that have codes not greater than
6265       // '9' except 'I' and &nbsp;.
6266       if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
6267         return isolate->heap()->nan_value();
6268       }
6269     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
6270       // The maximal/minimal smi has 10 digits. If the string has less digits we
6271       // know it will fit into the smi-data type.
6272       int d = ParseDecimalInteger(data, start_pos, len);
6273       if (minus) {
6274         if (d == 0) return isolate->heap()->minus_zero_value();
6275         d = -d;
6276       } else if (!subject->HasHashCode() &&
6277                  len <= String::kMaxArrayIndexSize &&
6278                  (len == 1 || data[0] != '0')) {
6279         // String hash is not calculated yet but all the data are present.
6280         // Update the hash field to speed up sequential convertions.
6281         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
6282 #ifdef DEBUG
6283         subject->Hash();  // Force hash calculation.
6284         ASSERT_EQ(static_cast<int>(subject->hash_field()),
6285                   static_cast<int>(hash));
6286 #endif
6287         subject->set_hash_field(hash);
6288       }
6289       return Smi::FromInt(d);
6290     }
6291   }
6292
6293   // Slower case.
6294   int flags = ALLOW_HEX;
6295   if (FLAG_harmony_numeric_literals) {
6296     // The current spec draft has not updated "ToNumber Applied to the String
6297     // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6298     flags |= ALLOW_OCTAL | ALLOW_BINARY;
6299   }
6300   return isolate->heap()->NumberFromDouble(
6301       StringToDouble(isolate->unicode_cache(), subject, flags));
6302 }
6303
6304
6305 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
6306   SealHandleScope shs(isolate);
6307   CONVERT_SMI_ARG_CHECKED(length, 0);
6308   CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6309   if (length == 0) return isolate->heap()->empty_string();
6310   if (is_one_byte) {
6311     return isolate->heap()->AllocateRawOneByteString(length);
6312   } else {
6313     return isolate->heap()->AllocateRawTwoByteString(length);
6314   }
6315 }
6316
6317
6318 RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
6319   HandleScope scope(isolate);
6320   CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
6321   CONVERT_SMI_ARG_CHECKED(new_length, 1);
6322   return *SeqString::Truncate(string, new_length);
6323 }
6324
6325
6326 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
6327   HandleScope scope(isolate);
6328   ASSERT(args.length() == 1);
6329   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6330   Handle<String> string = FlattenGetString(source);
6331   ASSERT(string->IsFlat());
6332   Handle<String> result = string->IsOneByteRepresentationUnderneath()
6333       ? URIEscape::Escape<uint8_t>(isolate, source)
6334       : URIEscape::Escape<uc16>(isolate, source);
6335   RETURN_IF_EMPTY_HANDLE(isolate, result);
6336   return *result;
6337 }
6338
6339
6340 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
6341   HandleScope scope(isolate);
6342   ASSERT(args.length() == 1);
6343   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6344   Handle<String> string = FlattenGetString(source);
6345   ASSERT(string->IsFlat());
6346   return string->IsOneByteRepresentationUnderneath()
6347       ? *URIUnescape::Unescape<uint8_t>(isolate, source)
6348       : *URIUnescape::Unescape<uc16>(isolate, source);
6349 }
6350
6351
6352 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
6353   HandleScope scope(isolate);
6354   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6355   ASSERT(args.length() == 1);
6356   return BasicJsonStringifier::StringifyString(isolate, string);
6357 }
6358
6359
6360 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
6361   HandleScope scope(isolate);
6362   ASSERT(args.length() == 1);
6363   BasicJsonStringifier stringifier(isolate);
6364   return stringifier.Stringify(Handle<Object>(args[0], isolate));
6365 }
6366
6367
6368 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
6369   SealHandleScope shs(isolate);
6370
6371   CONVERT_ARG_CHECKED(String, s, 0);
6372   CONVERT_SMI_ARG_CHECKED(radix, 1);
6373
6374   s->TryFlatten();
6375
6376   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6377   double value = StringToInt(isolate->unicode_cache(), s, radix);
6378   return isolate->heap()->NumberFromDouble(value);
6379 }
6380
6381
6382 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6383   SealHandleScope shs(isolate);
6384   CONVERT_ARG_CHECKED(String, str, 0);
6385
6386   // ECMA-262 section 15.1.2.3, empty string is NaN
6387   double value = StringToDouble(isolate->unicode_cache(),
6388                                 str, ALLOW_TRAILING_JUNK, OS::nan_value());
6389
6390   // Create a number object from the value.
6391   return isolate->heap()->NumberFromDouble(value);
6392 }
6393
6394
6395 static inline bool ToUpperOverflows(uc32 character) {
6396   // y with umlauts and the micro sign are the only characters that stop
6397   // fitting into one-byte when converting to uppercase.
6398   static const uc32 yuml_code = 0xff;
6399   static const uc32 micro_code = 0xb5;
6400   return (character == yuml_code || character == micro_code);
6401 }
6402
6403
6404 template <class Converter>
6405 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6406     Isolate* isolate,
6407     String* string,
6408     SeqString* result,
6409     int result_length,
6410     unibrow::Mapping<Converter, 128>* mapping) {
6411   DisallowHeapAllocation no_gc;
6412   // We try this twice, once with the assumption that the result is no longer
6413   // than the input and, if that assumption breaks, again with the exact
6414   // length.  This may not be pretty, but it is nicer than what was here before
6415   // and I hereby claim my vaffel-is.
6416   //
6417   // NOTE: This assumes that the upper/lower case of an ASCII
6418   // character is also ASCII.  This is currently the case, but it
6419   // might break in the future if we implement more context and locale
6420   // dependent upper/lower conversions.
6421   bool has_changed_character = false;
6422
6423   // Convert all characters to upper case, assuming that they will fit
6424   // in the buffer
6425   Access<ConsStringIteratorOp> op(
6426       isolate->runtime_state()->string_iterator());
6427   StringCharacterStream stream(string, op.value());
6428   unibrow::uchar chars[Converter::kMaxWidth];
6429   // We can assume that the string is not empty
6430   uc32 current = stream.GetNext();
6431   bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
6432   for (int i = 0; i < result_length;) {
6433     bool has_next = stream.HasMore();
6434     uc32 next = has_next ? stream.GetNext() : 0;
6435     int char_length = mapping->get(current, next, chars);
6436     if (char_length == 0) {
6437       // The case conversion of this character is the character itself.
6438       result->Set(i, current);
6439       i++;
6440     } else if (char_length == 1 &&
6441                (ignore_overflow || !ToUpperOverflows(current))) {
6442       // Common case: converting the letter resulted in one character.
6443       ASSERT(static_cast<uc32>(chars[0]) != current);
6444       result->Set(i, chars[0]);
6445       has_changed_character = true;
6446       i++;
6447     } else if (result_length == string->length()) {
6448       bool overflows = ToUpperOverflows(current);
6449       // We've assumed that the result would be as long as the
6450       // input but here is a character that converts to several
6451       // characters.  No matter, we calculate the exact length
6452       // of the result and try the whole thing again.
6453       //
6454       // Note that this leaves room for optimization.  We could just
6455       // memcpy what we already have to the result string.  Also,
6456       // the result string is the last object allocated we could
6457       // "realloc" it and probably, in the vast majority of cases,
6458       // extend the existing string to be able to hold the full
6459       // result.
6460       int next_length = 0;
6461       if (has_next) {
6462         next_length = mapping->get(next, 0, chars);
6463         if (next_length == 0) next_length = 1;
6464       }
6465       int current_length = i + char_length + next_length;
6466       while (stream.HasMore()) {
6467         current = stream.GetNext();
6468         overflows |= ToUpperOverflows(current);
6469         // NOTE: we use 0 as the next character here because, while
6470         // the next character may affect what a character converts to,
6471         // it does not in any case affect the length of what it convert
6472         // to.
6473         int char_length = mapping->get(current, 0, chars);
6474         if (char_length == 0) char_length = 1;
6475         current_length += char_length;
6476         if (current_length > String::kMaxLength) {
6477           AllowHeapAllocation allocate_error_and_return;
6478           return isolate->ThrowInvalidStringLength();
6479         }
6480       }
6481       // Try again with the real length.  Return signed if we need
6482       // to allocate a two-byte string for to uppercase.
6483       return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
6484                                              : Smi::FromInt(current_length);
6485     } else {
6486       for (int j = 0; j < char_length; j++) {
6487         result->Set(i, chars[j]);
6488         i++;
6489       }
6490       has_changed_character = true;
6491     }
6492     current = next;
6493   }
6494   if (has_changed_character) {
6495     return result;
6496   } else {
6497     // If we didn't actually change anything in doing the conversion
6498     // we simple return the result and let the converted string
6499     // become garbage; there is no reason to keep two identical strings
6500     // alive.
6501     return string;
6502   }
6503 }
6504
6505
6506 namespace {
6507
6508 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6509 static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6510
6511 // Given a word and two range boundaries returns a word with high bit
6512 // set in every byte iff the corresponding input byte was strictly in
6513 // the range (m, n). All the other bits in the result are cleared.
6514 // This function is only useful when it can be inlined and the
6515 // boundaries are statically known.
6516 // Requires: all bytes in the input word and the boundaries must be
6517 // ASCII (less than 0x7F).
6518 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6519   // Use strict inequalities since in edge cases the function could be
6520   // further simplified.
6521   ASSERT(0 < m && m < n);
6522   // Has high bit set in every w byte less than n.
6523   uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6524   // Has high bit set in every w byte greater than m.
6525   uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6526   return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6527 }
6528
6529
6530 #ifdef DEBUG
6531 static bool CheckFastAsciiConvert(char* dst,
6532                                   const char* src,
6533                                   int length,
6534                                   bool changed,
6535                                   bool is_to_lower) {
6536   bool expected_changed = false;
6537   for (int i = 0; i < length; i++) {
6538     if (dst[i] == src[i]) continue;
6539     expected_changed = true;
6540     if (is_to_lower) {
6541       ASSERT('A' <= src[i] && src[i] <= 'Z');
6542       ASSERT(dst[i] == src[i] + ('a' - 'A'));
6543     } else {
6544       ASSERT('a' <= src[i] && src[i] <= 'z');
6545       ASSERT(dst[i] == src[i] - ('a' - 'A'));
6546     }
6547   }
6548   return (expected_changed == changed);
6549 }
6550 #endif
6551
6552
6553 template<class Converter>
6554 static bool FastAsciiConvert(char* dst,
6555                              const char* src,
6556                              int length,
6557                              bool* changed_out) {
6558 #ifdef DEBUG
6559     char* saved_dst = dst;
6560     const char* saved_src = src;
6561 #endif
6562   DisallowHeapAllocation no_gc;
6563   // We rely on the distance between upper and lower case letters
6564   // being a known power of 2.
6565   ASSERT('a' - 'A' == (1 << 5));
6566   // Boundaries for the range of input characters than require conversion.
6567   static const char lo = Converter::kIsToLower ? 'A' - 1 : 'a' - 1;
6568   static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
6569   bool changed = false;
6570   uintptr_t or_acc = 0;
6571   const char* const limit = src + length;
6572 #ifdef V8_HOST_CAN_READ_UNALIGNED
6573   // Process the prefix of the input that requires no conversion one
6574   // (machine) word at a time.
6575   while (src <= limit - sizeof(uintptr_t)) {
6576     const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6577     or_acc |= w;
6578     if (AsciiRangeMask(w, lo, hi) != 0) {
6579       changed = true;
6580       break;
6581     }
6582     *reinterpret_cast<uintptr_t*>(dst) = w;
6583     src += sizeof(uintptr_t);
6584     dst += sizeof(uintptr_t);
6585   }
6586   // Process the remainder of the input performing conversion when
6587   // required one word at a time.
6588   while (src <= limit - sizeof(uintptr_t)) {
6589     const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6590     or_acc |= w;
6591     uintptr_t m = AsciiRangeMask(w, lo, hi);
6592     // The mask has high (7th) bit set in every byte that needs
6593     // conversion and we know that the distance between cases is
6594     // 1 << 5.
6595     *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6596     src += sizeof(uintptr_t);
6597     dst += sizeof(uintptr_t);
6598   }
6599 #endif
6600   // Process the last few bytes of the input (or the whole input if
6601   // unaligned access is not supported).
6602   while (src < limit) {
6603     char c = *src;
6604     or_acc |= c;
6605     if (lo < c && c < hi) {
6606       c ^= (1 << 5);
6607       changed = true;
6608     }
6609     *dst = c;
6610     ++src;
6611     ++dst;
6612   }
6613   if ((or_acc & kAsciiMask) != 0) {
6614     return false;
6615   }
6616
6617   ASSERT(CheckFastAsciiConvert(
6618              saved_dst, saved_src, length, changed, Converter::kIsToLower));
6619
6620   *changed_out = changed;
6621   return true;
6622 }
6623
6624 }  // namespace
6625
6626
6627 template <class Converter>
6628 MUST_USE_RESULT static MaybeObject* ConvertCase(
6629     Arguments args,
6630     Isolate* isolate,
6631     unibrow::Mapping<Converter, 128>* mapping) {
6632   HandleScope handle_scope(isolate);
6633   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6634   s = FlattenGetString(s);
6635   int length = s->length();
6636   // Assume that the string is not empty; we need this assumption later
6637   if (length == 0) return *s;
6638
6639   // Simpler handling of ASCII strings.
6640   //
6641   // NOTE: This assumes that the upper/lower case of an ASCII
6642   // character is also ASCII.  This is currently the case, but it
6643   // might break in the future if we implement more context and locale
6644   // dependent upper/lower conversions.
6645   if (s->IsOneByteRepresentationUnderneath()) {
6646     Handle<SeqOneByteString> result =
6647         isolate->factory()->NewRawOneByteString(length);
6648     ASSERT(!result.is_null());  // Same length as input.
6649     DisallowHeapAllocation no_gc;
6650     String::FlatContent flat_content = s->GetFlatContent();
6651     ASSERT(flat_content.IsFlat());
6652     bool has_changed_character = false;
6653     bool is_ascii = FastAsciiConvert<Converter>(
6654         reinterpret_cast<char*>(result->GetChars()),
6655         reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
6656         length,
6657         &has_changed_character);
6658     // If not ASCII, we discard the result and take the 2 byte path.
6659     if (is_ascii)  return has_changed_character ? *result : *s;
6660   }
6661
6662   Handle<SeqString> result;
6663   if (s->IsOneByteRepresentation()) {
6664     result = isolate->factory()->NewRawOneByteString(length);
6665   } else {
6666     result = isolate->factory()->NewRawTwoByteString(length);
6667   }
6668   ASSERT(!result.is_null());  // Same length as input.
6669
6670   MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping);
6671   Object* answer;
6672   if (!maybe->ToObject(&answer)) return maybe;
6673   if (answer->IsString()) return answer;
6674
6675   ASSERT(answer->IsSmi());
6676   length = Smi::cast(answer)->value();
6677   if (s->IsOneByteRepresentation() && length > 0) {
6678     result = isolate->factory()->NewRawOneByteString(length);
6679   } else {
6680     if (length < 0) length = -length;
6681     result = isolate->factory()->NewRawTwoByteString(length);
6682   }
6683   RETURN_IF_EMPTY_HANDLE(isolate, result);
6684   return ConvertCaseHelper(isolate, *s, *result, length, mapping);
6685 }
6686
6687
6688 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6689   return ConvertCase(
6690       args, isolate, isolate->runtime_state()->to_lower_mapping());
6691 }
6692
6693
6694 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6695   return ConvertCase(
6696       args, isolate, isolate->runtime_state()->to_upper_mapping());
6697 }
6698
6699
6700 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6701   HandleScope scope(isolate);
6702   ASSERT(args.length() == 3);
6703
6704   CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6705   CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6706   CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6707
6708   string = FlattenGetString(string);
6709   int length = string->length();
6710
6711   int left = 0;
6712   UnicodeCache* unicode_cache = isolate->unicode_cache();
6713   if (trimLeft) {
6714     while (left < length &&
6715            unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
6716       left++;
6717     }
6718   }
6719
6720   int right = length;
6721   if (trimRight) {
6722     while (right > left &&
6723            unicode_cache->IsWhiteSpaceOrLineTerminator(
6724                string->Get(right - 1))) {
6725       right--;
6726     }
6727   }
6728
6729   return *isolate->factory()->NewSubString(string, left, right);
6730 }
6731
6732
6733 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6734   HandleScope handle_scope(isolate);
6735   ASSERT(args.length() == 3);
6736   CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6737   CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6738   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6739
6740   int subject_length = subject->length();
6741   int pattern_length = pattern->length();
6742   RUNTIME_ASSERT(pattern_length > 0);
6743
6744   if (limit == 0xffffffffu) {
6745     Handle<Object> cached_answer(
6746         RegExpResultsCache::Lookup(isolate->heap(),
6747                                    *subject,
6748                                    *pattern,
6749                                    RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
6750         isolate);
6751     if (*cached_answer != Smi::FromInt(0)) {
6752       // The cache FixedArray is a COW-array and can therefore be reused.
6753       Handle<JSArray> result =
6754           isolate->factory()->NewJSArrayWithElements(
6755               Handle<FixedArray>::cast(cached_answer));
6756       return *result;
6757     }
6758   }
6759
6760   // The limit can be very large (0xffffffffu), but since the pattern
6761   // isn't empty, we can never create more parts than ~half the length
6762   // of the subject.
6763
6764   if (!subject->IsFlat()) FlattenString(subject);
6765
6766   static const int kMaxInitialListCapacity = 16;
6767
6768   ZoneScope zone_scope(isolate->runtime_zone());
6769
6770   // Find (up to limit) indices of separator and end-of-string in subject
6771   int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6772   ZoneList<int> indices(initial_capacity, zone_scope.zone());
6773   if (!pattern->IsFlat()) FlattenString(pattern);
6774
6775   FindStringIndicesDispatch(isolate, *subject, *pattern,
6776                             &indices, limit, zone_scope.zone());
6777
6778   if (static_cast<uint32_t>(indices.length()) < limit) {
6779     indices.Add(subject_length, zone_scope.zone());
6780   }
6781
6782   // The list indices now contains the end of each part to create.
6783
6784   // Create JSArray of substrings separated by separator.
6785   int part_count = indices.length();
6786
6787   Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6788   JSObject::EnsureCanContainHeapObjectElements(result);
6789   result->set_length(Smi::FromInt(part_count));
6790
6791   ASSERT(result->HasFastObjectElements());
6792
6793   if (part_count == 1 && indices.at(0) == subject_length) {
6794     FixedArray::cast(result->elements())->set(0, *subject);
6795     return *result;
6796   }
6797
6798   Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6799   int part_start = 0;
6800   for (int i = 0; i < part_count; i++) {
6801     HandleScope local_loop_handle(isolate);
6802     int part_end = indices.at(i);
6803     Handle<String> substring =
6804         isolate->factory()->NewProperSubString(subject, part_start, part_end);
6805     elements->set(i, *substring);
6806     part_start = part_end + pattern_length;
6807   }
6808
6809   if (limit == 0xffffffffu) {
6810     if (result->HasFastObjectElements()) {
6811       RegExpResultsCache::Enter(isolate->heap(),
6812                                 *subject,
6813                                 *pattern,
6814                                 *elements,
6815                                 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
6816     }
6817   }
6818
6819   return *result;
6820 }
6821
6822
6823 // Copies ASCII characters to the given fixed array looking up
6824 // one-char strings in the cache. Gives up on the first char that is
6825 // not in the cache and fills the remainder with smi zeros. Returns
6826 // the length of the successfully copied prefix.
6827 static int CopyCachedAsciiCharsToArray(Heap* heap,
6828                                        const uint8_t* chars,
6829                                        FixedArray* elements,
6830                                        int length) {
6831   DisallowHeapAllocation no_gc;
6832   FixedArray* ascii_cache = heap->single_character_string_cache();
6833   Object* undefined = heap->undefined_value();
6834   int i;
6835   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6836   for (i = 0; i < length; ++i) {
6837     Object* value = ascii_cache->get(chars[i]);
6838     if (value == undefined) break;
6839     elements->set(i, value, mode);
6840   }
6841   if (i < length) {
6842     ASSERT(Smi::FromInt(0) == 0);
6843     memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6844   }
6845 #ifdef DEBUG
6846   for (int j = 0; j < length; ++j) {
6847     Object* element = elements->get(j);
6848     ASSERT(element == Smi::FromInt(0) ||
6849            (element->IsString() && String::cast(element)->LooksValid()));
6850   }
6851 #endif
6852   return i;
6853 }
6854
6855
6856 // Converts a String to JSArray.
6857 // For example, "foo" => ["f", "o", "o"].
6858 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6859   HandleScope scope(isolate);
6860   ASSERT(args.length() == 2);
6861   CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6862   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6863
6864   s = FlattenGetString(s);
6865   const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6866
6867   Handle<FixedArray> elements;
6868   int position = 0;
6869   if (s->IsFlat() && s->IsOneByteRepresentation()) {
6870     // Try using cached chars where possible.
6871     Object* obj;
6872     { MaybeObject* maybe_obj =
6873           isolate->heap()->AllocateUninitializedFixedArray(length);
6874       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6875     }
6876     elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6877     DisallowHeapAllocation no_gc;
6878     String::FlatContent content = s->GetFlatContent();
6879     if (content.IsAscii()) {
6880       Vector<const uint8_t> chars = content.ToOneByteVector();
6881       // Note, this will initialize all elements (not only the prefix)
6882       // to prevent GC from seeing partially initialized array.
6883       position = CopyCachedAsciiCharsToArray(isolate->heap(),
6884                                              chars.start(),
6885                                              *elements,
6886                                              length);
6887     } else {
6888       MemsetPointer(elements->data_start(),
6889                     isolate->heap()->undefined_value(),
6890                     length);
6891     }
6892   } else {
6893     elements = isolate->factory()->NewFixedArray(length);
6894   }
6895   for (int i = position; i < length; ++i) {
6896     Handle<Object> str =
6897         LookupSingleCharacterStringFromCode(isolate, s->Get(i));
6898     elements->set(i, *str);
6899   }
6900
6901 #ifdef DEBUG
6902   for (int i = 0; i < length; ++i) {
6903     ASSERT(String::cast(elements->get(i))->length() == 1);
6904   }
6905 #endif
6906
6907   return *isolate->factory()->NewJSArrayWithElements(elements);
6908 }
6909
6910
6911 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6912   SealHandleScope shs(isolate);
6913   ASSERT(args.length() == 1);
6914   CONVERT_ARG_CHECKED(String, value, 0);
6915   return value->ToObject(isolate);
6916 }
6917
6918
6919 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6920   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6921   int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6922   return char_length == 0;
6923 }
6924
6925
6926 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToString) {
6927   SealHandleScope shs(isolate);
6928   ASSERT(args.length() == 1);
6929
6930   Object* number = args[0];
6931   RUNTIME_ASSERT(number->IsNumber());
6932
6933   return isolate->heap()->NumberToString(number);
6934 }
6935
6936
6937 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToStringSkipCache) {
6938   SealHandleScope shs(isolate);
6939   ASSERT(args.length() == 1);
6940
6941   Object* number = args[0];
6942   RUNTIME_ASSERT(number->IsNumber());
6943
6944   return isolate->heap()->NumberToString(number, false);
6945 }
6946
6947
6948 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6949   SealHandleScope shs(isolate);
6950   ASSERT(args.length() == 1);
6951
6952   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6953
6954   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6955   if (number > 0 && number <= Smi::kMaxValue) {
6956     return Smi::FromInt(static_cast<int>(number));
6957   }
6958   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6959 }
6960
6961
6962 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6963   SealHandleScope shs(isolate);
6964   ASSERT(args.length() == 1);
6965
6966   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6967
6968   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6969   if (number > 0 && number <= Smi::kMaxValue) {
6970     return Smi::FromInt(static_cast<int>(number));
6971   }
6972
6973   double double_value = DoubleToInteger(number);
6974   // Map both -0 and +0 to +0.
6975   if (double_value == 0) double_value = 0;
6976
6977   return isolate->heap()->NumberFromDouble(double_value);
6978 }
6979
6980
6981 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6982   SealHandleScope shs(isolate);
6983   ASSERT(args.length() == 1);
6984
6985   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6986   return isolate->heap()->NumberFromUint32(number);
6987 }
6988
6989
6990 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6991   SealHandleScope shs(isolate);
6992   ASSERT(args.length() == 1);
6993
6994   CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6995
6996   // We do not include 0 so that we don't have to treat +0 / -0 cases.
6997   if (number > 0 && number <= Smi::kMaxValue) {
6998     return Smi::FromInt(static_cast<int>(number));
6999   }
7000   return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
7001 }
7002
7003
7004 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
7005 // a small integer.
7006 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToSmi) {
7007   SealHandleScope shs(isolate);
7008   ASSERT(args.length() == 1);
7009
7010   Object* obj = args[0];
7011   if (obj->IsSmi()) {
7012     return obj;
7013   }
7014   if (obj->IsHeapNumber()) {
7015     double value = HeapNumber::cast(obj)->value();
7016     int int_value = FastD2I(value);
7017     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
7018       return Smi::FromInt(int_value);
7019     }
7020   }
7021   return isolate->heap()->nan_value();
7022 }
7023
7024
7025 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateHeapNumber) {
7026   SealHandleScope shs(isolate);
7027   ASSERT(args.length() == 0);
7028   return isolate->heap()->AllocateHeapNumber(0);
7029 }
7030
7031
7032 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateFloat32x4) {
7033   SealHandleScope shs(isolate);
7034   ASSERT(args.length() == 0);
7035
7036   float32x4_value_t zero = {{0, 0, 0, 0}};
7037   return isolate->heap()->AllocateFloat32x4(zero);
7038 }
7039
7040
7041 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInt32x4) {
7042   SealHandleScope shs(isolate);
7043   ASSERT(args.length() == 0);
7044
7045   int32x4_value_t zero = {{0, 0, 0, 0}};
7046   return isolate->heap()->AllocateInt32x4(zero);
7047 }
7048
7049
7050 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
7051   SealHandleScope shs(isolate);
7052   ASSERT(args.length() == 2);
7053
7054   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7055   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7056   return isolate->heap()->NumberFromDouble(x + y);
7057 }
7058
7059
7060 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
7061   SealHandleScope shs(isolate);
7062   ASSERT(args.length() == 2);
7063
7064   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7065   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7066   return isolate->heap()->NumberFromDouble(x - y);
7067 }
7068
7069
7070 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
7071   SealHandleScope shs(isolate);
7072   ASSERT(args.length() == 2);
7073
7074   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7075   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7076   return isolate->heap()->NumberFromDouble(x * y);
7077 }
7078
7079
7080 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
7081   SealHandleScope shs(isolate);
7082   ASSERT(args.length() == 1);
7083
7084   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7085   return isolate->heap()->NumberFromDouble(-x);
7086 }
7087
7088
7089 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
7090   SealHandleScope shs(isolate);
7091   ASSERT(args.length() == 0);
7092
7093   return isolate->heap()->NumberFromDouble(9876543210.0);
7094 }
7095
7096
7097 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
7098   SealHandleScope shs(isolate);
7099   ASSERT(args.length() == 2);
7100
7101   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7102   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7103   return isolate->heap()->NumberFromDouble(x / y);
7104 }
7105
7106
7107 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
7108   SealHandleScope shs(isolate);
7109   ASSERT(args.length() == 2);
7110
7111   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7112   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7113
7114   x = modulo(x, y);
7115   // NumberFromDouble may return a Smi instead of a Number object
7116   return isolate->heap()->NumberFromDouble(x);
7117 }
7118
7119
7120 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
7121   SealHandleScope shs(isolate);
7122   ASSERT(args.length() == 2);
7123
7124   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7125   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7126   return isolate->heap()->NumberFromInt32(x * y);
7127 }
7128
7129
7130 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringAdd) {
7131   HandleScope scope(isolate);
7132   ASSERT(args.length() == 2);
7133   CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
7134   CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
7135   isolate->counters()->string_add_runtime()->Increment();
7136   Handle<String> result = isolate->factory()->NewConsString(str1, str2);
7137   RETURN_IF_EMPTY_HANDLE(isolate, result);
7138   return *result;
7139 }
7140
7141
7142 template <typename sinkchar>
7143 static inline void StringBuilderConcatHelper(String* special,
7144                                              sinkchar* sink,
7145                                              FixedArray* fixed_array,
7146                                              int array_length) {
7147   int position = 0;
7148   for (int i = 0; i < array_length; i++) {
7149     Object* element = fixed_array->get(i);
7150     if (element->IsSmi()) {
7151       // Smi encoding of position and length.
7152       int encoded_slice = Smi::cast(element)->value();
7153       int pos;
7154       int len;
7155       if (encoded_slice > 0) {
7156         // Position and length encoded in one smi.
7157         pos = StringBuilderSubstringPosition::decode(encoded_slice);
7158         len = StringBuilderSubstringLength::decode(encoded_slice);
7159       } else {
7160         // Position and length encoded in two smis.
7161         Object* obj = fixed_array->get(++i);
7162         ASSERT(obj->IsSmi());
7163         pos = Smi::cast(obj)->value();
7164         len = -encoded_slice;
7165       }
7166       String::WriteToFlat(special,
7167                           sink + position,
7168                           pos,
7169                           pos + len);
7170       position += len;
7171     } else {
7172       String* string = String::cast(element);
7173       int element_length = string->length();
7174       String::WriteToFlat(string, sink + position, 0, element_length);
7175       position += element_length;
7176     }
7177   }
7178 }
7179
7180
7181 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
7182   HandleScope scope(isolate);
7183   ASSERT(args.length() == 3);
7184   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7185   if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
7186   int array_length = args.smi_at(1);
7187   CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
7188
7189   // This assumption is used by the slice encoding in one or two smis.
7190   ASSERT(Smi::kMaxValue >= String::kMaxLength);
7191
7192   JSObject::EnsureCanContainHeapObjectElements(array);
7193
7194   int special_length = special->length();
7195   if (!array->HasFastObjectElements()) {
7196     return isolate->Throw(isolate->heap()->illegal_argument_string());
7197   }
7198   FixedArray* fixed_array = FixedArray::cast(array->elements());
7199   if (fixed_array->length() < array_length) {
7200     array_length = fixed_array->length();
7201   }
7202
7203   if (array_length == 0) {
7204     return isolate->heap()->empty_string();
7205   } else if (array_length == 1) {
7206     Object* first = fixed_array->get(0);
7207     if (first->IsString()) return first;
7208   }
7209
7210   bool one_byte = special->HasOnlyOneByteChars();
7211   int position = 0;
7212   for (int i = 0; i < array_length; i++) {
7213     int increment = 0;
7214     Object* elt = fixed_array->get(i);
7215     if (elt->IsSmi()) {
7216       // Smi encoding of position and length.
7217       int smi_value = Smi::cast(elt)->value();
7218       int pos;
7219       int len;
7220       if (smi_value > 0) {
7221         // Position and length encoded in one smi.
7222         pos = StringBuilderSubstringPosition::decode(smi_value);
7223         len = StringBuilderSubstringLength::decode(smi_value);
7224       } else {
7225         // Position and length encoded in two smis.
7226         len = -smi_value;
7227         // Get the position and check that it is a positive smi.
7228         i++;
7229         if (i >= array_length) {
7230           return isolate->Throw(isolate->heap()->illegal_argument_string());
7231         }
7232         Object* next_smi = fixed_array->get(i);
7233         if (!next_smi->IsSmi()) {
7234           return isolate->Throw(isolate->heap()->illegal_argument_string());
7235         }
7236         pos = Smi::cast(next_smi)->value();
7237         if (pos < 0) {
7238           return isolate->Throw(isolate->heap()->illegal_argument_string());
7239         }
7240       }
7241       ASSERT(pos >= 0);
7242       ASSERT(len >= 0);
7243       if (pos > special_length || len > special_length - pos) {
7244         return isolate->Throw(isolate->heap()->illegal_argument_string());
7245       }
7246       increment = len;
7247     } else if (elt->IsString()) {
7248       String* element = String::cast(elt);
7249       int element_length = element->length();
7250       increment = element_length;
7251       if (one_byte && !element->HasOnlyOneByteChars()) {
7252         one_byte = false;
7253       }
7254     } else {
7255       ASSERT(!elt->IsTheHole());
7256       return isolate->Throw(isolate->heap()->illegal_argument_string());
7257     }
7258     if (increment > String::kMaxLength - position) {
7259       return isolate->ThrowInvalidStringLength();
7260     }
7261     position += increment;
7262   }
7263
7264   int length = position;
7265   Object* object;
7266
7267   if (one_byte) {
7268     { MaybeObject* maybe_object =
7269           isolate->heap()->AllocateRawOneByteString(length);
7270       if (!maybe_object->ToObject(&object)) return maybe_object;
7271     }
7272     SeqOneByteString* answer = SeqOneByteString::cast(object);
7273     StringBuilderConcatHelper(*special,
7274                               answer->GetChars(),
7275                               fixed_array,
7276                               array_length);
7277     return answer;
7278   } else {
7279     { MaybeObject* maybe_object =
7280           isolate->heap()->AllocateRawTwoByteString(length);
7281       if (!maybe_object->ToObject(&object)) return maybe_object;
7282     }
7283     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7284     StringBuilderConcatHelper(*special,
7285                               answer->GetChars(),
7286                               fixed_array,
7287                               array_length);
7288     return answer;
7289   }
7290 }
7291
7292
7293 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
7294   HandleScope scope(isolate);
7295   ASSERT(args.length() == 3);
7296   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7297   if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
7298   int array_length = args.smi_at(1);
7299   CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
7300   RUNTIME_ASSERT(array->HasFastObjectElements());
7301
7302   Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
7303   if (fixed_array->length() < array_length) {
7304     array_length = fixed_array->length();
7305   }
7306
7307   if (array_length == 0) {
7308     return isolate->heap()->empty_string();
7309   } else if (array_length == 1) {
7310     Object* first = fixed_array->get(0);
7311     RUNTIME_ASSERT(first->IsString());
7312     return first;
7313   }
7314
7315   int separator_length = separator->length();
7316   int max_nof_separators =
7317       (String::kMaxLength + separator_length - 1) / separator_length;
7318   if (max_nof_separators < (array_length - 1)) {
7319     return isolate->ThrowInvalidStringLength();
7320   }
7321   int length = (array_length - 1) * separator_length;
7322   for (int i = 0; i < array_length; i++) {
7323     Object* element_obj = fixed_array->get(i);
7324     RUNTIME_ASSERT(element_obj->IsString());
7325     String* element = String::cast(element_obj);
7326     int increment = element->length();
7327     if (increment > String::kMaxLength - length) {
7328       STATIC_ASSERT(String::kMaxLength < kMaxInt);
7329       length = kMaxInt;  // Provoke exception;
7330       break;
7331     }
7332     length += increment;
7333   }
7334
7335   Handle<SeqTwoByteString> answer =
7336       isolate->factory()->NewRawTwoByteString(length);
7337   RETURN_IF_EMPTY_HANDLE(isolate, answer);
7338
7339   DisallowHeapAllocation no_gc;
7340
7341   uc16* sink = answer->GetChars();
7342 #ifdef DEBUG
7343   uc16* end = sink + length;
7344 #endif
7345
7346   String* first = String::cast(fixed_array->get(0));
7347   String* seperator_raw = *separator;
7348   int first_length = first->length();
7349   String::WriteToFlat(first, sink, 0, first_length);
7350   sink += first_length;
7351
7352   for (int i = 1; i < array_length; i++) {
7353     ASSERT(sink + separator_length <= end);
7354     String::WriteToFlat(seperator_raw, sink, 0, separator_length);
7355     sink += separator_length;
7356
7357     String* element = String::cast(fixed_array->get(i));
7358     int element_length = element->length();
7359     ASSERT(sink + element_length <= end);
7360     String::WriteToFlat(element, sink, 0, element_length);
7361     sink += element_length;
7362   }
7363   ASSERT(sink == end);
7364
7365   // Use %_FastAsciiArrayJoin instead.
7366   ASSERT(!answer->IsOneByteRepresentation());
7367   return *answer;
7368 }
7369
7370 template <typename Char>
7371 static void JoinSparseArrayWithSeparator(FixedArray* elements,
7372                                          int elements_length,
7373                                          uint32_t array_length,
7374                                          String* separator,
7375                                          Vector<Char> buffer) {
7376   int previous_separator_position = 0;
7377   int separator_length = separator->length();
7378   int cursor = 0;
7379   for (int i = 0; i < elements_length; i += 2) {
7380     int position = NumberToInt32(elements->get(i));
7381     String* string = String::cast(elements->get(i + 1));
7382     int string_length = string->length();
7383     if (string->length() > 0) {
7384       while (previous_separator_position < position) {
7385         String::WriteToFlat<Char>(separator, &buffer[cursor],
7386                                   0, separator_length);
7387         cursor += separator_length;
7388         previous_separator_position++;
7389       }
7390       String::WriteToFlat<Char>(string, &buffer[cursor],
7391                                 0, string_length);
7392       cursor += string->length();
7393     }
7394   }
7395   if (separator_length > 0) {
7396     // Array length must be representable as a signed 32-bit number,
7397     // otherwise the total string length would have been too large.
7398     ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
7399     int last_array_index = static_cast<int>(array_length - 1);
7400     while (previous_separator_position < last_array_index) {
7401       String::WriteToFlat<Char>(separator, &buffer[cursor],
7402                                 0, separator_length);
7403       cursor += separator_length;
7404       previous_separator_position++;
7405     }
7406   }
7407   ASSERT(cursor <= buffer.length());
7408 }
7409
7410
7411 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
7412   HandleScope scope(isolate);
7413   ASSERT(args.length() == 3);
7414   CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
7415   RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7416   CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7417   CONVERT_ARG_CHECKED(String, separator, 2);
7418   // elements_array is fast-mode JSarray of alternating positions
7419   // (increasing order) and strings.
7420   // array_length is length of original array (used to add separators);
7421   // separator is string to put between elements. Assumed to be non-empty.
7422
7423   // Find total length of join result.
7424   int string_length = 0;
7425   bool is_ascii = separator->IsOneByteRepresentation();
7426   bool overflow = false;
7427   CONVERT_NUMBER_CHECKED(int, elements_length,
7428                          Int32, elements_array->length());
7429   RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7430   FixedArray* elements = FixedArray::cast(elements_array->elements());
7431   for (int i = 0; i < elements_length; i += 2) {
7432     RUNTIME_ASSERT(elements->get(i)->IsNumber());
7433     RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7434     String* string = String::cast(elements->get(i + 1));
7435     int length = string->length();
7436     if (is_ascii && !string->IsOneByteRepresentation()) {
7437       is_ascii = false;
7438     }
7439     if (length > String::kMaxLength ||
7440         String::kMaxLength - length < string_length) {
7441       overflow = true;
7442       break;
7443     }
7444     string_length += length;
7445   }
7446   int separator_length = separator->length();
7447   if (!overflow && separator_length > 0) {
7448     if (array_length <= 0x7fffffffu) {
7449       int separator_count = static_cast<int>(array_length) - 1;
7450       int remaining_length = String::kMaxLength - string_length;
7451       if ((remaining_length / separator_length) >= separator_count) {
7452         string_length += separator_length * (array_length - 1);
7453       } else {
7454         // Not room for the separators within the maximal string length.
7455         overflow = true;
7456       }
7457     } else {
7458       // Nonempty separator and at least 2^31-1 separators necessary
7459       // means that the string is too large to create.
7460       STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7461       overflow = true;
7462     }
7463   }
7464   if (overflow) {
7465     // Throw an exception if the resulting string is too large. See
7466     // https://code.google.com/p/chromium/issues/detail?id=336820
7467     // for details.
7468     return isolate->ThrowInvalidStringLength();
7469   }
7470
7471   if (is_ascii) {
7472     MaybeObject* result_allocation =
7473         isolate->heap()->AllocateRawOneByteString(string_length);
7474     if (result_allocation->IsFailure()) return result_allocation;
7475     SeqOneByteString* result_string =
7476         SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
7477     JoinSparseArrayWithSeparator<uint8_t>(elements,
7478                                           elements_length,
7479                                           array_length,
7480                                           separator,
7481                                           Vector<uint8_t>(
7482                                               result_string->GetChars(),
7483                                               string_length));
7484     return result_string;
7485   } else {
7486     MaybeObject* result_allocation =
7487         isolate->heap()->AllocateRawTwoByteString(string_length);
7488     if (result_allocation->IsFailure()) return result_allocation;
7489     SeqTwoByteString* result_string =
7490         SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7491     JoinSparseArrayWithSeparator<uc16>(elements,
7492                                        elements_length,
7493                                        array_length,
7494                                        separator,
7495                                        Vector<uc16>(result_string->GetChars(),
7496                                                     string_length));
7497     return result_string;
7498   }
7499 }
7500
7501
7502 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7503   SealHandleScope shs(isolate);
7504   ASSERT(args.length() == 2);
7505
7506   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7507   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7508   return isolate->heap()->NumberFromInt32(x | y);
7509 }
7510
7511
7512 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7513   SealHandleScope shs(isolate);
7514   ASSERT(args.length() == 2);
7515
7516   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7517   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7518   return isolate->heap()->NumberFromInt32(x & y);
7519 }
7520
7521
7522 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7523   SealHandleScope shs(isolate);
7524   ASSERT(args.length() == 2);
7525
7526   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7527   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7528   return isolate->heap()->NumberFromInt32(x ^ y);
7529 }
7530
7531
7532 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7533   SealHandleScope shs(isolate);
7534   ASSERT(args.length() == 2);
7535
7536   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7537   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7538   return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7539 }
7540
7541
7542 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7543   SealHandleScope shs(isolate);
7544   ASSERT(args.length() == 2);
7545
7546   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7547   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7548   return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7549 }
7550
7551
7552 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7553   SealHandleScope shs(isolate);
7554   ASSERT(args.length() == 2);
7555
7556   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7557   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7558   return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7559 }
7560
7561
7562 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7563   SealHandleScope shs(isolate);
7564   ASSERT(args.length() == 2);
7565
7566   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7567   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7568   if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7569   if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7570   if (x == y) return Smi::FromInt(EQUAL);
7571   Object* result;
7572   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7573     result = Smi::FromInt(EQUAL);
7574   } else {
7575     result = Smi::FromInt(NOT_EQUAL);
7576   }
7577   return result;
7578 }
7579
7580
7581 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7582   SealHandleScope shs(isolate);
7583   ASSERT(args.length() == 2);
7584
7585   CONVERT_ARG_CHECKED(String, x, 0);
7586   CONVERT_ARG_CHECKED(String, y, 1);
7587
7588   bool not_equal = !x->Equals(y);
7589   // This is slightly convoluted because the value that signifies
7590   // equality is 0 and inequality is 1 so we have to negate the result
7591   // from String::Equals.
7592   ASSERT(not_equal == 0 || not_equal == 1);
7593   STATIC_CHECK(EQUAL == 0);
7594   STATIC_CHECK(NOT_EQUAL == 1);
7595   return Smi::FromInt(not_equal);
7596 }
7597
7598
7599 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7600   SealHandleScope shs(isolate);
7601   ASSERT(args.length() == 3);
7602
7603   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7604   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7605   if (std::isnan(x) || std::isnan(y)) return args[2];
7606   if (x == y) return Smi::FromInt(EQUAL);
7607   if (isless(x, y)) return Smi::FromInt(LESS);
7608   return Smi::FromInt(GREATER);
7609 }
7610
7611
7612 // Compare two Smis as if they were converted to strings and then
7613 // compared lexicographically.
7614 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7615   SealHandleScope shs(isolate);
7616   ASSERT(args.length() == 2);
7617   CONVERT_SMI_ARG_CHECKED(x_value, 0);
7618   CONVERT_SMI_ARG_CHECKED(y_value, 1);
7619
7620   // If the integers are equal so are the string representations.
7621   if (x_value == y_value) return Smi::FromInt(EQUAL);
7622
7623   // If one of the integers is zero the normal integer order is the
7624   // same as the lexicographic order of the string representations.
7625   if (x_value == 0 || y_value == 0)
7626     return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7627
7628   // If only one of the integers is negative the negative number is
7629   // smallest because the char code of '-' is less than the char code
7630   // of any digit.  Otherwise, we make both values positive.
7631
7632   // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7633   // architectures using 32-bit Smis.
7634   uint32_t x_scaled = x_value;
7635   uint32_t y_scaled = y_value;
7636   if (x_value < 0 || y_value < 0) {
7637     if (y_value >= 0) return Smi::FromInt(LESS);
7638     if (x_value >= 0) return Smi::FromInt(GREATER);
7639     x_scaled = -x_value;
7640     y_scaled = -y_value;
7641   }
7642
7643   static const uint32_t kPowersOf10[] = {
7644     1, 10, 100, 1000, 10*1000, 100*1000,
7645     1000*1000, 10*1000*1000, 100*1000*1000,
7646     1000*1000*1000
7647   };
7648
7649   // If the integers have the same number of decimal digits they can be
7650   // compared directly as the numeric order is the same as the
7651   // lexicographic order.  If one integer has fewer digits, it is scaled
7652   // by some power of 10 to have the same number of digits as the longer
7653   // integer.  If the scaled integers are equal it means the shorter
7654   // integer comes first in the lexicographic order.
7655
7656   // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7657   int x_log2 = IntegerLog2(x_scaled);
7658   int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7659   x_log10 -= x_scaled < kPowersOf10[x_log10];
7660
7661   int y_log2 = IntegerLog2(y_scaled);
7662   int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7663   y_log10 -= y_scaled < kPowersOf10[y_log10];
7664
7665   int tie = EQUAL;
7666
7667   if (x_log10 < y_log10) {
7668     // X has fewer digits.  We would like to simply scale up X but that
7669     // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7670     // be scaled up to 9_000_000_000. So we scale up by the next
7671     // smallest power and scale down Y to drop one digit. It is OK to
7672     // drop one digit from the longer integer since the final digit is
7673     // past the length of the shorter integer.
7674     x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7675     y_scaled /= 10;
7676     tie = LESS;
7677   } else if (y_log10 < x_log10) {
7678     y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7679     x_scaled /= 10;
7680     tie = GREATER;
7681   }
7682
7683   if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7684   if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7685   return Smi::FromInt(tie);
7686 }
7687
7688
7689 static Object* StringCharacterStreamCompare(RuntimeState* state,
7690                                         String* x,
7691                                         String* y) {
7692   StringCharacterStream stream_x(x, state->string_iterator_compare_x());
7693   StringCharacterStream stream_y(y, state->string_iterator_compare_y());
7694   while (stream_x.HasMore() && stream_y.HasMore()) {
7695     int d = stream_x.GetNext() - stream_y.GetNext();
7696     if (d < 0) return Smi::FromInt(LESS);
7697     else if (d > 0) return Smi::FromInt(GREATER);
7698   }
7699
7700   // x is (non-trivial) prefix of y:
7701   if (stream_y.HasMore()) return Smi::FromInt(LESS);
7702   // y is prefix of x:
7703   return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
7704 }
7705
7706
7707 static Object* FlatStringCompare(String* x, String* y) {
7708   ASSERT(x->IsFlat());
7709   ASSERT(y->IsFlat());
7710   Object* equal_prefix_result = Smi::FromInt(EQUAL);
7711   int prefix_length = x->length();
7712   if (y->length() < prefix_length) {
7713     prefix_length = y->length();
7714     equal_prefix_result = Smi::FromInt(GREATER);
7715   } else if (y->length() > prefix_length) {
7716     equal_prefix_result = Smi::FromInt(LESS);
7717   }
7718   int r;
7719   DisallowHeapAllocation no_gc;
7720   String::FlatContent x_content = x->GetFlatContent();
7721   String::FlatContent y_content = y->GetFlatContent();
7722   if (x_content.IsAscii()) {
7723     Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7724     if (y_content.IsAscii()) {
7725       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7726       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7727     } else {
7728       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7729       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7730     }
7731   } else {
7732     Vector<const uc16> x_chars = x_content.ToUC16Vector();
7733     if (y_content.IsAscii()) {
7734       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7735       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7736     } else {
7737       Vector<const uc16> y_chars = y_content.ToUC16Vector();
7738       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7739     }
7740   }
7741   Object* result;
7742   if (r == 0) {
7743     result = equal_prefix_result;
7744   } else {
7745     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7746   }
7747   ASSERT(result ==
7748       StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
7749   return result;
7750 }
7751
7752
7753 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
7754   SealHandleScope shs(isolate);
7755   ASSERT(args.length() == 2);
7756
7757   CONVERT_ARG_CHECKED(String, x, 0);
7758   CONVERT_ARG_CHECKED(String, y, 1);
7759
7760   isolate->counters()->string_compare_runtime()->Increment();
7761
7762   // A few fast case tests before we flatten.
7763   if (x == y) return Smi::FromInt(EQUAL);
7764   if (y->length() == 0) {
7765     if (x->length() == 0) return Smi::FromInt(EQUAL);
7766     return Smi::FromInt(GREATER);
7767   } else if (x->length() == 0) {
7768     return Smi::FromInt(LESS);
7769   }
7770
7771   int d = x->Get(0) - y->Get(0);
7772   if (d < 0) return Smi::FromInt(LESS);
7773   else if (d > 0) return Smi::FromInt(GREATER);
7774
7775   Object* obj;
7776   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7777     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7778   }
7779   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7780     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7781   }
7782
7783   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7784       : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
7785 }
7786
7787
7788 #define RUNTIME_UNARY_MATH(NAME)                                               \
7789 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_##NAME) {                          \
7790   SealHandleScope shs(isolate);                                                \
7791   ASSERT(args.length() == 1);                                                  \
7792   isolate->counters()->math_##NAME()->Increment();                             \
7793   CONVERT_DOUBLE_ARG_CHECKED(x, 0);                                            \
7794   return isolate->heap()->AllocateHeapNumber(std::NAME(x));                    \
7795 }
7796
7797 RUNTIME_UNARY_MATH(acos)
7798 RUNTIME_UNARY_MATH(asin)
7799 RUNTIME_UNARY_MATH(atan)
7800 RUNTIME_UNARY_MATH(log)
7801 #undef RUNTIME_UNARY_MATH
7802
7803
7804 RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleHi) {
7805   SealHandleScope shs(isolate);
7806   ASSERT(args.length() == 1);
7807   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7808   uint64_t integer = double_to_uint64(x);
7809   integer = (integer >> 32) & 0xFFFFFFFFu;
7810   return isolate->heap()->NumberFromDouble(static_cast<int32_t>(integer));
7811 }
7812
7813
7814 RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleLo) {
7815   SealHandleScope shs(isolate);
7816   ASSERT(args.length() == 1);
7817   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7818   return isolate->heap()->NumberFromDouble(
7819       static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu));
7820 }
7821
7822
7823 RUNTIME_FUNCTION(MaybeObject*, Runtime_ConstructDouble) {
7824   SealHandleScope shs(isolate);
7825   ASSERT(args.length() == 2);
7826   CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
7827   CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
7828   uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
7829   return isolate->heap()->AllocateHeapNumber(uint64_to_double(result));
7830 }
7831
7832
7833 static const double kPiDividedBy4 = 0.78539816339744830962;
7834
7835
7836 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7837   SealHandleScope shs(isolate);
7838   ASSERT(args.length() == 2);
7839   isolate->counters()->math_atan2()->Increment();
7840
7841   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7842   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7843   double result;
7844   if (std::isinf(x) && std::isinf(y)) {
7845     // Make sure that the result in case of two infinite arguments
7846     // is a multiple of Pi / 4. The sign of the result is determined
7847     // by the first argument (x) and the sign of the second argument
7848     // determines the multiplier: one or three.
7849     int multiplier = (x < 0) ? -1 : 1;
7850     if (y < 0) multiplier *= 3;
7851     result = multiplier * kPiDividedBy4;
7852   } else {
7853     result = std::atan2(x, y);
7854   }
7855   return isolate->heap()->AllocateHeapNumber(result);
7856 }
7857
7858
7859 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7860   SealHandleScope shs(isolate);
7861   ASSERT(args.length() == 1);
7862   isolate->counters()->math_exp()->Increment();
7863
7864   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7865   lazily_initialize_fast_exp();
7866   return isolate->heap()->NumberFromDouble(fast_exp(x));
7867 }
7868
7869
7870 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7871   SealHandleScope shs(isolate);
7872   ASSERT(args.length() == 1);
7873   isolate->counters()->math_floor()->Increment();
7874
7875   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7876   return isolate->heap()->NumberFromDouble(std::floor(x));
7877 }
7878
7879
7880 // Slow version of Math.pow.  We check for fast paths for special cases.
7881 // Used if SSE2/VFP3 is not available.
7882 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7883   SealHandleScope shs(isolate);
7884   ASSERT(args.length() == 2);
7885   isolate->counters()->math_pow()->Increment();
7886
7887   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7888
7889   // If the second argument is a smi, it is much faster to call the
7890   // custom powi() function than the generic pow().
7891   if (args[1]->IsSmi()) {
7892     int y = args.smi_at(1);
7893     return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7894   }
7895
7896   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7897   double result = power_helper(x, y);
7898   if (std::isnan(result)) return isolate->heap()->nan_value();
7899   return isolate->heap()->AllocateHeapNumber(result);
7900 }
7901
7902
7903 // Fast version of Math.pow if we know that y is not an integer and y is not
7904 // -0.5 or 0.5.  Used as slow case from full codegen.
7905 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7906   SealHandleScope shs(isolate);
7907   ASSERT(args.length() == 2);
7908   isolate->counters()->math_pow()->Increment();
7909
7910   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7911   CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7912   if (y == 0) {
7913     return Smi::FromInt(1);
7914   } else {
7915     double result = power_double_double(x, y);
7916     if (std::isnan(result)) return isolate->heap()->nan_value();
7917     return isolate->heap()->AllocateHeapNumber(result);
7918   }
7919 }
7920
7921
7922 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7923   SealHandleScope shs(isolate);
7924   ASSERT(args.length() == 1);
7925   isolate->counters()->math_round()->Increment();
7926
7927   if (!args[0]->IsHeapNumber()) {
7928     // Must be smi. Return the argument unchanged for all the other types
7929     // to make fuzz-natives test happy.
7930     return args[0];
7931   }
7932
7933   HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7934
7935   double value = number->value();
7936   int exponent = number->get_exponent();
7937   int sign = number->get_sign();
7938
7939   if (exponent < -1) {
7940     // Number in range ]-0.5..0.5[. These always round to +/-zero.
7941     if (sign) return isolate->heap()->minus_zero_value();
7942     return Smi::FromInt(0);
7943   }
7944
7945   // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7946   // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7947   // argument holds for 32-bit smis).
7948   if (!sign && exponent < kSmiValueSize - 2) {
7949     return Smi::FromInt(static_cast<int>(value + 0.5));
7950   }
7951
7952   // If the magnitude is big enough, there's no place for fraction part. If we
7953   // try to add 0.5 to this number, 1.0 will be added instead.
7954   if (exponent >= 52) {
7955     return number;
7956   }
7957
7958   if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7959
7960   // Do not call NumberFromDouble() to avoid extra checks.
7961   return isolate->heap()->AllocateHeapNumber(std::floor(value + 0.5));
7962 }
7963
7964
7965 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7966   SealHandleScope shs(isolate);
7967   ASSERT(args.length() == 1);
7968   isolate->counters()->math_sqrt()->Increment();
7969
7970   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7971   return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7972 }
7973
7974
7975 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_fround) {
7976   SealHandleScope shs(isolate);
7977   ASSERT(args.length() == 1);
7978
7979   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7980   float xf = static_cast<float>(x);
7981   return isolate->heap()->AllocateHeapNumber(xf);
7982 }
7983
7984
7985 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7986   SealHandleScope shs(isolate);
7987   ASSERT(args.length() == 2);
7988
7989   CONVERT_SMI_ARG_CHECKED(year, 0);
7990   CONVERT_SMI_ARG_CHECKED(month, 1);
7991
7992   return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7993 }
7994
7995
7996 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7997   HandleScope scope(isolate);
7998   ASSERT(args.length() == 3);
7999
8000   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
8001   CONVERT_DOUBLE_ARG_CHECKED(time, 1);
8002   CONVERT_SMI_ARG_CHECKED(is_utc, 2);
8003
8004   DateCache* date_cache = isolate->date_cache();
8005
8006   Object* value = NULL;
8007   bool is_value_nan = false;
8008   if (std::isnan(time)) {
8009     value = isolate->heap()->nan_value();
8010     is_value_nan = true;
8011   } else if (!is_utc &&
8012              (time < -DateCache::kMaxTimeBeforeUTCInMs ||
8013               time > DateCache::kMaxTimeBeforeUTCInMs)) {
8014     value = isolate->heap()->nan_value();
8015     is_value_nan = true;
8016   } else {
8017     time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
8018     if (time < -DateCache::kMaxTimeInMs ||
8019         time > DateCache::kMaxTimeInMs) {
8020       value = isolate->heap()->nan_value();
8021       is_value_nan = true;
8022     } else  {
8023       MaybeObject* maybe_result =
8024           isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
8025       if (!maybe_result->ToObject(&value)) return maybe_result;
8026     }
8027   }
8028   date->SetValue(value, is_value_nan);
8029   return value;
8030 }
8031
8032
8033 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewArgumentsFast) {
8034   HandleScope scope(isolate);
8035   ASSERT(args.length() == 3);
8036
8037   Handle<JSFunction> callee = args.at<JSFunction>(0);
8038   Object** parameters = reinterpret_cast<Object**>(args[1]);
8039   const int argument_count = Smi::cast(args[2])->value();
8040
8041   Handle<JSObject> result =
8042       isolate->factory()->NewArgumentsObject(callee, argument_count);
8043   // Allocate the elements if needed.
8044   int parameter_count = callee->shared()->formal_parameter_count();
8045   if (argument_count > 0) {
8046     if (parameter_count > 0) {
8047       int mapped_count = Min(argument_count, parameter_count);
8048       Handle<FixedArray> parameter_map =
8049           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
8050       parameter_map->set_map(
8051           isolate->heap()->sloppy_arguments_elements_map());
8052
8053       Handle<Map> old_map(result->map());
8054       Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
8055       new_map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
8056
8057       result->set_map(*new_map);
8058       result->set_elements(*parameter_map);
8059
8060       // Store the context and the arguments array at the beginning of the
8061       // parameter map.
8062       Handle<Context> context(isolate->context());
8063       Handle<FixedArray> arguments =
8064           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8065       parameter_map->set(0, *context);
8066       parameter_map->set(1, *arguments);
8067
8068       // Loop over the actual parameters backwards.
8069       int index = argument_count - 1;
8070       while (index >= mapped_count) {
8071         // These go directly in the arguments array and have no
8072         // corresponding slot in the parameter map.
8073         arguments->set(index, *(parameters - index - 1));
8074         --index;
8075       }
8076
8077       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
8078       while (index >= 0) {
8079         // Detect duplicate names to the right in the parameter list.
8080         Handle<String> name(scope_info->ParameterName(index));
8081         int context_local_count = scope_info->ContextLocalCount();
8082         bool duplicate = false;
8083         for (int j = index + 1; j < parameter_count; ++j) {
8084           if (scope_info->ParameterName(j) == *name) {
8085             duplicate = true;
8086             break;
8087           }
8088         }
8089
8090         if (duplicate) {
8091           // This goes directly in the arguments array with a hole in the
8092           // parameter map.
8093           arguments->set(index, *(parameters - index - 1));
8094           parameter_map->set_the_hole(index + 2);
8095         } else {
8096           // The context index goes in the parameter map with a hole in the
8097           // arguments array.
8098           int context_index = -1;
8099           for (int j = 0; j < context_local_count; ++j) {
8100             if (scope_info->ContextLocalName(j) == *name) {
8101               context_index = j;
8102               break;
8103             }
8104           }
8105           ASSERT(context_index >= 0);
8106           arguments->set_the_hole(index);
8107           parameter_map->set(index + 2, Smi::FromInt(
8108               Context::MIN_CONTEXT_SLOTS + context_index));
8109         }
8110
8111         --index;
8112       }
8113     } else {
8114       // If there is no aliasing, the arguments object elements are not
8115       // special in any way.
8116       Handle<FixedArray> elements =
8117           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8118       result->set_elements(*elements);
8119       for (int i = 0; i < argument_count; ++i) {
8120         elements->set(i, *(parameters - i - 1));
8121       }
8122     }
8123   }
8124   return *result;
8125 }
8126
8127
8128 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewStrictArgumentsFast) {
8129   SealHandleScope shs(isolate);
8130   ASSERT(args.length() == 3);
8131
8132   JSFunction* callee = JSFunction::cast(args[0]);
8133   Object** parameters = reinterpret_cast<Object**>(args[1]);
8134   const int length = args.smi_at(2);
8135
8136   Object* result;
8137   { MaybeObject* maybe_result =
8138         isolate->heap()->AllocateArgumentsObject(callee, length);
8139     if (!maybe_result->ToObject(&result)) return maybe_result;
8140   }
8141   // Allocate the elements if needed.
8142   if (length > 0) {
8143     // Allocate the fixed array.
8144     FixedArray* array;
8145     { MaybeObject* maybe_obj =
8146           isolate->heap()->AllocateUninitializedFixedArray(length);
8147       if (!maybe_obj->To(&array)) return maybe_obj;
8148     }
8149
8150     DisallowHeapAllocation no_gc;
8151     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
8152     for (int i = 0; i < length; i++) {
8153       array->set(i, *--parameters, mode);
8154     }
8155     JSObject::cast(result)->set_elements(array);
8156   }
8157   return result;
8158 }
8159
8160
8161 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewClosureFromStubFailure) {
8162   HandleScope scope(isolate);
8163   ASSERT(args.length() == 1);
8164   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
8165   Handle<Context> context(isolate->context());
8166   PretenureFlag pretenure_flag = NOT_TENURED;
8167   Handle<JSFunction> result =
8168       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8169                                                             context,
8170                                                             pretenure_flag);
8171   return *result;
8172 }
8173
8174
8175 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewClosure) {
8176   HandleScope scope(isolate);
8177   ASSERT(args.length() == 3);
8178   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8179   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
8180   CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
8181
8182   // The caller ensures that we pretenure closures that are assigned
8183   // directly to properties.
8184   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
8185   Handle<JSFunction> result =
8186       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8187                                                             context,
8188                                                             pretenure_flag);
8189   return *result;
8190 }
8191
8192
8193 // Find the arguments of the JavaScript function invocation that called
8194 // into C++ code. Collect these in a newly allocated array of handles (possibly
8195 // prefixed by a number of empty handles).
8196 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
8197     Isolate* isolate,
8198     int prefix_argc,
8199     int* total_argc) {
8200   // Find frame containing arguments passed to the caller.
8201   JavaScriptFrameIterator it(isolate);
8202   JavaScriptFrame* frame = it.frame();
8203   List<JSFunction*> functions(2);
8204   frame->GetFunctions(&functions);
8205   if (functions.length() > 1) {
8206     int inlined_jsframe_index = functions.length() - 1;
8207     JSFunction* inlined_function = functions[inlined_jsframe_index];
8208     SlotRefValueBuilder slot_refs(
8209         frame,
8210         inlined_jsframe_index,
8211         inlined_function->shared()->formal_parameter_count());
8212
8213     int args_count = slot_refs.args_length();
8214
8215     *total_argc = prefix_argc + args_count;
8216     SmartArrayPointer<Handle<Object> > param_data(
8217         NewArray<Handle<Object> >(*total_argc));
8218     slot_refs.Prepare(isolate);
8219     for (int i = 0; i < args_count; i++) {
8220       Handle<Object> val = slot_refs.GetNext(isolate, 0);
8221       param_data[prefix_argc + i] = val;
8222     }
8223     slot_refs.Finish(isolate);
8224
8225     return param_data;
8226   } else {
8227     it.AdvanceToArgumentsFrame();
8228     frame = it.frame();
8229     int args_count = frame->ComputeParametersCount();
8230
8231     *total_argc = prefix_argc + args_count;
8232     SmartArrayPointer<Handle<Object> > param_data(
8233         NewArray<Handle<Object> >(*total_argc));
8234     for (int i = 0; i < args_count; i++) {
8235       Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
8236       param_data[prefix_argc + i] = val;
8237     }
8238     return param_data;
8239   }
8240 }
8241
8242
8243 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
8244   HandleScope scope(isolate);
8245   ASSERT(args.length() == 4);
8246   CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
8247   RUNTIME_ASSERT(args[3]->IsNumber());
8248   Handle<Object> bindee = args.at<Object>(1);
8249
8250   // TODO(lrn): Create bound function in C++ code from premade shared info.
8251   bound_function->shared()->set_bound(true);
8252   // Get all arguments of calling function (Function.prototype.bind).
8253   int argc = 0;
8254   SmartArrayPointer<Handle<Object> > arguments =
8255       GetCallerArguments(isolate, 0, &argc);
8256   // Don't count the this-arg.
8257   if (argc > 0) {
8258     ASSERT(*arguments[0] == args[2]);
8259     argc--;
8260   } else {
8261     ASSERT(args[2]->IsUndefined());
8262   }
8263   // Initialize array of bindings (function, this, and any existing arguments
8264   // if the function was already bound).
8265   Handle<FixedArray> new_bindings;
8266   int i;
8267   if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8268     Handle<FixedArray> old_bindings(
8269         JSFunction::cast(*bindee)->function_bindings());
8270     new_bindings =
8271         isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8272     bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8273                             isolate);
8274     i = 0;
8275     for (int n = old_bindings->length(); i < n; i++) {
8276       new_bindings->set(i, old_bindings->get(i));
8277     }
8278   } else {
8279     int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8280     new_bindings = isolate->factory()->NewFixedArray(array_size);
8281     new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8282     new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
8283     i = 2;
8284   }
8285   // Copy arguments, skipping the first which is "this_arg".
8286   for (int j = 0; j < argc; j++, i++) {
8287     new_bindings->set(i, *arguments[j + 1]);
8288   }
8289   new_bindings->set_map_no_write_barrier(
8290       isolate->heap()->fixed_cow_array_map());
8291   bound_function->set_function_bindings(*new_bindings);
8292
8293   // Update length.
8294   Handle<String> length_string = isolate->factory()->length_string();
8295   Handle<Object> new_length(args.at<Object>(3));
8296   PropertyAttributes attr =
8297       static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8298   ForceSetProperty(bound_function, length_string, new_length, attr);
8299   return *bound_function;
8300 }
8301
8302
8303 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
8304   HandleScope handles(isolate);
8305   ASSERT(args.length() == 1);
8306   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8307   if (callable->IsJSFunction()) {
8308     Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8309     if (function->shared()->bound()) {
8310       Handle<FixedArray> bindings(function->function_bindings());
8311       ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8312       return *isolate->factory()->NewJSArrayWithElements(bindings);
8313     }
8314   }
8315   return isolate->heap()->undefined_value();
8316 }
8317
8318
8319 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
8320   HandleScope scope(isolate);
8321   ASSERT(args.length() == 1);
8322   // First argument is a function to use as a constructor.
8323   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8324   RUNTIME_ASSERT(function->shared()->bound());
8325
8326   // The argument is a bound function. Extract its bound arguments
8327   // and callable.
8328   Handle<FixedArray> bound_args =
8329       Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8330   int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8331   Handle<Object> bound_function(
8332       JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
8333       isolate);
8334   ASSERT(!bound_function->IsJSFunction() ||
8335          !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8336
8337   int total_argc = 0;
8338   SmartArrayPointer<Handle<Object> > param_data =
8339       GetCallerArguments(isolate, bound_argc, &total_argc);
8340   for (int i = 0; i < bound_argc; i++) {
8341     param_data[i] = Handle<Object>(bound_args->get(
8342         JSFunction::kBoundArgumentsStartIndex + i), isolate);
8343   }
8344
8345   if (!bound_function->IsJSFunction()) {
8346     bool exception_thrown;
8347     bound_function = Execution::TryGetConstructorDelegate(isolate,
8348                                                           bound_function,
8349                                                           &exception_thrown);
8350     if (exception_thrown) return Failure::Exception();
8351   }
8352   ASSERT(bound_function->IsJSFunction());
8353
8354   bool exception = false;
8355   Handle<Object> result =
8356       Execution::New(Handle<JSFunction>::cast(bound_function),
8357                      total_argc, param_data.get(), &exception);
8358   if (exception) {
8359     return Failure::Exception();
8360   }
8361   ASSERT(!result.is_null());
8362   return *result;
8363 }
8364
8365
8366 static MaybeObject* Runtime_NewObjectHelper(Isolate* isolate,
8367                                             Handle<Object> constructor,
8368                                             Handle<AllocationSite> site) {
8369   // If the constructor isn't a proper function we throw a type error.
8370   if (!constructor->IsJSFunction()) {
8371     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8372     Handle<Object> type_error =
8373         isolate->factory()->NewTypeError("not_constructor", arguments);
8374     return isolate->Throw(*type_error);
8375   }
8376
8377   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8378
8379   // If function should not have prototype, construction is not allowed. In this
8380   // case generated code bailouts here, since function has no initial_map.
8381   if (!function->should_have_prototype() && !function->shared()->bound()) {
8382     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8383     Handle<Object> type_error =
8384         isolate->factory()->NewTypeError("not_constructor", arguments);
8385     return isolate->Throw(*type_error);
8386   }
8387
8388 #ifdef ENABLE_DEBUGGER_SUPPORT
8389   Debug* debug = isolate->debug();
8390   // Handle stepping into constructors if step into is active.
8391   if (debug->StepInActive()) {
8392     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8393   }
8394 #endif
8395
8396   if (function->has_initial_map()) {
8397     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8398       // The 'Function' function ignores the receiver object when
8399       // called using 'new' and creates a new JSFunction object that
8400       // is returned.  The receiver object is only used for error
8401       // reporting if an error occurs when constructing the new
8402       // JSFunction. Factory::NewJSObject() should not be used to
8403       // allocate JSFunctions since it does not properly initialize
8404       // the shared part of the function. Since the receiver is
8405       // ignored anyway, we use the global object as the receiver
8406       // instead of a new JSFunction object. This way, errors are
8407       // reported the same way whether or not 'Function' is called
8408       // using 'new'.
8409       return isolate->context()->global_object();
8410     }
8411   }
8412
8413   // The function should be compiled for the optimization hints to be
8414   // available.
8415   Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
8416
8417   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8418   if (!function->has_initial_map() &&
8419       shared->IsInobjectSlackTrackingInProgress()) {
8420     // The tracking is already in progress for another function. We can only
8421     // track one initial_map at a time, so we force the completion before the
8422     // function is called as a constructor for the first time.
8423     shared->CompleteInobjectSlackTracking();
8424   }
8425
8426   Handle<JSObject> result;
8427   if (site.is_null()) {
8428     result = isolate->factory()->NewJSObject(function);
8429   } else {
8430     result = isolate->factory()->NewJSObjectWithMemento(function, site);
8431   }
8432   RETURN_IF_EMPTY_HANDLE(isolate, result);
8433
8434   isolate->counters()->constructed_objects()->Increment();
8435   isolate->counters()->constructed_objects_runtime()->Increment();
8436
8437   return *result;
8438 }
8439
8440
8441 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewObject) {
8442   HandleScope scope(isolate);
8443   ASSERT(args.length() == 1);
8444
8445   Handle<Object> constructor = args.at<Object>(0);
8446   return Runtime_NewObjectHelper(isolate,
8447                                  constructor,
8448                                  Handle<AllocationSite>::null());
8449 }
8450
8451
8452 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewObjectWithAllocationSite) {
8453   HandleScope scope(isolate);
8454   ASSERT(args.length() == 2);
8455
8456   Handle<Object> constructor = args.at<Object>(1);
8457   Handle<Object> feedback = args.at<Object>(0);
8458   Handle<AllocationSite> site;
8459   if (feedback->IsAllocationSite()) {
8460     // The feedback can be an AllocationSite or undefined.
8461     site = Handle<AllocationSite>::cast(feedback);
8462   }
8463   return Runtime_NewObjectHelper(isolate,
8464                                  constructor,
8465                                  site);
8466 }
8467
8468
8469 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_FinalizeInstanceSize) {
8470   HandleScope scope(isolate);
8471   ASSERT(args.length() == 1);
8472
8473   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8474   function->shared()->CompleteInobjectSlackTracking();
8475
8476   return isolate->heap()->undefined_value();
8477 }
8478
8479
8480 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CompileUnoptimized) {
8481   HandleScope scope(isolate);
8482   ASSERT(args.length() == 1);
8483
8484   Handle<JSFunction> function = args.at<JSFunction>(0);
8485 #ifdef DEBUG
8486   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8487     PrintF("[unoptimized: ");
8488     function->PrintName();
8489     PrintF("]\n");
8490   }
8491 #endif
8492
8493   // Compile the target function.
8494   ASSERT(function->shared()->allows_lazy_compilation());
8495
8496   Handle<Code> code = Compiler::GetUnoptimizedCode(function);
8497   RETURN_IF_EMPTY_HANDLE(isolate, code);
8498   function->ReplaceCode(*code);
8499
8500   // All done. Return the compiled code.
8501   ASSERT(function->is_compiled());
8502   ASSERT(function->code()->kind() == Code::FUNCTION ||
8503          (FLAG_always_opt &&
8504           function->code()->kind() == Code::OPTIMIZED_FUNCTION));
8505   return *code;
8506 }
8507
8508
8509 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CompileOptimized) {
8510   HandleScope scope(isolate);
8511   ASSERT(args.length() == 2);
8512   Handle<JSFunction> function = args.at<JSFunction>(0);
8513   CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
8514
8515   Handle<Code> unoptimized(function->shared()->code());
8516   if (!function->shared()->is_compiled()) {
8517     // If the function is not compiled, do not optimize.
8518     // This can happen if the debugger is activated and
8519     // the function is returned to the not compiled state.
8520     // TODO(yangguo): reconsider this.
8521     function->ReplaceCode(function->shared()->code());
8522   } else if (!isolate->use_crankshaft() ||
8523              function->shared()->optimization_disabled() ||
8524              isolate->DebuggerHasBreakPoints()) {
8525     // If the function is not optimizable or debugger is active continue
8526     // using the code from the full compiler.
8527     if (FLAG_trace_opt) {
8528       PrintF("[failed to optimize ");
8529       function->PrintName();
8530       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8531           function->shared()->optimization_disabled() ? "F" : "T",
8532           isolate->DebuggerHasBreakPoints() ? "T" : "F");
8533     }
8534     function->ReplaceCode(*unoptimized);
8535   } else {
8536     Compiler::ConcurrencyMode mode = concurrent ? Compiler::CONCURRENT
8537                                                 : Compiler::NOT_CONCURRENT;
8538     Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized, mode);
8539     function->ReplaceCode(code.is_null() ? *unoptimized : *code);
8540   }
8541
8542   ASSERT(function->code()->kind() == Code::FUNCTION ||
8543          function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
8544          function->IsInOptimizationQueue());
8545   return function->code();
8546 }
8547
8548
8549 class ActivationsFinder : public ThreadVisitor {
8550  public:
8551   Code* code_;
8552   bool has_code_activations_;
8553
8554   explicit ActivationsFinder(Code* code)
8555     : code_(code),
8556       has_code_activations_(false) { }
8557
8558   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8559     JavaScriptFrameIterator it(isolate, top);
8560     VisitFrames(&it);
8561   }
8562
8563   void VisitFrames(JavaScriptFrameIterator* it) {
8564     for (; !it->done(); it->Advance()) {
8565       JavaScriptFrame* frame = it->frame();
8566       if (code_->contains(frame->pc())) has_code_activations_ = true;
8567     }
8568   }
8569 };
8570
8571
8572 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NotifyStubFailure) {
8573   HandleScope scope(isolate);
8574   ASSERT(args.length() == 0);
8575   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8576   ASSERT(AllowHeapAllocation::IsAllowed());
8577   delete deoptimizer;
8578   return isolate->heap()->undefined_value();
8579 }
8580
8581
8582 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NotifyDeoptimized) {
8583   HandleScope scope(isolate);
8584   ASSERT(args.length() == 1);
8585   RUNTIME_ASSERT(args[0]->IsSmi());
8586   Deoptimizer::BailoutType type =
8587       static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8588   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8589   ASSERT(AllowHeapAllocation::IsAllowed());
8590
8591   Handle<JSFunction> function = deoptimizer->function();
8592   Handle<Code> optimized_code = deoptimizer->compiled_code();
8593
8594   ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
8595   ASSERT(type == deoptimizer->bailout_type());
8596
8597   // Make sure to materialize objects before causing any allocation.
8598   JavaScriptFrameIterator it(isolate);
8599   deoptimizer->MaterializeHeapObjects(&it);
8600   delete deoptimizer;
8601
8602   JavaScriptFrame* frame = it.frame();
8603   RUNTIME_ASSERT(frame->function()->IsJSFunction());
8604   ASSERT(frame->function() == *function);
8605
8606   // Avoid doing too much work when running with --always-opt and keep
8607   // the optimized code around.
8608   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8609     return isolate->heap()->undefined_value();
8610   }
8611
8612   // Search for other activations of the same function and code.
8613   ActivationsFinder activations_finder(*optimized_code);
8614   activations_finder.VisitFrames(&it);
8615   isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8616
8617   if (!activations_finder.has_code_activations_) {
8618     if (function->code() == *optimized_code) {
8619       if (FLAG_trace_deopt) {
8620         PrintF("[removing optimized code for: ");
8621         function->PrintName();
8622         PrintF("]\n");
8623       }
8624       function->ReplaceCode(function->shared()->code());
8625       // Evict optimized code for this function from the cache so that it
8626       // doesn't get used for new closures.
8627       function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8628                                                     "notify deoptimized");
8629     }
8630   } else {
8631     // TODO(titzer): we should probably do DeoptimizeCodeList(code)
8632     // unconditionally if the code is not already marked for deoptimization.
8633     // If there is an index by shared function info, all the better.
8634     Deoptimizer::DeoptimizeFunction(*function);
8635   }
8636
8637   return isolate->heap()->undefined_value();
8638 }
8639
8640
8641 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8642   HandleScope scope(isolate);
8643   ASSERT(args.length() == 1);
8644   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8645   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8646
8647   Deoptimizer::DeoptimizeFunction(*function);
8648
8649   return isolate->heap()->undefined_value();
8650 }
8651
8652
8653 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8654   HandleScope scope(isolate);
8655   ASSERT(args.length() == 1);
8656   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8657   Code* unoptimized = function->shared()->code();
8658   if (unoptimized->kind() == Code::FUNCTION) {
8659     unoptimized->ClearInlineCaches();
8660     unoptimized->ClearTypeFeedbackInfo(isolate->heap());
8661   }
8662   return isolate->heap()->undefined_value();
8663 }
8664
8665
8666 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8667   SealHandleScope shs(isolate);
8668 #if defined(USE_SIMULATOR)
8669   return isolate->heap()->true_value();
8670 #else
8671   return isolate->heap()->false_value();
8672 #endif
8673 }
8674
8675
8676 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) {
8677   HandleScope scope(isolate);
8678   return isolate->concurrent_recompilation_enabled()
8679       ? isolate->heap()->true_value() : isolate->heap()->false_value();
8680 }
8681
8682
8683 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8684   HandleScope scope(isolate);
8685   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8686   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8687
8688   if (!function->IsOptimizable() &&
8689       !function->IsMarkedForConcurrentOptimization() &&
8690       !function->IsInOptimizationQueue()) {
8691     return isolate->heap()->undefined_value();
8692   }
8693
8694   function->MarkForOptimization();
8695
8696   Code* unoptimized = function->shared()->code();
8697   if (args.length() == 2 &&
8698       unoptimized->kind() == Code::FUNCTION) {
8699     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8700     if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
8701       // Start patching from the currently patched loop nesting level.
8702       int current_level = unoptimized->allow_osr_at_loop_nesting_level();
8703       ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
8704       for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
8705         unoptimized->set_allow_osr_at_loop_nesting_level(i);
8706         isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8707       }
8708     } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent")) &&
8709                isolate->concurrent_recompilation_enabled()) {
8710       function->MarkForConcurrentOptimization();
8711     }
8712   }
8713
8714   return isolate->heap()->undefined_value();
8715 }
8716
8717
8718 RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
8719   HandleScope scope(isolate);
8720   ASSERT(args.length() == 1);
8721   CONVERT_ARG_CHECKED(JSFunction, function, 0);
8722   function->shared()->set_optimization_disabled(true);
8723   return isolate->heap()->undefined_value();
8724 }
8725
8726
8727 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8728   HandleScope scope(isolate);
8729   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8730   if (!isolate->use_crankshaft()) {
8731     return Smi::FromInt(4);  // 4 == "never".
8732   }
8733   bool sync_with_compiler_thread = true;
8734   if (args.length() == 2) {
8735     CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
8736     if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
8737       sync_with_compiler_thread = false;
8738     }
8739   }
8740   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8741   if (isolate->concurrent_recompilation_enabled() &&
8742       sync_with_compiler_thread) {
8743     while (function->IsInOptimizationQueue()) {
8744       isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8745       OS::Sleep(50);
8746     }
8747   }
8748   if (FLAG_always_opt) {
8749     // We may have always opt, but that is more best-effort than a real
8750     // promise, so we still say "no" if it is not optimized.
8751     return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8752                                    : Smi::FromInt(2);  // 2 == "no".
8753   }
8754   if (FLAG_deopt_every_n_times) {
8755     return Smi::FromInt(6);  // 6 == "maybe deopted".
8756   }
8757   return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8758                                  : Smi::FromInt(2);  // 2 == "no".
8759 }
8760
8761
8762 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
8763   RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
8764   RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
8765   isolate->optimizing_compiler_thread()->Unblock();
8766   return isolate->heap()->undefined_value();
8767 }
8768
8769
8770 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8771   HandleScope scope(isolate);
8772   ASSERT(args.length() == 1);
8773   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8774   return Smi::FromInt(function->shared()->opt_count());
8775 }
8776
8777
8778 static bool IsSuitableForOnStackReplacement(Isolate* isolate,
8779                                             Handle<JSFunction> function,
8780                                             Handle<Code> current_code) {
8781   // Keep track of whether we've succeeded in optimizing.
8782   if (!isolate->use_crankshaft() || !current_code->optimizable()) return false;
8783   // If we are trying to do OSR when there are already optimized
8784   // activations of the function, it means (a) the function is directly or
8785   // indirectly recursive and (b) an optimized invocation has been
8786   // deoptimized so that we are currently in an unoptimized activation.
8787   // Check for optimized activations of this function.
8788   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
8789     JavaScriptFrame* frame = it.frame();
8790     if (frame->is_optimized() && frame->function() == *function) return false;
8791   }
8792
8793   return true;
8794 }
8795
8796
8797 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8798   HandleScope scope(isolate);
8799   ASSERT(args.length() == 1);
8800   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8801   Handle<Code> caller_code(function->shared()->code());
8802
8803   // We're not prepared to handle a function with arguments object.
8804   ASSERT(!function->shared()->uses_arguments());
8805
8806   // Passing the PC in the javascript frame from the caller directly is
8807   // not GC safe, so we walk the stack to get it.
8808   JavaScriptFrameIterator it(isolate);
8809   JavaScriptFrame* frame = it.frame();
8810   if (!caller_code->contains(frame->pc())) {
8811     // Code on the stack may not be the code object referenced by the shared
8812     // function info.  It may have been replaced to include deoptimization data.
8813     caller_code = Handle<Code>(frame->LookupCode());
8814   }
8815
8816   uint32_t pc_offset = static_cast<uint32_t>(
8817       frame->pc() - caller_code->instruction_start());
8818
8819 #ifdef DEBUG
8820   ASSERT_EQ(frame->function(), *function);
8821   ASSERT_EQ(frame->LookupCode(), *caller_code);
8822   ASSERT(caller_code->contains(frame->pc()));
8823 #endif  // DEBUG
8824
8825
8826   BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
8827   ASSERT(!ast_id.IsNone());
8828
8829   Compiler::ConcurrencyMode mode = isolate->concurrent_osr_enabled()
8830       ? Compiler::CONCURRENT : Compiler::NOT_CONCURRENT;
8831   Handle<Code> result = Handle<Code>::null();
8832
8833   OptimizedCompileJob* job = NULL;
8834   if (mode == Compiler::CONCURRENT) {
8835     // Gate the OSR entry with a stack check.
8836     BackEdgeTable::AddStackCheck(caller_code, pc_offset);
8837     // Poll already queued compilation jobs.
8838     OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
8839     if (thread->IsQueuedForOSR(function, ast_id)) {
8840       if (FLAG_trace_osr) {
8841         PrintF("[OSR - Still waiting for queued: ");
8842         function->PrintName();
8843         PrintF(" at AST id %d]\n", ast_id.ToInt());
8844       }
8845       return NULL;
8846     }
8847
8848     job = thread->FindReadyOSRCandidate(function, ast_id);
8849   }
8850
8851   if (job != NULL) {
8852     if (FLAG_trace_osr) {
8853       PrintF("[OSR - Found ready: ");
8854       function->PrintName();
8855       PrintF(" at AST id %d]\n", ast_id.ToInt());
8856     }
8857     result = Compiler::GetConcurrentlyOptimizedCode(job);
8858   } else if (result.is_null() &&
8859              IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
8860     if (FLAG_trace_osr) {
8861       PrintF("[OSR - Compiling: ");
8862       function->PrintName();
8863       PrintF(" at AST id %d]\n", ast_id.ToInt());
8864     }
8865     result = Compiler::GetOptimizedCode(function, caller_code, mode, ast_id);
8866     if (result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
8867       // Optimization is queued.  Return to check later.
8868       return NULL;
8869     }
8870   }
8871
8872   // Revert the patched back edge table, regardless of whether OSR succeeds.
8873   BackEdgeTable::Revert(isolate, *caller_code);
8874
8875   // Check whether we ended up with usable optimized code.
8876   if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
8877     DeoptimizationInputData* data =
8878         DeoptimizationInputData::cast(result->deoptimization_data());
8879
8880     if (data->OsrPcOffset()->value() >= 0) {
8881       ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8882       if (FLAG_trace_osr) {
8883         PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
8884                ast_id.ToInt(), data->OsrPcOffset()->value());
8885       }
8886       // TODO(titzer): this is a massive hack to make the deopt counts
8887       // match. Fix heuristics for reenabling optimizations!
8888       function->shared()->increment_deopt_count();
8889
8890       // TODO(titzer): Do not install code into the function.
8891       function->ReplaceCode(*result);
8892       return *result;
8893     }
8894   }
8895
8896   // Failed.
8897   if (FLAG_trace_osr) {
8898     PrintF("[OSR - Failed: ");
8899     function->PrintName();
8900     PrintF(" at AST id %d]\n", ast_id.ToInt());
8901   }
8902
8903   if (!function->IsOptimized()) {
8904     function->ReplaceCode(function->shared()->code());
8905   }
8906   return NULL;
8907 }
8908
8909
8910 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
8911   SealHandleScope shs(isolate);
8912   ASSERT(args.length() == 2 || args.length() == 3);
8913 #ifdef DEBUG
8914   CONVERT_SMI_ARG_CHECKED(interval, 0);
8915   CONVERT_SMI_ARG_CHECKED(timeout, 1);
8916   isolate->heap()->set_allocation_timeout(timeout);
8917   FLAG_gc_interval = interval;
8918   if (args.length() == 3) {
8919     // Enable/disable inline allocation if requested.
8920     CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
8921     if (inline_allocation) {
8922       isolate->heap()->EnableInlineAllocation();
8923     } else {
8924       isolate->heap()->DisableInlineAllocation();
8925     }
8926   }
8927 #endif
8928   return isolate->heap()->undefined_value();
8929 }
8930
8931
8932 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8933   SealHandleScope shs(isolate);
8934   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8935   return isolate->heap()->undefined_value();
8936 }
8937
8938
8939 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8940   SealHandleScope shs(isolate);
8941   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8942   return isolate->heap()->nan_value();
8943 }
8944
8945
8946 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8947   HandleScope scope(isolate);
8948   ASSERT(args.length() >= 2);
8949   int argc = args.length() - 2;
8950   CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8951   Object* receiver = args[0];
8952
8953   // If there are too many arguments, allocate argv via malloc.
8954   const int argv_small_size = 10;
8955   Handle<Object> argv_small_buffer[argv_small_size];
8956   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8957   Handle<Object>* argv = argv_small_buffer;
8958   if (argc > argv_small_size) {
8959     argv = new Handle<Object>[argc];
8960     if (argv == NULL) return isolate->StackOverflow();
8961     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8962   }
8963
8964   for (int i = 0; i < argc; ++i) {
8965      MaybeObject* maybe = args[1 + i];
8966      Object* object;
8967      if (!maybe->To<Object>(&object)) return maybe;
8968      argv[i] = Handle<Object>(object, isolate);
8969   }
8970
8971   bool threw;
8972   Handle<JSReceiver> hfun(fun);
8973   Handle<Object> hreceiver(receiver, isolate);
8974   Handle<Object> result = Execution::Call(
8975       isolate, hfun, hreceiver, argc, argv, &threw, true);
8976
8977   if (threw) return Failure::Exception();
8978   return *result;
8979 }
8980
8981
8982 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8983   HandleScope scope(isolate);
8984   ASSERT(args.length() == 5);
8985   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8986   Handle<Object> receiver = args.at<Object>(1);
8987   CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8988   CONVERT_SMI_ARG_CHECKED(offset, 3);
8989   CONVERT_SMI_ARG_CHECKED(argc, 4);
8990   RUNTIME_ASSERT(offset >= 0);
8991   RUNTIME_ASSERT(argc >= 0);
8992
8993   // If there are too many arguments, allocate argv via malloc.
8994   const int argv_small_size = 10;
8995   Handle<Object> argv_small_buffer[argv_small_size];
8996   SmartArrayPointer<Handle<Object> > argv_large_buffer;
8997   Handle<Object>* argv = argv_small_buffer;
8998   if (argc > argv_small_size) {
8999     argv = new Handle<Object>[argc];
9000     if (argv == NULL) return isolate->StackOverflow();
9001     argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
9002   }
9003
9004   for (int i = 0; i < argc; ++i) {
9005     argv[i] = Object::GetElement(isolate, arguments, offset + i);
9006     RETURN_IF_EMPTY_HANDLE(isolate, argv[i]);
9007   }
9008
9009   bool threw;
9010   Handle<Object> result = Execution::Call(
9011       isolate, fun, receiver, argc, argv, &threw, true);
9012
9013   if (threw) return Failure::Exception();
9014   return *result;
9015 }
9016
9017
9018 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
9019   HandleScope scope(isolate);
9020   ASSERT(args.length() == 1);
9021   RUNTIME_ASSERT(!args[0]->IsJSFunction());
9022   return *Execution::GetFunctionDelegate(isolate, args.at<Object>(0));
9023 }
9024
9025
9026 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
9027   HandleScope scope(isolate);
9028   ASSERT(args.length() == 1);
9029   RUNTIME_ASSERT(!args[0]->IsJSFunction());
9030   return *Execution::GetConstructorDelegate(isolate, args.at<Object>(0));
9031 }
9032
9033
9034 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewGlobalContext) {
9035   SealHandleScope shs(isolate);
9036   ASSERT(args.length() == 2);
9037
9038   CONVERT_ARG_CHECKED(JSFunction, function, 0);
9039   CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
9040   Context* result;
9041   MaybeObject* maybe_result =
9042       isolate->heap()->AllocateGlobalContext(function, scope_info);
9043   if (!maybe_result->To(&result)) return maybe_result;
9044
9045   ASSERT(function->context() == isolate->context());
9046   ASSERT(function->context()->global_object() == result->global_object());
9047   result->global_object()->set_global_context(result);
9048
9049   return result;  // non-failure
9050 }
9051
9052
9053 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewFunctionContext) {
9054   SealHandleScope shs(isolate);
9055   ASSERT(args.length() == 1);
9056
9057   CONVERT_ARG_CHECKED(JSFunction, function, 0);
9058   int length = function->shared()->scope_info()->ContextLength();
9059   return isolate->heap()->AllocateFunctionContext(length, function);
9060 }
9061
9062
9063 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushWithContext) {
9064   SealHandleScope shs(isolate);
9065   ASSERT(args.length() == 2);
9066   JSReceiver* extension_object;
9067   if (args[0]->IsJSReceiver()) {
9068     extension_object = JSReceiver::cast(args[0]);
9069   } else {
9070     // Convert the object to a proper JavaScript object.
9071     MaybeObject* maybe_js_object = args[0]->ToObject(isolate);
9072     if (!maybe_js_object->To(&extension_object)) {
9073       if (Failure::cast(maybe_js_object)->IsInternalError()) {
9074         HandleScope scope(isolate);
9075         Handle<Object> handle = args.at<Object>(0);
9076         Handle<Object> result =
9077             isolate->factory()->NewTypeError("with_expression",
9078                                              HandleVector(&handle, 1));
9079         return isolate->Throw(*result);
9080       } else {
9081         return maybe_js_object;
9082       }
9083     }
9084   }
9085
9086   JSFunction* function;
9087   if (args[1]->IsSmi()) {
9088     // A smi sentinel indicates a context nested inside global code rather
9089     // than some function.  There is a canonical empty function that can be
9090     // gotten from the native context.
9091     function = isolate->context()->native_context()->closure();
9092   } else {
9093     function = JSFunction::cast(args[1]);
9094   }
9095
9096   Context* context;
9097   MaybeObject* maybe_context =
9098       isolate->heap()->AllocateWithContext(function,
9099                                            isolate->context(),
9100                                            extension_object);
9101   if (!maybe_context->To(&context)) return maybe_context;
9102   isolate->set_context(context);
9103   return context;
9104 }
9105
9106
9107 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushCatchContext) {
9108   SealHandleScope shs(isolate);
9109   ASSERT(args.length() == 3);
9110   String* name = String::cast(args[0]);
9111   Object* thrown_object = args[1];
9112   JSFunction* function;
9113   if (args[2]->IsSmi()) {
9114     // A smi sentinel indicates a context nested inside global code rather
9115     // than some function.  There is a canonical empty function that can be
9116     // gotten from the native context.
9117     function = isolate->context()->native_context()->closure();
9118   } else {
9119     function = JSFunction::cast(args[2]);
9120   }
9121   Context* context;
9122   MaybeObject* maybe_context =
9123       isolate->heap()->AllocateCatchContext(function,
9124                                             isolate->context(),
9125                                             name,
9126                                             thrown_object);
9127   if (!maybe_context->To(&context)) return maybe_context;
9128   isolate->set_context(context);
9129   return context;
9130 }
9131
9132
9133 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushBlockContext) {
9134   SealHandleScope shs(isolate);
9135   ASSERT(args.length() == 2);
9136   ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
9137   JSFunction* function;
9138   if (args[1]->IsSmi()) {
9139     // A smi sentinel indicates a context nested inside global code rather
9140     // than some function.  There is a canonical empty function that can be
9141     // gotten from the native context.
9142     function = isolate->context()->native_context()->closure();
9143   } else {
9144     function = JSFunction::cast(args[1]);
9145   }
9146   Context* context;
9147   MaybeObject* maybe_context =
9148       isolate->heap()->AllocateBlockContext(function,
9149                                             isolate->context(),
9150                                             scope_info);
9151   if (!maybe_context->To(&context)) return maybe_context;
9152   isolate->set_context(context);
9153   return context;
9154 }
9155
9156
9157 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
9158   SealHandleScope shs(isolate);
9159   ASSERT(args.length() == 1);
9160   Object* obj = args[0];
9161   return isolate->heap()->ToBoolean(obj->IsJSModule());
9162 }
9163
9164
9165 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushModuleContext) {
9166   SealHandleScope shs(isolate);
9167   ASSERT(args.length() == 2);
9168   CONVERT_SMI_ARG_CHECKED(index, 0);
9169
9170   if (!args[1]->IsScopeInfo()) {
9171     // Module already initialized. Find hosting context and retrieve context.
9172     Context* host = Context::cast(isolate->context())->global_context();
9173     Context* context = Context::cast(host->get(index));
9174     ASSERT(context->previous() == isolate->context());
9175     isolate->set_context(context);
9176     return context;
9177   }
9178
9179   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
9180
9181   // Allocate module context.
9182   HandleScope scope(isolate);
9183   Factory* factory = isolate->factory();
9184   Handle<Context> context = factory->NewModuleContext(scope_info);
9185   Handle<JSModule> module = factory->NewJSModule(context, scope_info);
9186   context->set_module(*module);
9187   Context* previous = isolate->context();
9188   context->set_previous(previous);
9189   context->set_closure(previous->closure());
9190   context->set_global_object(previous->global_object());
9191   isolate->set_context(*context);
9192
9193   // Find hosting scope and initialize internal variable holding module there.
9194   previous->global_context()->set(index, *context);
9195
9196   return *context;
9197 }
9198
9199
9200 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareModules) {
9201   HandleScope scope(isolate);
9202   ASSERT(args.length() == 1);
9203   CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
9204   Context* host_context = isolate->context();
9205
9206   for (int i = 0; i < descriptions->length(); ++i) {
9207     Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
9208     int host_index = description->host_index();
9209     Handle<Context> context(Context::cast(host_context->get(host_index)));
9210     Handle<JSModule> module(context->module());
9211
9212     for (int j = 0; j < description->length(); ++j) {
9213       Handle<String> name(description->name(j));
9214       VariableMode mode = description->mode(j);
9215       int index = description->index(j);
9216       switch (mode) {
9217         case VAR:
9218         case LET:
9219         case CONST:
9220         case CONST_LEGACY: {
9221           PropertyAttributes attr =
9222               IsImmutableVariableMode(mode) ? FROZEN : SEALED;
9223           Handle<AccessorInfo> info =
9224               Accessors::MakeModuleExport(name, index, attr);
9225           Handle<Object> result = JSObject::SetAccessor(module, info);
9226           ASSERT(!(result.is_null() || result->IsUndefined()));
9227           USE(result);
9228           break;
9229         }
9230         case MODULE: {
9231           Object* referenced_context = Context::cast(host_context)->get(index);
9232           Handle<JSModule> value(Context::cast(referenced_context)->module());
9233           JSReceiver::SetProperty(module, name, value, FROZEN, STRICT);
9234           break;
9235         }
9236         case INTERNAL:
9237         case TEMPORARY:
9238         case DYNAMIC:
9239         case DYNAMIC_GLOBAL:
9240         case DYNAMIC_LOCAL:
9241           UNREACHABLE();
9242       }
9243     }
9244
9245     JSObject::PreventExtensions(module);
9246   }
9247
9248   ASSERT(!isolate->has_pending_exception());
9249   return isolate->heap()->undefined_value();
9250 }
9251
9252
9253 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeleteContextSlot) {
9254   HandleScope scope(isolate);
9255   ASSERT(args.length() == 2);
9256
9257   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
9258   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
9259
9260   int index;
9261   PropertyAttributes attributes;
9262   ContextLookupFlags flags = FOLLOW_CHAINS;
9263   BindingFlags binding_flags;
9264   Handle<Object> holder = context->Lookup(name,
9265                                           flags,
9266                                           &index,
9267                                           &attributes,
9268                                           &binding_flags);
9269
9270   // If the slot was not found the result is true.
9271   if (holder.is_null()) {
9272     return isolate->heap()->true_value();
9273   }
9274
9275   // If the slot was found in a context, it should be DONT_DELETE.
9276   if (holder->IsContext()) {
9277     return isolate->heap()->false_value();
9278   }
9279
9280   // The slot was found in a JSObject, either a context extension object,
9281   // the global object, or the subject of a with.  Try to delete it
9282   // (respecting DONT_DELETE).
9283   Handle<JSObject> object = Handle<JSObject>::cast(holder);
9284   Handle<Object> result = JSReceiver::DeleteProperty(object, name);
9285   RETURN_IF_EMPTY_HANDLE(isolate, result);
9286   return *result;
9287 }
9288
9289
9290 // A mechanism to return a pair of Object pointers in registers (if possible).
9291 // How this is achieved is calling convention-dependent.
9292 // All currently supported x86 compiles uses calling conventions that are cdecl
9293 // variants where a 64-bit value is returned in two 32-bit registers
9294 // (edx:eax on ia32, r1:r0 on ARM).
9295 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9296 // In Win64 calling convention, a struct of two pointers is returned in memory,
9297 // allocated by the caller, and passed as a pointer in a hidden first parameter.
9298 #ifdef V8_HOST_ARCH_64_BIT
9299 struct ObjectPair {
9300   MaybeObject* x;
9301   MaybeObject* y;
9302 };
9303
9304
9305 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9306   ObjectPair result = {x, y};
9307   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9308   // In Win64 they are assigned to a hidden first argument.
9309   return result;
9310 }
9311 #else
9312 typedef uint64_t ObjectPair;
9313 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9314   return reinterpret_cast<uint32_t>(x) |
9315       (reinterpret_cast<ObjectPair>(y) << 32);
9316 }
9317 #endif
9318
9319
9320 static inline MaybeObject* Unhole(Heap* heap,
9321                                   MaybeObject* x,
9322                                   PropertyAttributes attributes) {
9323   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
9324   USE(attributes);
9325   return x->IsTheHole() ? heap->undefined_value() : x;
9326 }
9327
9328
9329 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9330                                            JSObject* holder) {
9331   ASSERT(!holder->IsGlobalObject());
9332   Context* top = isolate->context();
9333   // Get the context extension function.
9334   JSFunction* context_extension_function =
9335       top->native_context()->context_extension_function();
9336   // If the holder isn't a context extension object, we just return it
9337   // as the receiver. This allows arguments objects to be used as
9338   // receivers, but only if they are put in the context scope chain
9339   // explicitly via a with-statement.
9340   Object* constructor = holder->map()->constructor();
9341   if (constructor != context_extension_function) return holder;
9342   // Fall back to using the global object as the implicit receiver if
9343   // the property turns out to be a local variable allocated in a
9344   // context extension object - introduced via eval.
9345   return isolate->heap()->undefined_value();
9346 }
9347
9348
9349 static ObjectPair LoadContextSlotHelper(Arguments args,
9350                                         Isolate* isolate,
9351                                         bool throw_error) {
9352   HandleScope scope(isolate);
9353   ASSERT_EQ(2, args.length());
9354
9355   if (!args[0]->IsContext() || !args[1]->IsString()) {
9356     return MakePair(isolate->ThrowIllegalOperation(), NULL);
9357   }
9358   Handle<Context> context = args.at<Context>(0);
9359   Handle<String> name = args.at<String>(1);
9360
9361   int index;
9362   PropertyAttributes attributes;
9363   ContextLookupFlags flags = FOLLOW_CHAINS;
9364   BindingFlags binding_flags;
9365   Handle<Object> holder = context->Lookup(name,
9366                                           flags,
9367                                           &index,
9368                                           &attributes,
9369                                           &binding_flags);
9370   if (isolate->has_pending_exception()) {
9371     return MakePair(Failure::Exception(), NULL);
9372   }
9373
9374   // If the index is non-negative, the slot has been found in a context.
9375   if (index >= 0) {
9376     ASSERT(holder->IsContext());
9377     // If the "property" we were looking for is a local variable, the
9378     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9379     Handle<Object> receiver = isolate->factory()->undefined_value();
9380     Object* value = Context::cast(*holder)->get(index);
9381     // Check for uninitialized bindings.
9382     switch (binding_flags) {
9383       case MUTABLE_CHECK_INITIALIZED:
9384       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
9385         if (value->IsTheHole()) {
9386           Handle<Object> reference_error =
9387               isolate->factory()->NewReferenceError("not_defined",
9388                                                     HandleVector(&name, 1));
9389           return MakePair(isolate->Throw(*reference_error), NULL);
9390         }
9391         // FALLTHROUGH
9392       case MUTABLE_IS_INITIALIZED:
9393       case IMMUTABLE_IS_INITIALIZED:
9394       case IMMUTABLE_IS_INITIALIZED_HARMONY:
9395         ASSERT(!value->IsTheHole());
9396         return MakePair(value, *receiver);
9397       case IMMUTABLE_CHECK_INITIALIZED:
9398         return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
9399       case MISSING_BINDING:
9400         UNREACHABLE();
9401         return MakePair(NULL, NULL);
9402     }
9403   }
9404
9405   // Otherwise, if the slot was found the holder is a context extension
9406   // object, subject of a with, or a global object.  We read the named
9407   // property from it.
9408   if (!holder.is_null()) {
9409     Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9410     ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name));
9411     // GetProperty below can cause GC.
9412     Handle<Object> receiver_handle(
9413         object->IsGlobalObject()
9414             ? Object::cast(isolate->heap()->undefined_value())
9415             : object->IsJSProxy() ? static_cast<Object*>(*object)
9416                 : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9417         isolate);
9418
9419     // No need to unhole the value here.  This is taken care of by the
9420     // GetProperty function.
9421     MaybeObject* value = object->GetProperty(*name);
9422     return MakePair(value, *receiver_handle);
9423   }
9424
9425   if (throw_error) {
9426     // The property doesn't exist - throw exception.
9427     Handle<Object> reference_error =
9428         isolate->factory()->NewReferenceError("not_defined",
9429                                               HandleVector(&name, 1));
9430     return MakePair(isolate->Throw(*reference_error), NULL);
9431   } else {
9432     // The property doesn't exist - return undefined.
9433     return MakePair(isolate->heap()->undefined_value(),
9434                     isolate->heap()->undefined_value());
9435   }
9436 }
9437
9438
9439 RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_LoadContextSlot) {
9440   return LoadContextSlotHelper(args, isolate, true);
9441 }
9442
9443
9444 RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_LoadContextSlotNoReferenceError) {
9445   return LoadContextSlotHelper(args, isolate, false);
9446 }
9447
9448
9449 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StoreContextSlot) {
9450   HandleScope scope(isolate);
9451   ASSERT(args.length() == 4);
9452
9453   Handle<Object> value(args[0], isolate);
9454   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9455   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9456   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
9457
9458   int index;
9459   PropertyAttributes attributes;
9460   ContextLookupFlags flags = FOLLOW_CHAINS;
9461   BindingFlags binding_flags;
9462   Handle<Object> holder = context->Lookup(name,
9463                                           flags,
9464                                           &index,
9465                                           &attributes,
9466                                           &binding_flags);
9467   if (isolate->has_pending_exception()) return Failure::Exception();
9468
9469   if (index >= 0) {
9470     // The property was found in a context slot.
9471     Handle<Context> context = Handle<Context>::cast(holder);
9472     if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9473         context->get(index)->IsTheHole()) {
9474       Handle<Object> error =
9475           isolate->factory()->NewReferenceError("not_defined",
9476                                                 HandleVector(&name, 1));
9477       return isolate->Throw(*error);
9478     }
9479     // Ignore if read_only variable.
9480     if ((attributes & READ_ONLY) == 0) {
9481       // Context is a fixed array and set cannot fail.
9482       context->set(index, *value);
9483     } else if (strict_mode == STRICT) {
9484       // Setting read only property in strict mode.
9485       Handle<Object> error =
9486           isolate->factory()->NewTypeError("strict_cannot_assign",
9487                                            HandleVector(&name, 1));
9488       return isolate->Throw(*error);
9489     }
9490     return *value;
9491   }
9492
9493   // Slow case: The property is not in a context slot.  It is either in a
9494   // context extension object, a property of the subject of a with, or a
9495   // property of the global object.
9496   Handle<JSReceiver> object;
9497
9498   if (!holder.is_null()) {
9499     // The property exists on the holder.
9500     object = Handle<JSReceiver>::cast(holder);
9501   } else {
9502     // The property was not found.
9503     ASSERT(attributes == ABSENT);
9504
9505     if (strict_mode == STRICT) {
9506       // Throw in strict mode (assignment to undefined variable).
9507       Handle<Object> error =
9508           isolate->factory()->NewReferenceError(
9509               "not_defined", HandleVector(&name, 1));
9510       return isolate->Throw(*error);
9511     }
9512     // In sloppy mode, the property is added to the global object.
9513     attributes = NONE;
9514     object = Handle<JSReceiver>(isolate->context()->global_object());
9515   }
9516
9517   // Set the property if it's not read only or doesn't yet exist.
9518   if ((attributes & READ_ONLY) == 0 ||
9519       (JSReceiver::GetLocalPropertyAttribute(object, name) == ABSENT)) {
9520     RETURN_IF_EMPTY_HANDLE(
9521         isolate,
9522         JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9523   } else if (strict_mode == STRICT && (attributes & READ_ONLY) != 0) {
9524     // Setting read only property in strict mode.
9525     Handle<Object> error =
9526       isolate->factory()->NewTypeError(
9527           "strict_cannot_assign", HandleVector(&name, 1));
9528     return isolate->Throw(*error);
9529   }
9530   return *value;
9531 }
9532
9533
9534 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Throw) {
9535   HandleScope scope(isolate);
9536   ASSERT(args.length() == 1);
9537
9538   return isolate->Throw(args[0]);
9539 }
9540
9541
9542 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ReThrow) {
9543   HandleScope scope(isolate);
9544   ASSERT(args.length() == 1);
9545
9546   return isolate->ReThrow(args[0]);
9547 }
9548
9549
9550 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PromoteScheduledException) {
9551   SealHandleScope shs(isolate);
9552   ASSERT_EQ(0, args.length());
9553   return isolate->PromoteScheduledException();
9554 }
9555
9556
9557 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowReferenceError) {
9558   HandleScope scope(isolate);
9559   ASSERT(args.length() == 1);
9560
9561   Handle<Object> name(args[0], isolate);
9562   Handle<Object> reference_error =
9563     isolate->factory()->NewReferenceError("not_defined",
9564                                           HandleVector(&name, 1));
9565   return isolate->Throw(*reference_error);
9566 }
9567
9568
9569 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowNotDateError) {
9570   HandleScope scope(isolate);
9571   ASSERT(args.length() == 0);
9572   return isolate->Throw(*isolate->factory()->NewTypeError(
9573       "not_date_object", HandleVector<Object>(NULL, 0)));
9574 }
9575
9576
9577 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowMessage) {
9578   HandleScope scope(isolate);
9579   ASSERT(args.length() == 1);
9580   CONVERT_SMI_ARG_CHECKED(message_id, 0);
9581   const char* message = GetBailoutReason(
9582       static_cast<BailoutReason>(message_id));
9583   Handle<String> message_handle =
9584       isolate->factory()->NewStringFromAscii(CStrVector(message));
9585   RETURN_IF_EMPTY_HANDLE(isolate, message_handle);
9586   return isolate->Throw(*message_handle);
9587 }
9588
9589
9590 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StackGuard) {
9591   SealHandleScope shs(isolate);
9592   ASSERT(args.length() == 0);
9593
9594   // First check if this is a real stack overflow.
9595   if (isolate->stack_guard()->IsStackOverflow()) {
9596     return isolate->StackOverflow();
9597   }
9598
9599   return Execution::HandleStackGuardInterrupt(isolate);
9600 }
9601
9602
9603 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_TryInstallOptimizedCode) {
9604   HandleScope scope(isolate);
9605   ASSERT(args.length() == 1);
9606   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9607
9608   // First check if this is a real stack overflow.
9609   if (isolate->stack_guard()->IsStackOverflow()) {
9610     SealHandleScope shs(isolate);
9611     return isolate->StackOverflow();
9612   }
9613
9614   isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
9615   return (function->IsOptimized()) ? function->code()
9616                                    : function->shared()->code();
9617 }
9618
9619
9620 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Interrupt) {
9621   SealHandleScope shs(isolate);
9622   ASSERT(args.length() == 0);
9623   return Execution::HandleStackGuardInterrupt(isolate);
9624 }
9625
9626
9627 static int StackSize(Isolate* isolate) {
9628   int n = 0;
9629   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9630   return n;
9631 }
9632
9633
9634 static void PrintTransition(Isolate* isolate, Object* result) {
9635   // indentation
9636   { const int nmax = 80;
9637     int n = StackSize(isolate);
9638     if (n <= nmax)
9639       PrintF("%4d:%*s", n, n, "");
9640     else
9641       PrintF("%4d:%*s", n, nmax, "...");
9642   }
9643
9644   if (result == NULL) {
9645     JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9646     PrintF(" {\n");
9647   } else {
9648     // function result
9649     PrintF("} -> ");
9650     result->ShortPrint();
9651     PrintF("\n");
9652   }
9653 }
9654
9655
9656 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9657   SealHandleScope shs(isolate);
9658   ASSERT(args.length() == 0);
9659   PrintTransition(isolate, NULL);
9660   return isolate->heap()->undefined_value();
9661 }
9662
9663
9664 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9665   SealHandleScope shs(isolate);
9666   PrintTransition(isolate, args[0]);
9667   return args[0];  // return TOS
9668 }
9669
9670
9671 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9672   SealHandleScope shs(isolate);
9673   ASSERT(args.length() == 1);
9674
9675 #ifdef DEBUG
9676   if (args[0]->IsString()) {
9677     // If we have a string, assume it's a code "marker"
9678     // and print some interesting cpu debugging info.
9679     JavaScriptFrameIterator it(isolate);
9680     JavaScriptFrame* frame = it.frame();
9681     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9682            frame->fp(), frame->sp(), frame->caller_sp());
9683   } else {
9684     PrintF("DebugPrint: ");
9685   }
9686   args[0]->Print();
9687   if (args[0]->IsHeapObject()) {
9688     PrintF("\n");
9689     HeapObject::cast(args[0])->map()->Print();
9690   }
9691 #else
9692   // ShortPrint is available in release mode. Print is not.
9693   args[0]->ShortPrint();
9694 #endif
9695   PrintF("\n");
9696   Flush();
9697
9698   return args[0];  // return TOS
9699 }
9700
9701
9702 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9703   SealHandleScope shs(isolate);
9704   ASSERT(args.length() == 0);
9705   isolate->PrintStack(stdout);
9706   return isolate->heap()->undefined_value();
9707 }
9708
9709
9710 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9711   SealHandleScope shs(isolate);
9712   ASSERT(args.length() == 0);
9713
9714   // According to ECMA-262, section 15.9.1, page 117, the precision of
9715   // the number in a Date object representing a particular instant in
9716   // time is milliseconds. Therefore, we floor the result of getting
9717   // the OS time.
9718   double millis = std::floor(OS::TimeCurrentMillis());
9719   return isolate->heap()->NumberFromDouble(millis);
9720 }
9721
9722
9723 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9724   HandleScope scope(isolate);
9725   ASSERT(args.length() == 2);
9726
9727   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9728   FlattenString(str);
9729
9730   CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9731
9732   JSObject::EnsureCanContainHeapObjectElements(output);
9733   RUNTIME_ASSERT(output->HasFastObjectElements());
9734
9735   DisallowHeapAllocation no_gc;
9736
9737   FixedArray* output_array = FixedArray::cast(output->elements());
9738   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9739   bool result;
9740   String::FlatContent str_content = str->GetFlatContent();
9741   if (str_content.IsAscii()) {
9742     result = DateParser::Parse(str_content.ToOneByteVector(),
9743                                output_array,
9744                                isolate->unicode_cache());
9745   } else {
9746     ASSERT(str_content.IsTwoByte());
9747     result = DateParser::Parse(str_content.ToUC16Vector(),
9748                                output_array,
9749                                isolate->unicode_cache());
9750   }
9751
9752   if (result) {
9753     return *output;
9754   } else {
9755     return isolate->heap()->null_value();
9756   }
9757 }
9758
9759
9760 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9761   SealHandleScope shs(isolate);
9762   ASSERT(args.length() == 1);
9763
9764   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9765   const char* zone =
9766       isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
9767   return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9768 }
9769
9770
9771 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9772   SealHandleScope shs(isolate);
9773   ASSERT(args.length() == 1);
9774
9775   CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9776   int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9777
9778   return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9779 }
9780
9781
9782 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCacheVersion) {
9783   HandleScope hs(isolate);
9784   ASSERT(args.length() == 0);
9785   if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
9786     Handle<FixedArray> date_cache_version =
9787         isolate->factory()->NewFixedArray(1, TENURED);
9788     date_cache_version->set(0, Smi::FromInt(0));
9789     isolate->eternal_handles()->CreateSingleton(
9790         isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
9791   }
9792   Handle<FixedArray> date_cache_version =
9793       Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
9794           EternalHandles::DATE_CACHE_VERSION));
9795   // Return result as a JS array.
9796   Handle<JSObject> result =
9797       isolate->factory()->NewJSObject(isolate->array_function());
9798   JSArray::SetContent(Handle<JSArray>::cast(result), date_cache_version);
9799   return *result;
9800 }
9801
9802
9803 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9804   SealHandleScope shs(isolate);
9805   ASSERT(args.length() == 1);
9806   Object* global = args[0];
9807   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9808   return JSGlobalObject::cast(global)->global_receiver();
9809 }
9810
9811
9812 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAttachedGlobal) {
9813   SealHandleScope shs(isolate);
9814   ASSERT(args.length() == 1);
9815   Object* global = args[0];
9816   if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
9817   return isolate->heap()->ToBoolean(
9818       !JSGlobalObject::cast(global)->IsDetached());
9819 }
9820
9821
9822 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9823   HandleScope scope(isolate);
9824   ASSERT_EQ(1, args.length());
9825   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9826
9827   source = Handle<String>(FlattenGetString(source));
9828   // Optimized fast case where we only have ASCII characters.
9829   Handle<Object> result;
9830   if (source->IsSeqOneByteString()) {
9831     result = JsonParser<true>::Parse(source);
9832   } else {
9833     result = JsonParser<false>::Parse(source);
9834   }
9835   if (result.is_null()) {
9836     // Syntax error or stack overflow in scanner.
9837     ASSERT(isolate->has_pending_exception());
9838     return Failure::Exception();
9839   }
9840   return *result;
9841 }
9842
9843
9844 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9845                                       Handle<Context> context) {
9846   ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9847   // Check with callback if set.
9848   AllowCodeGenerationFromStringsCallback callback =
9849       isolate->allow_code_gen_callback();
9850   if (callback == NULL) {
9851     // No callback set and code generation disallowed.
9852     return false;
9853   } else {
9854     // Callback set. Let it decide if code generation is allowed.
9855     VMState<EXTERNAL> state(isolate);
9856     return callback(v8::Utils::ToLocal(context));
9857   }
9858 }
9859
9860
9861 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9862   HandleScope scope(isolate);
9863   ASSERT_EQ(2, args.length());
9864   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9865   CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9866
9867   // Extract native context.
9868   Handle<Context> context(isolate->context()->native_context());
9869
9870   // Check if native context allows code generation from
9871   // strings. Throw an exception if it doesn't.
9872   if (context->allow_code_gen_from_strings()->IsFalse() &&
9873       !CodeGenerationFromStringsAllowed(isolate, context)) {
9874     Handle<Object> error_message =
9875         context->ErrorMessageForCodeGenerationFromStrings();
9876     return isolate->Throw(*isolate->factory()->NewEvalError(
9877         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9878   }
9879
9880   // Compile source string in the native context.
9881   ParseRestriction restriction = function_literal_only
9882       ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
9883   Handle<JSFunction> fun = Compiler::GetFunctionFromEval(
9884       source, context, SLOPPY, restriction, RelocInfo::kNoPosition);
9885   RETURN_IF_EMPTY_HANDLE(isolate, fun);
9886   return *fun;
9887 }
9888
9889
9890 static ObjectPair CompileGlobalEval(Isolate* isolate,
9891                                     Handle<String> source,
9892                                     Handle<Object> receiver,
9893                                     StrictMode strict_mode,
9894                                     int scope_position) {
9895   Handle<Context> context = Handle<Context>(isolate->context());
9896   Handle<Context> native_context = Handle<Context>(context->native_context());
9897
9898   // Check if native context allows code generation from
9899   // strings. Throw an exception if it doesn't.
9900   if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9901       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9902     Handle<Object> error_message =
9903         native_context->ErrorMessageForCodeGenerationFromStrings();
9904     isolate->Throw(*isolate->factory()->NewEvalError(
9905         "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9906     return MakePair(Failure::Exception(), NULL);
9907   }
9908
9909   // Deal with a normal eval call with a string argument. Compile it
9910   // and return the compiled function bound in the local context.
9911   static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
9912   Handle<JSFunction> compiled = Compiler::GetFunctionFromEval(
9913       source, context, strict_mode, restriction, scope_position);
9914   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, compiled,
9915                                MakePair(Failure::Exception(), NULL));
9916   return MakePair(*compiled, *receiver);
9917 }
9918
9919
9920 RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_ResolvePossiblyDirectEval) {
9921   HandleScope scope(isolate);
9922   ASSERT(args.length() == 5);
9923
9924   Handle<Object> callee = args.at<Object>(0);
9925
9926   // If "eval" didn't refer to the original GlobalEval, it's not a
9927   // direct call to eval.
9928   // (And even if it is, but the first argument isn't a string, just let
9929   // execution default to an indirect call to eval, which will also return
9930   // the first argument without doing anything).
9931   if (*callee != isolate->native_context()->global_eval_fun() ||
9932       !args[1]->IsString()) {
9933     return MakePair(*callee, isolate->heap()->undefined_value());
9934   }
9935
9936   ASSERT(args[3]->IsSmi());
9937   ASSERT(args.smi_at(3) == SLOPPY || args.smi_at(3) == STRICT);
9938   StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(3));
9939   ASSERT(args[4]->IsSmi());
9940   return CompileGlobalEval(isolate,
9941                            args.at<String>(1),
9942                            args.at<Object>(2),
9943                            strict_mode,
9944                            args.smi_at(4));
9945 }
9946
9947
9948 // Allocate a block of memory in the given space (filled with a filler).
9949 // Used as a fall-back for generated code when the space is full.
9950 static MaybeObject* Allocate(Isolate* isolate,
9951                              int size,
9952                              bool double_align,
9953                              AllocationSpace space) {
9954   Heap* heap = isolate->heap();
9955   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9956   RUNTIME_ASSERT(size > 0);
9957   RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
9958   HeapObject* allocation;
9959   { MaybeObject* maybe_allocation = heap->AllocateRaw(size, space, space);
9960     if (!maybe_allocation->To(&allocation)) return maybe_allocation;
9961   }
9962 #ifdef DEBUG
9963   MemoryChunk* chunk = MemoryChunk::FromAddress(allocation->address());
9964   ASSERT(chunk->owner()->identity() == space);
9965 #endif
9966   heap->CreateFillerObjectAt(allocation->address(), size);
9967   return allocation;
9968 }
9969
9970
9971 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateInNewSpace) {
9972   SealHandleScope shs(isolate);
9973   ASSERT(args.length() == 1);
9974   CONVERT_SMI_ARG_CHECKED(size, 0);
9975   return Allocate(isolate, size, false, NEW_SPACE);
9976 }
9977
9978
9979 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateInTargetSpace) {
9980   SealHandleScope shs(isolate);
9981   ASSERT(args.length() == 2);
9982   CONVERT_SMI_ARG_CHECKED(size, 0);
9983   CONVERT_SMI_ARG_CHECKED(flags, 1);
9984   bool double_align = AllocateDoubleAlignFlag::decode(flags);
9985   AllocationSpace space = AllocateTargetSpace::decode(flags);
9986   return Allocate(isolate, size, double_align, space);
9987 }
9988
9989
9990 // Push an object unto an array of objects if it is not already in the
9991 // array.  Returns true if the element was pushed on the stack and
9992 // false otherwise.
9993 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9994   HandleScope scope(isolate);
9995   ASSERT(args.length() == 2);
9996   CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
9997   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, element, 1);
9998   RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9999   int length = Smi::cast(array->length())->value();
10000   FixedArray* elements = FixedArray::cast(array->elements());
10001   for (int i = 0; i < length; i++) {
10002     if (elements->get(i) == *element) return isolate->heap()->false_value();
10003   }
10004
10005   // Strict not needed. Used for cycle detection in Array join implementation.
10006   RETURN_IF_EMPTY_HANDLE(isolate, JSObject::SetFastElement(array, length,
10007                                                            element,
10008                                                            SLOPPY,
10009                                                            true));
10010   return isolate->heap()->true_value();
10011 }
10012
10013
10014 /**
10015  * A simple visitor visits every element of Array's.
10016  * The backend storage can be a fixed array for fast elements case,
10017  * or a dictionary for sparse array. Since Dictionary is a subtype
10018  * of FixedArray, the class can be used by both fast and slow cases.
10019  * The second parameter of the constructor, fast_elements, specifies
10020  * whether the storage is a FixedArray or Dictionary.
10021  *
10022  * An index limit is used to deal with the situation that a result array
10023  * length overflows 32-bit non-negative integer.
10024  */
10025 class ArrayConcatVisitor {
10026  public:
10027   ArrayConcatVisitor(Isolate* isolate,
10028                      Handle<FixedArray> storage,
10029                      bool fast_elements) :
10030       isolate_(isolate),
10031       storage_(Handle<FixedArray>::cast(
10032           isolate->global_handles()->Create(*storage))),
10033       index_offset_(0u),
10034       fast_elements_(fast_elements),
10035       exceeds_array_limit_(false) { }
10036
10037   ~ArrayConcatVisitor() {
10038     clear_storage();
10039   }
10040
10041   void visit(uint32_t i, Handle<Object> elm) {
10042     if (i > JSObject::kMaxElementCount - index_offset_) {
10043       exceeds_array_limit_ = true;
10044       return;
10045     }
10046     uint32_t index = index_offset_ + i;
10047
10048     if (fast_elements_) {
10049       if (index < static_cast<uint32_t>(storage_->length())) {
10050         storage_->set(index, *elm);
10051         return;
10052       }
10053       // Our initial estimate of length was foiled, possibly by
10054       // getters on the arrays increasing the length of later arrays
10055       // during iteration.
10056       // This shouldn't happen in anything but pathological cases.
10057       SetDictionaryMode(index);
10058       // Fall-through to dictionary mode.
10059     }
10060     ASSERT(!fast_elements_);
10061     Handle<SeededNumberDictionary> dict(
10062         SeededNumberDictionary::cast(*storage_));
10063     Handle<SeededNumberDictionary> result =
10064         isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
10065     if (!result.is_identical_to(dict)) {
10066       // Dictionary needed to grow.
10067       clear_storage();
10068       set_storage(*result);
10069     }
10070   }
10071
10072   void increase_index_offset(uint32_t delta) {
10073     if (JSObject::kMaxElementCount - index_offset_ < delta) {
10074       index_offset_ = JSObject::kMaxElementCount;
10075     } else {
10076       index_offset_ += delta;
10077     }
10078   }
10079
10080   bool exceeds_array_limit() {
10081     return exceeds_array_limit_;
10082   }
10083
10084   Handle<JSArray> ToArray() {
10085     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
10086     Handle<Object> length =
10087         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
10088     Handle<Map> map;
10089     if (fast_elements_) {
10090       map = JSObject::GetElementsTransitionMap(array, FAST_HOLEY_ELEMENTS);
10091     } else {
10092       map = JSObject::GetElementsTransitionMap(array, DICTIONARY_ELEMENTS);
10093     }
10094     array->set_map(*map);
10095     array->set_length(*length);
10096     array->set_elements(*storage_);
10097     return array;
10098   }
10099
10100  private:
10101   // Convert storage to dictionary mode.
10102   void SetDictionaryMode(uint32_t index) {
10103     ASSERT(fast_elements_);
10104     Handle<FixedArray> current_storage(*storage_);
10105     Handle<SeededNumberDictionary> slow_storage(
10106         isolate_->factory()->NewSeededNumberDictionary(
10107             current_storage->length()));
10108     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
10109     for (uint32_t i = 0; i < current_length; i++) {
10110       HandleScope loop_scope(isolate_);
10111       Handle<Object> element(current_storage->get(i), isolate_);
10112       if (!element->IsTheHole()) {
10113         Handle<SeededNumberDictionary> new_storage =
10114           isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
10115         if (!new_storage.is_identical_to(slow_storage)) {
10116           slow_storage = loop_scope.CloseAndEscape(new_storage);
10117         }
10118       }
10119     }
10120     clear_storage();
10121     set_storage(*slow_storage);
10122     fast_elements_ = false;
10123   }
10124
10125   inline void clear_storage() {
10126     GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
10127   }
10128
10129   inline void set_storage(FixedArray* storage) {
10130     storage_ = Handle<FixedArray>::cast(
10131         isolate_->global_handles()->Create(storage));
10132   }
10133
10134   Isolate* isolate_;
10135   Handle<FixedArray> storage_;  // Always a global handle.
10136   // Index after last seen index. Always less than or equal to
10137   // JSObject::kMaxElementCount.
10138   uint32_t index_offset_;
10139   bool fast_elements_ : 1;
10140   bool exceeds_array_limit_ : 1;
10141 };
10142
10143
10144 static uint32_t EstimateElementCount(Handle<JSArray> array) {
10145   uint32_t length = static_cast<uint32_t>(array->length()->Number());
10146   int element_count = 0;
10147   switch (array->GetElementsKind()) {
10148     case FAST_SMI_ELEMENTS:
10149     case FAST_HOLEY_SMI_ELEMENTS:
10150     case FAST_ELEMENTS:
10151     case FAST_HOLEY_ELEMENTS: {
10152       // Fast elements can't have lengths that are not representable by
10153       // a 32-bit signed integer.
10154       ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
10155       int fast_length = static_cast<int>(length);
10156       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
10157       for (int i = 0; i < fast_length; i++) {
10158         if (!elements->get(i)->IsTheHole()) element_count++;
10159       }
10160       break;
10161     }
10162     case FAST_DOUBLE_ELEMENTS:
10163     case FAST_HOLEY_DOUBLE_ELEMENTS: {
10164       // Fast elements can't have lengths that are not representable by
10165       // a 32-bit signed integer.
10166       ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
10167       int fast_length = static_cast<int>(length);
10168       if (array->elements()->IsFixedArray()) {
10169         ASSERT(FixedArray::cast(array->elements())->length() == 0);
10170         break;
10171       }
10172       Handle<FixedDoubleArray> elements(
10173           FixedDoubleArray::cast(array->elements()));
10174       for (int i = 0; i < fast_length; i++) {
10175         if (!elements->is_the_hole(i)) element_count++;
10176       }
10177       break;
10178     }
10179     case DICTIONARY_ELEMENTS: {
10180       Handle<SeededNumberDictionary> dictionary(
10181           SeededNumberDictionary::cast(array->elements()));
10182       int capacity = dictionary->Capacity();
10183       for (int i = 0; i < capacity; i++) {
10184         Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
10185         if (dictionary->IsKey(*key)) {
10186           element_count++;
10187         }
10188       }
10189       break;
10190     }
10191     case SLOPPY_ARGUMENTS_ELEMENTS:
10192 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
10193     case EXTERNAL_##TYPE##_ELEMENTS:                                         \
10194     case TYPE##_ELEMENTS:                                                    \
10195
10196     TYPED_ARRAYS(TYPED_ARRAY_CASE)
10197 #undef TYPED_ARRAY_CASE
10198       // External arrays are always dense.
10199       return length;
10200   }
10201   // As an estimate, we assume that the prototype doesn't contain any
10202   // inherited elements.
10203   return element_count;
10204 }
10205
10206
10207
10208 template<class ExternalArrayClass, class ElementType>
10209 static void IterateExternalArrayElements(Isolate* isolate,
10210                                          Handle<JSObject> receiver,
10211                                          bool elements_are_ints,
10212                                          bool elements_are_guaranteed_smis,
10213                                          ArrayConcatVisitor* visitor) {
10214   Handle<ExternalArrayClass> array(
10215       ExternalArrayClass::cast(receiver->elements()));
10216   uint32_t len = static_cast<uint32_t>(array->length());
10217
10218   ASSERT(visitor != NULL);
10219   if (elements_are_ints) {
10220     if (elements_are_guaranteed_smis) {
10221       for (uint32_t j = 0; j < len; j++) {
10222         HandleScope loop_scope(isolate);
10223         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
10224                       isolate);
10225         visitor->visit(j, e);
10226       }
10227     } else {
10228       for (uint32_t j = 0; j < len; j++) {
10229         HandleScope loop_scope(isolate);
10230         int64_t val = static_cast<int64_t>(array->get_scalar(j));
10231         if (Smi::IsValid(static_cast<intptr_t>(val))) {
10232           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
10233           visitor->visit(j, e);
10234         } else {
10235           Handle<Object> e =
10236               isolate->factory()->NewNumber(static_cast<ElementType>(val));
10237           visitor->visit(j, e);
10238         }
10239       }
10240     }
10241   } else {
10242     for (uint32_t j = 0; j < len; j++) {
10243       HandleScope loop_scope(isolate);
10244       Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
10245       visitor->visit(j, e);
10246     }
10247   }
10248 }
10249
10250
10251 static void IterateExternalFloat32x4ArrayElements(Isolate* isolate,
10252                                                 Handle<JSObject> receiver,
10253                                                 ArrayConcatVisitor* visitor) {
10254   Handle<ExternalFloat32x4Array> array(
10255       ExternalFloat32x4Array::cast(receiver->elements()));
10256   uint32_t len = static_cast<uint32_t>(array->length());
10257
10258   ASSERT(visitor != NULL);
10259   for (uint32_t j = 0; j < len; j++) {
10260     HandleScope loop_scope(isolate);
10261     Handle<Object> e = isolate->factory()->NewFloat32x4(array->get_scalar(j));
10262     visitor->visit(j, e);
10263   }
10264 }
10265
10266
10267 static void IterateExternalInt32x4ArrayElements(Isolate* isolate,
10268                                                  Handle<JSObject> receiver,
10269                                                  ArrayConcatVisitor* visitor) {
10270   Handle<ExternalInt32x4Array> array(
10271       ExternalInt32x4Array::cast(receiver->elements()));
10272   uint32_t len = static_cast<uint32_t>(array->length());
10273
10274   ASSERT(visitor != NULL);
10275   for (uint32_t j = 0; j < len; j++) {
10276     HandleScope loop_scope(isolate);
10277     Handle<Object> e = isolate->factory()->NewInt32x4(array->get_scalar(j));
10278     visitor->visit(j, e);
10279   }
10280 }
10281
10282
10283 // Used for sorting indices in a List<uint32_t>.
10284 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
10285   uint32_t a = *ap;
10286   uint32_t b = *bp;
10287   return (a == b) ? 0 : (a < b) ? -1 : 1;
10288 }
10289
10290
10291 static void CollectElementIndices(Handle<JSObject> object,
10292                                   uint32_t range,
10293                                   List<uint32_t>* indices) {
10294   Isolate* isolate = object->GetIsolate();
10295   ElementsKind kind = object->GetElementsKind();
10296   switch (kind) {
10297     case FAST_SMI_ELEMENTS:
10298     case FAST_ELEMENTS:
10299     case FAST_HOLEY_SMI_ELEMENTS:
10300     case FAST_HOLEY_ELEMENTS: {
10301       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
10302       uint32_t length = static_cast<uint32_t>(elements->length());
10303       if (range < length) length = range;
10304       for (uint32_t i = 0; i < length; i++) {
10305         if (!elements->get(i)->IsTheHole()) {
10306           indices->Add(i);
10307         }
10308       }
10309       break;
10310     }
10311     case FAST_HOLEY_DOUBLE_ELEMENTS:
10312     case FAST_DOUBLE_ELEMENTS: {
10313       // TODO(1810): Decide if it's worthwhile to implement this.
10314       UNREACHABLE();
10315       break;
10316     }
10317     case DICTIONARY_ELEMENTS: {
10318       Handle<SeededNumberDictionary> dict(
10319           SeededNumberDictionary::cast(object->elements()));
10320       uint32_t capacity = dict->Capacity();
10321       for (uint32_t j = 0; j < capacity; j++) {
10322         HandleScope loop_scope(isolate);
10323         Handle<Object> k(dict->KeyAt(j), isolate);
10324         if (dict->IsKey(*k)) {
10325           ASSERT(k->IsNumber());
10326           uint32_t index = static_cast<uint32_t>(k->Number());
10327           if (index < range) {
10328             indices->Add(index);
10329           }
10330         }
10331       }
10332       break;
10333     }
10334     default: {
10335       int dense_elements_length;
10336       switch (kind) {
10337 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
10338         case EXTERNAL_##TYPE##_ELEMENTS: {                                     \
10339           dense_elements_length =                                              \
10340               External##Type##Array::cast(object->elements())->length();       \
10341           break;                                                               \
10342         }
10343
10344         TYPED_ARRAYS(TYPED_ARRAY_CASE)
10345 #undef TYPED_ARRAY_CASE
10346
10347         default:
10348           UNREACHABLE();
10349           dense_elements_length = 0;
10350           break;
10351       }
10352       uint32_t length = static_cast<uint32_t>(dense_elements_length);
10353       if (range <= length) {
10354         length = range;
10355         // We will add all indices, so we might as well clear it first
10356         // and avoid duplicates.
10357         indices->Clear();
10358       }
10359       for (uint32_t i = 0; i < length; i++) {
10360         indices->Add(i);
10361       }
10362       if (length == range) return;  // All indices accounted for already.
10363       break;
10364     }
10365   }
10366
10367   Handle<Object> prototype(object->GetPrototype(), isolate);
10368   if (prototype->IsJSObject()) {
10369     // The prototype will usually have no inherited element indices,
10370     // but we have to check.
10371     CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
10372   }
10373 }
10374
10375
10376 /**
10377  * A helper function that visits elements of a JSArray in numerical
10378  * order.
10379  *
10380  * The visitor argument called for each existing element in the array
10381  * with the element index and the element's value.
10382  * Afterwards it increments the base-index of the visitor by the array
10383  * length.
10384  * Returns false if any access threw an exception, otherwise true.
10385  */
10386 static bool IterateElements(Isolate* isolate,
10387                             Handle<JSArray> receiver,
10388                             ArrayConcatVisitor* visitor) {
10389   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10390   switch (receiver->GetElementsKind()) {
10391     case FAST_SMI_ELEMENTS:
10392     case FAST_ELEMENTS:
10393     case FAST_HOLEY_SMI_ELEMENTS:
10394     case FAST_HOLEY_ELEMENTS: {
10395       // Run through the elements FixedArray and use HasElement and GetElement
10396       // to check the prototype for missing elements.
10397       Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10398       int fast_length = static_cast<int>(length);
10399       ASSERT(fast_length <= elements->length());
10400       for (int j = 0; j < fast_length; j++) {
10401         HandleScope loop_scope(isolate);
10402         Handle<Object> element_value(elements->get(j), isolate);
10403         if (!element_value->IsTheHole()) {
10404           visitor->visit(j, element_value);
10405         } else if (JSReceiver::HasElement(receiver, j)) {
10406           // Call GetElement on receiver, not its prototype, or getters won't
10407           // have the correct receiver.
10408           element_value = Object::GetElement(isolate, receiver, j);
10409           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10410           visitor->visit(j, element_value);
10411         }
10412       }
10413       break;
10414     }
10415     case FAST_HOLEY_DOUBLE_ELEMENTS:
10416     case FAST_DOUBLE_ELEMENTS: {
10417       // Run through the elements FixedArray and use HasElement and GetElement
10418       // to check the prototype for missing elements.
10419       Handle<FixedDoubleArray> elements(
10420           FixedDoubleArray::cast(receiver->elements()));
10421       int fast_length = static_cast<int>(length);
10422       ASSERT(fast_length <= elements->length());
10423       for (int j = 0; j < fast_length; j++) {
10424         HandleScope loop_scope(isolate);
10425         if (!elements->is_the_hole(j)) {
10426           double double_value = elements->get_scalar(j);
10427           Handle<Object> element_value =
10428               isolate->factory()->NewNumber(double_value);
10429           visitor->visit(j, element_value);
10430         } else if (JSReceiver::HasElement(receiver, j)) {
10431           // Call GetElement on receiver, not its prototype, or getters won't
10432           // have the correct receiver.
10433           Handle<Object> element_value =
10434               Object::GetElement(isolate, receiver, j);
10435           RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10436           visitor->visit(j, element_value);
10437         }
10438       }
10439       break;
10440     }
10441     case DICTIONARY_ELEMENTS: {
10442       Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10443       List<uint32_t> indices(dict->Capacity() / 2);
10444       // Collect all indices in the object and the prototypes less
10445       // than length. This might introduce duplicates in the indices list.
10446       CollectElementIndices(receiver, length, &indices);
10447       indices.Sort(&compareUInt32);
10448       int j = 0;
10449       int n = indices.length();
10450       while (j < n) {
10451         HandleScope loop_scope(isolate);
10452         uint32_t index = indices[j];
10453         Handle<Object> element = Object::GetElement(isolate, receiver, index);
10454         RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
10455         visitor->visit(index, element);
10456         // Skip to next different index (i.e., omit duplicates).
10457         do {
10458           j++;
10459         } while (j < n && indices[j] == index);
10460       }
10461       break;
10462     }
10463     case EXTERNAL_UINT8_CLAMPED_ELEMENTS: {
10464       Handle<ExternalUint8ClampedArray> pixels(ExternalUint8ClampedArray::cast(
10465           receiver->elements()));
10466       for (uint32_t j = 0; j < length; j++) {
10467         Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10468         visitor->visit(j, e);
10469       }
10470       break;
10471     }
10472     case EXTERNAL_INT8_ELEMENTS: {
10473       IterateExternalArrayElements<ExternalInt8Array, int8_t>(
10474           isolate, receiver, true, true, visitor);
10475       break;
10476     }
10477     case EXTERNAL_UINT8_ELEMENTS: {
10478       IterateExternalArrayElements<ExternalUint8Array, uint8_t>(
10479           isolate, receiver, true, true, visitor);
10480       break;
10481     }
10482     case EXTERNAL_INT16_ELEMENTS: {
10483       IterateExternalArrayElements<ExternalInt16Array, int16_t>(
10484           isolate, receiver, true, true, visitor);
10485       break;
10486     }
10487     case EXTERNAL_UINT16_ELEMENTS: {
10488       IterateExternalArrayElements<ExternalUint16Array, uint16_t>(
10489           isolate, receiver, true, true, visitor);
10490       break;
10491     }
10492     case EXTERNAL_INT32_ELEMENTS: {
10493       IterateExternalArrayElements<ExternalInt32Array, int32_t>(
10494           isolate, receiver, true, false, visitor);
10495       break;
10496     }
10497     case EXTERNAL_UINT32_ELEMENTS: {
10498       IterateExternalArrayElements<ExternalUint32Array, uint32_t>(
10499           isolate, receiver, true, false, visitor);
10500       break;
10501     }
10502     case EXTERNAL_FLOAT32_ELEMENTS: {
10503       IterateExternalArrayElements<ExternalFloat32Array, float>(
10504           isolate, receiver, false, false, visitor);
10505       break;
10506     }
10507     case EXTERNAL_FLOAT32x4_ELEMENTS: {
10508       IterateExternalFloat32x4ArrayElements(isolate, receiver, visitor);
10509       break;
10510     }
10511     case EXTERNAL_INT32x4_ELEMENTS: {
10512       IterateExternalInt32x4ArrayElements(isolate, receiver, visitor);
10513       break;
10514     }
10515     case EXTERNAL_FLOAT64_ELEMENTS: {
10516       IterateExternalArrayElements<ExternalFloat64Array, double>(
10517           isolate, receiver, false, false, visitor);
10518       break;
10519     }
10520     default:
10521       UNREACHABLE();
10522       break;
10523   }
10524   visitor->increase_index_offset(length);
10525   return true;
10526 }
10527
10528
10529 /**
10530  * Array::concat implementation.
10531  * See ECMAScript 262, 15.4.4.4.
10532  * TODO(581): Fix non-compliance for very large concatenations and update to
10533  * following the ECMAScript 5 specification.
10534  */
10535 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
10536   HandleScope handle_scope(isolate);
10537   ASSERT(args.length() == 1);
10538
10539   CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10540   int argument_count = static_cast<int>(arguments->length()->Number());
10541   RUNTIME_ASSERT(arguments->HasFastObjectElements());
10542   Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10543
10544   // Pass 1: estimate the length and number of elements of the result.
10545   // The actual length can be larger if any of the arguments have getters
10546   // that mutate other arguments (but will otherwise be precise).
10547   // The number of elements is precise if there are no inherited elements.
10548
10549   ElementsKind kind = FAST_SMI_ELEMENTS;
10550
10551   uint32_t estimate_result_length = 0;
10552   uint32_t estimate_nof_elements = 0;
10553   for (int i = 0; i < argument_count; i++) {
10554     HandleScope loop_scope(isolate);
10555     Handle<Object> obj(elements->get(i), isolate);
10556     uint32_t length_estimate;
10557     uint32_t element_estimate;
10558     if (obj->IsJSArray()) {
10559       Handle<JSArray> array(Handle<JSArray>::cast(obj));
10560       length_estimate = static_cast<uint32_t>(array->length()->Number());
10561       if (length_estimate != 0) {
10562         ElementsKind array_kind =
10563             GetPackedElementsKind(array->map()->elements_kind());
10564         if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10565           kind = array_kind;
10566         }
10567       }
10568       element_estimate = EstimateElementCount(array);
10569     } else {
10570       if (obj->IsHeapObject()) {
10571         if (obj->IsNumber()) {
10572           if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
10573             kind = FAST_DOUBLE_ELEMENTS;
10574           }
10575         } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
10576           kind = FAST_ELEMENTS;
10577         }
10578       }
10579       length_estimate = 1;
10580       element_estimate = 1;
10581     }
10582     // Avoid overflows by capping at kMaxElementCount.
10583     if (JSObject::kMaxElementCount - estimate_result_length <
10584         length_estimate) {
10585       estimate_result_length = JSObject::kMaxElementCount;
10586     } else {
10587       estimate_result_length += length_estimate;
10588     }
10589     if (JSObject::kMaxElementCount - estimate_nof_elements <
10590         element_estimate) {
10591       estimate_nof_elements = JSObject::kMaxElementCount;
10592     } else {
10593       estimate_nof_elements += element_estimate;
10594     }
10595   }
10596
10597   // If estimated number of elements is more than half of length, a
10598   // fixed array (fast case) is more time and space-efficient than a
10599   // dictionary.
10600   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10601
10602   Handle<FixedArray> storage;
10603   if (fast_case) {
10604     if (kind == FAST_DOUBLE_ELEMENTS) {
10605       Handle<FixedDoubleArray> double_storage =
10606           isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10607       int j = 0;
10608       bool failure = false;
10609       for (int i = 0; i < argument_count; i++) {
10610         Handle<Object> obj(elements->get(i), isolate);
10611         if (obj->IsSmi()) {
10612           double_storage->set(j, Smi::cast(*obj)->value());
10613           j++;
10614         } else if (obj->IsNumber()) {
10615           double_storage->set(j, obj->Number());
10616           j++;
10617         } else {
10618           JSArray* array = JSArray::cast(*obj);
10619           uint32_t length = static_cast<uint32_t>(array->length()->Number());
10620           switch (array->map()->elements_kind()) {
10621             case FAST_HOLEY_DOUBLE_ELEMENTS:
10622             case FAST_DOUBLE_ELEMENTS: {
10623               // Empty fixed array indicates that there are no elements.
10624               if (array->elements()->IsFixedArray()) break;
10625               FixedDoubleArray* elements =
10626                   FixedDoubleArray::cast(array->elements());
10627               for (uint32_t i = 0; i < length; i++) {
10628                 if (elements->is_the_hole(i)) {
10629                   failure = true;
10630                   break;
10631                 }
10632                 double double_value = elements->get_scalar(i);
10633                 double_storage->set(j, double_value);
10634                 j++;
10635               }
10636               break;
10637             }
10638             case FAST_HOLEY_SMI_ELEMENTS:
10639             case FAST_SMI_ELEMENTS: {
10640               FixedArray* elements(
10641                   FixedArray::cast(array->elements()));
10642               for (uint32_t i = 0; i < length; i++) {
10643                 Object* element = elements->get(i);
10644                 if (element->IsTheHole()) {
10645                   failure = true;
10646                   break;
10647                 }
10648                 int32_t int_value = Smi::cast(element)->value();
10649                 double_storage->set(j, int_value);
10650                 j++;
10651               }
10652               break;
10653             }
10654             case FAST_HOLEY_ELEMENTS:
10655               ASSERT_EQ(0, length);
10656               break;
10657             default:
10658               UNREACHABLE();
10659           }
10660         }
10661         if (failure) break;
10662       }
10663       Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10664       Smi* length = Smi::FromInt(j);
10665       Handle<Map> map;
10666       map = JSObject::GetElementsTransitionMap(array, kind);
10667       array->set_map(*map);
10668       array->set_length(length);
10669       array->set_elements(*double_storage);
10670       return *array;
10671     }
10672     // The backing storage array must have non-existing elements to preserve
10673     // holes across concat operations.
10674     storage = isolate->factory()->NewFixedArrayWithHoles(
10675         estimate_result_length);
10676   } else {
10677     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10678     uint32_t at_least_space_for = estimate_nof_elements +
10679                                   (estimate_nof_elements >> 2);
10680     storage = Handle<FixedArray>::cast(
10681         isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
10682   }
10683
10684   ArrayConcatVisitor visitor(isolate, storage, fast_case);
10685
10686   for (int i = 0; i < argument_count; i++) {
10687     Handle<Object> obj(elements->get(i), isolate);
10688     if (obj->IsJSArray()) {
10689       Handle<JSArray> array = Handle<JSArray>::cast(obj);
10690       if (!IterateElements(isolate, array, &visitor)) {
10691         return Failure::Exception();
10692       }
10693     } else {
10694       visitor.visit(0, obj);
10695       visitor.increase_index_offset(1);
10696     }
10697   }
10698
10699   if (visitor.exceeds_array_limit()) {
10700     return isolate->Throw(
10701         *isolate->factory()->NewRangeError("invalid_array_length",
10702                                            HandleVector<Object>(NULL, 0)));
10703   }
10704   return *visitor.ToArray();
10705 }
10706
10707
10708 // This will not allocate (flatten the string), but it may run
10709 // very slowly for very deeply nested ConsStrings.  For debugging use only.
10710 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10711   SealHandleScope shs(isolate);
10712   ASSERT(args.length() == 1);
10713
10714   CONVERT_ARG_CHECKED(String, string, 0);
10715   ConsStringIteratorOp op;
10716   StringCharacterStream stream(string, &op);
10717   while (stream.HasMore()) {
10718     uint16_t character = stream.GetNext();
10719     PrintF("%c", character);
10720   }
10721   return string;
10722 }
10723
10724
10725 // Moves all own elements of an object, that are below a limit, to positions
10726 // starting at zero. All undefined values are placed after non-undefined values,
10727 // and are followed by non-existing element. Does not change the length
10728 // property.
10729 // Returns the number of non-undefined elements collected.
10730 // Returns -1 if hole removal is not supported by this method.
10731 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10732   HandleScope scope(isolate);
10733   ASSERT(args.length() == 2);
10734   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
10735   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10736   return *JSObject::PrepareElementsForSort(object, limit);
10737 }
10738
10739
10740 // Move contents of argument 0 (an array) to argument 1 (an array)
10741 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10742   SealHandleScope shs(isolate);
10743   ASSERT(args.length() == 2);
10744   CONVERT_ARG_CHECKED(JSArray, from, 0);
10745   CONVERT_ARG_CHECKED(JSArray, to, 1);
10746   from->ValidateElements();
10747   to->ValidateElements();
10748   FixedArrayBase* new_elements = from->elements();
10749   ElementsKind from_kind = from->GetElementsKind();
10750   MaybeObject* maybe_new_map;
10751   maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
10752   Object* new_map;
10753   if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10754   to->set_map_and_elements(Map::cast(new_map), new_elements);
10755   to->set_length(from->length());
10756   Object* obj;
10757   { MaybeObject* maybe_obj = from->ResetElements();
10758     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10759   }
10760   from->set_length(Smi::FromInt(0));
10761   to->ValidateElements();
10762   return to;
10763 }
10764
10765
10766 // How many elements does this object/array have?
10767 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10768   SealHandleScope shs(isolate);
10769   ASSERT(args.length() == 1);
10770   CONVERT_ARG_CHECKED(JSObject, object, 0);
10771   HeapObject* elements = object->elements();
10772   if (elements->IsDictionary()) {
10773     int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10774     return Smi::FromInt(result);
10775   } else if (object->IsJSArray()) {
10776     return JSArray::cast(object)->length();
10777   } else {
10778     return Smi::FromInt(FixedArray::cast(elements)->length());
10779   }
10780 }
10781
10782
10783 // Returns an array that tells you where in the [0, length) interval an array
10784 // might have elements.  Can either return an array of keys (positive integers
10785 // or undefined) or a number representing the positive length of an interval
10786 // starting at index 0.
10787 // Intervals can span over some keys that are not in the object.
10788 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10789   HandleScope scope(isolate);
10790   ASSERT(args.length() == 2);
10791   CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10792   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10793   if (array->elements()->IsDictionary()) {
10794     Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10795     for (Handle<Object> p = array;
10796          !p->IsNull();
10797          p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
10798       if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
10799         // Bail out if we find a proxy or interceptor, likely not worth
10800         // collecting keys in that case.
10801         return *isolate->factory()->NewNumberFromUint(length);
10802       }
10803       Handle<JSObject> current = Handle<JSObject>::cast(p);
10804       Handle<FixedArray> current_keys =
10805           isolate->factory()->NewFixedArray(
10806               current->NumberOfLocalElements(NONE));
10807       current->GetLocalElementKeys(*current_keys, NONE);
10808       keys = UnionOfKeys(keys, current_keys);
10809     }
10810     // Erase any keys >= length.
10811     // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10812     // is changed to let this happen on the JS side.
10813     for (int i = 0; i < keys->length(); i++) {
10814       if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10815     }
10816     return *isolate->factory()->NewJSArrayWithElements(keys);
10817   } else {
10818     ASSERT(array->HasFastSmiOrObjectElements() ||
10819            array->HasFastDoubleElements());
10820     uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10821     return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10822   }
10823 }
10824
10825
10826 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10827   HandleScope scope(isolate);
10828   ASSERT(args.length() == 3);
10829   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
10830   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10831   CONVERT_SMI_ARG_CHECKED(flag, 2);
10832   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10833   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10834   Handle<Object> result =
10835       JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component);
10836   RETURN_IF_EMPTY_HANDLE(isolate, result);
10837   return *result;
10838 }
10839
10840
10841 #ifdef ENABLE_DEBUGGER_SUPPORT
10842 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10843   SealHandleScope shs(isolate);
10844   ASSERT(args.length() == 0);
10845   return Execution::DebugBreakHelper(isolate);
10846 }
10847
10848
10849 // Helper functions for wrapping and unwrapping stack frame ids.
10850 static Smi* WrapFrameId(StackFrame::Id id) {
10851   ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10852   return Smi::FromInt(id >> 2);
10853 }
10854
10855
10856 static StackFrame::Id UnwrapFrameId(int wrapped) {
10857   return static_cast<StackFrame::Id>(wrapped << 2);
10858 }
10859
10860
10861 // Adds a JavaScript function as a debug event listener.
10862 // args[0]: debug event listener function to set or null or undefined for
10863 //          clearing the event listener function
10864 // args[1]: object supplied during callback
10865 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10866   SealHandleScope shs(isolate);
10867   ASSERT(args.length() == 2);
10868   RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10869                  args[0]->IsUndefined() ||
10870                  args[0]->IsNull());
10871   Handle<Object> callback = args.at<Object>(0);
10872   Handle<Object> data = args.at<Object>(1);
10873   isolate->debugger()->SetEventListener(callback, data);
10874
10875   return isolate->heap()->undefined_value();
10876 }
10877
10878
10879 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10880   SealHandleScope shs(isolate);
10881   ASSERT(args.length() == 0);
10882   isolate->stack_guard()->DebugBreak();
10883   return isolate->heap()->undefined_value();
10884 }
10885
10886
10887 static MaybeObject* DebugLookupResultValue(Heap* heap,
10888                                            Object* receiver,
10889                                            Name* name,
10890                                            LookupResult* result,
10891                                            bool* caught_exception) {
10892   Object* value;
10893   switch (result->type()) {
10894     case NORMAL:
10895       value = result->holder()->GetNormalizedProperty(result);
10896       if (value->IsTheHole()) {
10897         return heap->undefined_value();
10898       }
10899       return value;
10900     case FIELD: {
10901       Object* value;
10902       MaybeObject* maybe_value =
10903           JSObject::cast(result->holder())->FastPropertyAt(
10904               result->representation(),
10905               result->GetFieldIndex().field_index());
10906       if (!maybe_value->To(&value)) return maybe_value;
10907       if (value->IsTheHole()) {
10908         return heap->undefined_value();
10909       }
10910       return value;
10911     }
10912     case CONSTANT:
10913       return result->GetConstant();
10914     case CALLBACKS: {
10915       Object* structure = result->GetCallbackObject();
10916       if (structure->IsForeign() || structure->IsAccessorInfo()) {
10917         Isolate* isolate = heap->isolate();
10918         HandleScope scope(isolate);
10919         Handle<Object> value = JSObject::GetPropertyWithCallback(
10920             handle(result->holder(), isolate),
10921             handle(receiver, isolate),
10922             handle(structure, isolate),
10923             handle(name, isolate));
10924         if (value.is_null()) {
10925           MaybeObject* exception = heap->isolate()->pending_exception();
10926           heap->isolate()->clear_pending_exception();
10927           if (caught_exception != NULL) *caught_exception = true;
10928           return exception;
10929         }
10930         return *value;
10931       } else {
10932         return heap->undefined_value();
10933       }
10934     }
10935     case INTERCEPTOR:
10936     case TRANSITION:
10937       return heap->undefined_value();
10938     case HANDLER:
10939     case NONEXISTENT:
10940       UNREACHABLE();
10941       return heap->undefined_value();
10942   }
10943   UNREACHABLE();  // keep the compiler happy
10944   return heap->undefined_value();
10945 }
10946
10947
10948 // Get debugger related details for an object property.
10949 // args[0]: object holding property
10950 // args[1]: name of the property
10951 //
10952 // The array returned contains the following information:
10953 // 0: Property value
10954 // 1: Property details
10955 // 2: Property value is exception
10956 // 3: Getter function if defined
10957 // 4: Setter function if defined
10958 // Items 2-4 are only filled if the property has either a getter or a setter
10959 // defined through __defineGetter__ and/or __defineSetter__.
10960 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10961   HandleScope scope(isolate);
10962
10963   ASSERT(args.length() == 2);
10964
10965   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10966   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10967
10968   // Make sure to set the current context to the context before the debugger was
10969   // entered (if the debugger is entered). The reason for switching context here
10970   // is that for some property lookups (accessors and interceptors) callbacks
10971   // into the embedding application can occour, and the embedding application
10972   // could have the assumption that its own native context is the current
10973   // context and not some internal debugger context.
10974   SaveContext save(isolate);
10975   if (isolate->debug()->InDebugger()) {
10976     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10977   }
10978
10979   // Skip the global proxy as it has no properties and always delegates to the
10980   // real global object.
10981   if (obj->IsJSGlobalProxy()) {
10982     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10983   }
10984
10985
10986   // Check if the name is trivially convertible to an index and get the element
10987   // if so.
10988   uint32_t index;
10989   if (name->AsArrayIndex(&index)) {
10990     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10991     Handle<Object> element_or_char =
10992         Runtime::GetElementOrCharAt(isolate, obj, index);
10993     RETURN_IF_EMPTY_HANDLE(isolate, element_or_char);
10994     details->set(0, *element_or_char);
10995     details->set(
10996         1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
10997     return *isolate->factory()->NewJSArrayWithElements(details);
10998   }
10999
11000   // Find the number of objects making up this.
11001   int length = LocalPrototypeChainLength(*obj);
11002
11003   // Try local lookup on each of the objects.
11004   Handle<JSObject> jsproto = obj;
11005   for (int i = 0; i < length; i++) {
11006     LookupResult result(isolate);
11007     jsproto->LocalLookup(*name, &result);
11008     if (result.IsFound()) {
11009       // LookupResult is not GC safe as it holds raw object pointers.
11010       // GC can happen later in this code so put the required fields into
11011       // local variables using handles when required for later use.
11012       Handle<Object> result_callback_obj;
11013       if (result.IsPropertyCallbacks()) {
11014         result_callback_obj = Handle<Object>(result.GetCallbackObject(),
11015                                              isolate);
11016       }
11017       Smi* property_details = result.GetPropertyDetails().AsSmi();
11018       // DebugLookupResultValue can cause GC so details from LookupResult needs
11019       // to be copied to handles before this.
11020       bool caught_exception = false;
11021       Object* raw_value;
11022       { MaybeObject* maybe_raw_value =
11023             DebugLookupResultValue(isolate->heap(), *obj, *name,
11024                                    &result, &caught_exception);
11025         if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
11026       }
11027       Handle<Object> value(raw_value, isolate);
11028
11029       // If the callback object is a fixed array then it contains JavaScript
11030       // getter and/or setter.
11031       bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
11032                                     result_callback_obj->IsAccessorPair();
11033       Handle<FixedArray> details =
11034           isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
11035       details->set(0, *value);
11036       details->set(1, property_details);
11037       if (hasJavaScriptAccessors) {
11038         AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
11039         details->set(2, isolate->heap()->ToBoolean(caught_exception));
11040         details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
11041         details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
11042       }
11043
11044       return *isolate->factory()->NewJSArrayWithElements(details);
11045     }
11046     if (i < length - 1) {
11047       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
11048     }
11049   }
11050
11051   return isolate->heap()->undefined_value();
11052 }
11053
11054
11055 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
11056   HandleScope scope(isolate);
11057
11058   ASSERT(args.length() == 2);
11059
11060   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11061   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
11062
11063   LookupResult result(isolate);
11064   obj->Lookup(*name, &result);
11065   if (result.IsFound()) {
11066     return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
11067   }
11068   return isolate->heap()->undefined_value();
11069 }
11070
11071
11072 // Return the property type calculated from the property details.
11073 // args[0]: smi with property details.
11074 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
11075   SealHandleScope shs(isolate);
11076   ASSERT(args.length() == 1);
11077   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11078   return Smi::FromInt(static_cast<int>(details.type()));
11079 }
11080
11081
11082 // Return the property attribute calculated from the property details.
11083 // args[0]: smi with property details.
11084 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
11085   SealHandleScope shs(isolate);
11086   ASSERT(args.length() == 1);
11087   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11088   return Smi::FromInt(static_cast<int>(details.attributes()));
11089 }
11090
11091
11092 // Return the property insertion index calculated from the property details.
11093 // args[0]: smi with property details.
11094 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
11095   SealHandleScope shs(isolate);
11096   ASSERT(args.length() == 1);
11097   CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
11098   // TODO(verwaest): Depends on the type of details.
11099   return Smi::FromInt(details.dictionary_index());
11100 }
11101
11102
11103 // Return property value from named interceptor.
11104 // args[0]: object
11105 // args[1]: property name
11106 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
11107   HandleScope scope(isolate);
11108   ASSERT(args.length() == 2);
11109   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11110   RUNTIME_ASSERT(obj->HasNamedInterceptor());
11111   CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
11112
11113   PropertyAttributes attributes;
11114   Handle<Object> result =
11115       JSObject::GetPropertyWithInterceptor(obj, obj, name, &attributes);
11116   RETURN_IF_EMPTY_HANDLE(isolate, result);
11117   return *result;
11118 }
11119
11120
11121 // Return element value from indexed interceptor.
11122 // args[0]: object
11123 // args[1]: index
11124 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
11125   HandleScope scope(isolate);
11126   ASSERT(args.length() == 2);
11127   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11128   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
11129   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
11130   Handle<Object> result = JSObject::GetElementWithInterceptor(obj, obj, index);
11131   RETURN_IF_EMPTY_HANDLE(isolate, result);
11132   return *result;
11133 }
11134
11135
11136 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
11137   SealHandleScope shs(isolate);
11138   ASSERT(args.length() >= 1);
11139   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11140   // Check that the break id is valid.
11141   if (isolate->debug()->break_id() == 0 ||
11142       break_id != isolate->debug()->break_id()) {
11143     return isolate->Throw(
11144         isolate->heap()->illegal_execution_state_string());
11145   }
11146
11147   return isolate->heap()->true_value();
11148 }
11149
11150
11151 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
11152   HandleScope scope(isolate);
11153   ASSERT(args.length() == 1);
11154
11155   // Check arguments.
11156   Object* result;
11157   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11158       RUNTIME_ARGUMENTS(isolate, args));
11159     if (!maybe_result->ToObject(&result)) return maybe_result;
11160   }
11161
11162   // Count all frames which are relevant to debugging stack trace.
11163   int n = 0;
11164   StackFrame::Id id = isolate->debug()->break_frame_id();
11165   if (id == StackFrame::NO_ID) {
11166     // If there is no JavaScript stack frame count is 0.
11167     return Smi::FromInt(0);
11168   }
11169
11170   for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
11171     n += it.frame()->GetInlineCount();
11172   }
11173   return Smi::FromInt(n);
11174 }
11175
11176
11177 class FrameInspector {
11178  public:
11179   FrameInspector(JavaScriptFrame* frame,
11180                  int inlined_jsframe_index,
11181                  Isolate* isolate)
11182       : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
11183     // Calculate the deoptimized frame.
11184     if (frame->is_optimized()) {
11185       deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
11186           frame, inlined_jsframe_index, isolate);
11187     }
11188     has_adapted_arguments_ = frame_->has_adapted_arguments();
11189     is_bottommost_ = inlined_jsframe_index == 0;
11190     is_optimized_ = frame_->is_optimized();
11191   }
11192
11193   ~FrameInspector() {
11194     // Get rid of the calculated deoptimized frame if any.
11195     if (deoptimized_frame_ != NULL) {
11196       Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
11197                                                   isolate_);
11198     }
11199   }
11200
11201   int GetParametersCount() {
11202     return is_optimized_
11203         ? deoptimized_frame_->parameters_count()
11204         : frame_->ComputeParametersCount();
11205   }
11206   int expression_count() { return deoptimized_frame_->expression_count(); }
11207   Object* GetFunction() {
11208     return is_optimized_
11209         ? deoptimized_frame_->GetFunction()
11210         : frame_->function();
11211   }
11212   Object* GetParameter(int index) {
11213     return is_optimized_
11214         ? deoptimized_frame_->GetParameter(index)
11215         : frame_->GetParameter(index);
11216   }
11217   Object* GetExpression(int index) {
11218     return is_optimized_
11219         ? deoptimized_frame_->GetExpression(index)
11220         : frame_->GetExpression(index);
11221   }
11222   int GetSourcePosition() {
11223     return is_optimized_
11224         ? deoptimized_frame_->GetSourcePosition()
11225         : frame_->LookupCode()->SourcePosition(frame_->pc());
11226   }
11227   bool IsConstructor() {
11228     return is_optimized_ && !is_bottommost_
11229         ? deoptimized_frame_->HasConstructStub()
11230         : frame_->IsConstructor();
11231   }
11232
11233   // To inspect all the provided arguments the frame might need to be
11234   // replaced with the arguments frame.
11235   void SetArgumentsFrame(JavaScriptFrame* frame) {
11236     ASSERT(has_adapted_arguments_);
11237     frame_ = frame;
11238     is_optimized_ = frame_->is_optimized();
11239     ASSERT(!is_optimized_);
11240   }
11241
11242  private:
11243   JavaScriptFrame* frame_;
11244   DeoptimizedFrameInfo* deoptimized_frame_;
11245   Isolate* isolate_;
11246   bool is_optimized_;
11247   bool is_bottommost_;
11248   bool has_adapted_arguments_;
11249
11250   DISALLOW_COPY_AND_ASSIGN(FrameInspector);
11251 };
11252
11253
11254 static const int kFrameDetailsFrameIdIndex = 0;
11255 static const int kFrameDetailsReceiverIndex = 1;
11256 static const int kFrameDetailsFunctionIndex = 2;
11257 static const int kFrameDetailsArgumentCountIndex = 3;
11258 static const int kFrameDetailsLocalCountIndex = 4;
11259 static const int kFrameDetailsSourcePositionIndex = 5;
11260 static const int kFrameDetailsConstructCallIndex = 6;
11261 static const int kFrameDetailsAtReturnIndex = 7;
11262 static const int kFrameDetailsFlagsIndex = 8;
11263 static const int kFrameDetailsFirstDynamicIndex = 9;
11264
11265
11266 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
11267                                              JavaScriptFrame* frame) {
11268   SaveContext* save = isolate->save_context();
11269   while (save != NULL && !save->IsBelowFrame(frame)) {
11270     save = save->prev();
11271   }
11272   ASSERT(save != NULL);
11273   return save;
11274 }
11275
11276
11277 // Return an array with frame details
11278 // args[0]: number: break id
11279 // args[1]: number: frame index
11280 //
11281 // The array returned contains the following information:
11282 // 0: Frame id
11283 // 1: Receiver
11284 // 2: Function
11285 // 3: Argument count
11286 // 4: Local count
11287 // 5: Source position
11288 // 6: Constructor call
11289 // 7: Is at return
11290 // 8: Flags
11291 // Arguments name, value
11292 // Locals name, value
11293 // Return value if any
11294 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
11295   HandleScope scope(isolate);
11296   ASSERT(args.length() == 2);
11297
11298   // Check arguments.
11299   Object* check;
11300   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11301       RUNTIME_ARGUMENTS(isolate, args));
11302     if (!maybe_check->ToObject(&check)) return maybe_check;
11303   }
11304   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11305   Heap* heap = isolate->heap();
11306
11307   // Find the relevant frame with the requested index.
11308   StackFrame::Id id = isolate->debug()->break_frame_id();
11309   if (id == StackFrame::NO_ID) {
11310     // If there are no JavaScript stack frames return undefined.
11311     return heap->undefined_value();
11312   }
11313
11314   int count = 0;
11315   JavaScriptFrameIterator it(isolate, id);
11316   for (; !it.done(); it.Advance()) {
11317     if (index < count + it.frame()->GetInlineCount()) break;
11318     count += it.frame()->GetInlineCount();
11319   }
11320   if (it.done()) return heap->undefined_value();
11321
11322   bool is_optimized = it.frame()->is_optimized();
11323
11324   int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
11325   if (is_optimized) {
11326     inlined_jsframe_index =
11327         it.frame()->GetInlineCount() - (index - count) - 1;
11328   }
11329   FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11330
11331   // Traverse the saved contexts chain to find the active context for the
11332   // selected frame.
11333   SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11334
11335   // Get the frame id.
11336   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11337
11338   // Find source position in unoptimized code.
11339   int position = frame_inspector.GetSourcePosition();
11340
11341   // Check for constructor frame.
11342   bool constructor = frame_inspector.IsConstructor();
11343
11344   // Get scope info and read from it for local variable information.
11345   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11346   Handle<SharedFunctionInfo> shared(function->shared());
11347   Handle<ScopeInfo> scope_info(shared->scope_info());
11348   ASSERT(*scope_info != ScopeInfo::Empty(isolate));
11349
11350   // Get the locals names and values into a temporary array.
11351   //
11352   // TODO(1240907): Hide compiler-introduced stack variables
11353   // (e.g. .result)?  For users of the debugger, they will probably be
11354   // confusing.
11355   Handle<FixedArray> locals =
11356       isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
11357
11358   // Fill in the values of the locals.
11359   int i = 0;
11360   for (; i < scope_info->StackLocalCount(); ++i) {
11361     // Use the value from the stack.
11362     locals->set(i * 2, scope_info->LocalName(i));
11363     locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
11364   }
11365   if (i < scope_info->LocalCount()) {
11366     // Get the context containing declarations.
11367     Handle<Context> context(
11368         Context::cast(it.frame()->context())->declaration_context());
11369     for (; i < scope_info->LocalCount(); ++i) {
11370       Handle<String> name(scope_info->LocalName(i));
11371       VariableMode mode;
11372       InitializationFlag init_flag;
11373       locals->set(i * 2, *name);
11374       int context_slot_index =
11375           scope_info->ContextSlotIndex(*name, &mode, &init_flag);
11376       Object* value = context->get(context_slot_index);
11377       locals->set(i * 2 + 1, value);
11378     }
11379   }
11380
11381   // Check whether this frame is positioned at return. If not top
11382   // frame or if the frame is optimized it cannot be at a return.
11383   bool at_return = false;
11384   if (!is_optimized && index == 0) {
11385     at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11386   }
11387
11388   // If positioned just before return find the value to be returned and add it
11389   // to the frame information.
11390   Handle<Object> return_value = isolate->factory()->undefined_value();
11391   if (at_return) {
11392     StackFrameIterator it2(isolate);
11393     Address internal_frame_sp = NULL;
11394     while (!it2.done()) {
11395       if (it2.frame()->is_internal()) {
11396         internal_frame_sp = it2.frame()->sp();
11397       } else {
11398         if (it2.frame()->is_java_script()) {
11399           if (it2.frame()->id() == it.frame()->id()) {
11400             // The internal frame just before the JavaScript frame contains the
11401             // value to return on top. A debug break at return will create an
11402             // internal frame to store the return value (eax/rax/r0) before
11403             // entering the debug break exit frame.
11404             if (internal_frame_sp != NULL) {
11405               return_value =
11406                   Handle<Object>(Memory::Object_at(internal_frame_sp),
11407                                  isolate);
11408               break;
11409             }
11410           }
11411         }
11412
11413         // Indicate that the previous frame was not an internal frame.
11414         internal_frame_sp = NULL;
11415       }
11416       it2.Advance();
11417     }
11418   }
11419
11420   // Now advance to the arguments adapter frame (if any). It contains all
11421   // the provided parameters whereas the function frame always have the number
11422   // of arguments matching the functions parameters. The rest of the
11423   // information (except for what is collected above) is the same.
11424   if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11425     it.AdvanceToArgumentsFrame();
11426     frame_inspector.SetArgumentsFrame(it.frame());
11427   }
11428
11429   // Find the number of arguments to fill. At least fill the number of
11430   // parameters for the function and fill more if more parameters are provided.
11431   int argument_count = scope_info->ParameterCount();
11432   if (argument_count < frame_inspector.GetParametersCount()) {
11433     argument_count = frame_inspector.GetParametersCount();
11434   }
11435
11436   // Calculate the size of the result.
11437   int details_size = kFrameDetailsFirstDynamicIndex +
11438                      2 * (argument_count + scope_info->LocalCount()) +
11439                      (at_return ? 1 : 0);
11440   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11441
11442   // Add the frame id.
11443   details->set(kFrameDetailsFrameIdIndex, *frame_id);
11444
11445   // Add the function (same as in function frame).
11446   details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11447
11448   // Add the arguments count.
11449   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11450
11451   // Add the locals count
11452   details->set(kFrameDetailsLocalCountIndex,
11453                Smi::FromInt(scope_info->LocalCount()));
11454
11455   // Add the source position.
11456   if (position != RelocInfo::kNoPosition) {
11457     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11458   } else {
11459     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11460   }
11461
11462   // Add the constructor information.
11463   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11464
11465   // Add the at return information.
11466   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11467
11468   // Add flags to indicate information on whether this frame is
11469   //   bit 0: invoked in the debugger context.
11470   //   bit 1: optimized frame.
11471   //   bit 2: inlined in optimized frame
11472   int flags = 0;
11473   if (*save->context() == *isolate->debug()->debug_context()) {
11474     flags |= 1 << 0;
11475   }
11476   if (is_optimized) {
11477     flags |= 1 << 1;
11478     flags |= inlined_jsframe_index << 2;
11479   }
11480   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11481
11482   // Fill the dynamic part.
11483   int details_index = kFrameDetailsFirstDynamicIndex;
11484
11485   // Add arguments name and value.
11486   for (int i = 0; i < argument_count; i++) {
11487     // Name of the argument.
11488     if (i < scope_info->ParameterCount()) {
11489       details->set(details_index++, scope_info->ParameterName(i));
11490     } else {
11491       details->set(details_index++, heap->undefined_value());
11492     }
11493
11494     // Parameter value.
11495     if (i < frame_inspector.GetParametersCount()) {
11496       // Get the value from the stack.
11497       details->set(details_index++, frame_inspector.GetParameter(i));
11498     } else {
11499       details->set(details_index++, heap->undefined_value());
11500     }
11501   }
11502
11503   // Add locals name and value from the temporary copy from the function frame.
11504   for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
11505     details->set(details_index++, locals->get(i));
11506   }
11507
11508   // Add the value being returned.
11509   if (at_return) {
11510     details->set(details_index++, *return_value);
11511   }
11512
11513   // Add the receiver (same as in function frame).
11514   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11515   // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11516   Handle<Object> receiver(it.frame()->receiver(), isolate);
11517   if (!receiver->IsJSObject() &&
11518       shared->strict_mode() == SLOPPY &&
11519       !function->IsBuiltin()) {
11520     // If the receiver is not a JSObject and the function is not a
11521     // builtin or strict-mode we have hit an optimization where a
11522     // value object is not converted into a wrapped JS objects. To
11523     // hide this optimization from the debugger, we wrap the receiver
11524     // by creating correct wrapper object based on the calling frame's
11525     // native context.
11526     it.Advance();
11527     if (receiver->IsUndefined()) {
11528       Context* context = function->context();
11529       receiver = handle(context->global_object()->global_receiver());
11530     } else {
11531       ASSERT(!receiver->IsNull());
11532       Context* context = Context::cast(it.frame()->context());
11533       Handle<Context> native_context(Context::cast(context->native_context()));
11534       receiver = isolate->factory()->ToObject(receiver, native_context);
11535     }
11536   }
11537   details->set(kFrameDetailsReceiverIndex, *receiver);
11538
11539   ASSERT_EQ(details_size, details_index);
11540   return *isolate->factory()->NewJSArrayWithElements(details);
11541 }
11542
11543
11544 static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
11545                                               int index) {
11546   VariableMode mode;
11547   InitializationFlag flag;
11548   return info->ContextSlotIndex(info->ParameterName(index), &mode, &flag) != -1;
11549 }
11550
11551
11552 // Create a plain JSObject which materializes the local scope for the specified
11553 // frame.
11554 static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
11555     Isolate* isolate,
11556     Handle<JSObject> target,
11557     Handle<JSFunction> function,
11558     FrameInspector* frame_inspector) {
11559   Handle<SharedFunctionInfo> shared(function->shared());
11560   Handle<ScopeInfo> scope_info(shared->scope_info());
11561
11562   // First fill all parameters.
11563   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11564     // Do not materialize the parameter if it is shadowed by a context local.
11565     if (ParameterIsShadowedByContextLocal(scope_info, i)) continue;
11566
11567     HandleScope scope(isolate);
11568     Handle<Object> value(i < frame_inspector->GetParametersCount()
11569                              ? frame_inspector->GetParameter(i)
11570                              : isolate->heap()->undefined_value(),
11571                          isolate);
11572     ASSERT(!value->IsTheHole());
11573     Handle<String> name(scope_info->ParameterName(i));
11574
11575     RETURN_IF_EMPTY_HANDLE_VALUE(
11576         isolate,
11577         Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
11578         Handle<JSObject>());
11579   }
11580
11581   // Second fill all stack locals.
11582   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11583     Handle<String> name(scope_info->StackLocalName(i));
11584     Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11585     if (value->IsTheHole()) continue;
11586
11587     RETURN_IF_EMPTY_HANDLE_VALUE(
11588         isolate,
11589         Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
11590         Handle<JSObject>());
11591   }
11592
11593   return target;
11594 }
11595
11596
11597 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11598                                                     Handle<JSObject> target,
11599                                                     Handle<JSFunction> function,
11600                                                     JavaScriptFrame* frame,
11601                                                     int inlined_jsframe_index) {
11602   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11603     // Optimized frames are not supported.
11604     // TODO(yangguo): make sure all code deoptimized when debugger is active
11605     //                and assert that this cannot happen.
11606     return;
11607   }
11608
11609   Handle<SharedFunctionInfo> shared(function->shared());
11610   Handle<ScopeInfo> scope_info(shared->scope_info());
11611
11612   // Parameters.
11613   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11614     // Shadowed parameters were not materialized.
11615     if (ParameterIsShadowedByContextLocal(scope_info, i)) continue;
11616
11617     ASSERT(!frame->GetParameter(i)->IsTheHole());
11618     HandleScope scope(isolate);
11619     Handle<String> name(scope_info->ParameterName(i));
11620     Handle<Object> value = GetProperty(isolate, target, name);
11621     frame->SetParameterValue(i, *value);
11622   }
11623
11624   // Stack locals.
11625   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11626     if (frame->GetExpression(i)->IsTheHole()) continue;
11627     HandleScope scope(isolate);
11628     Handle<Object> value = GetProperty(
11629         isolate, target, Handle<String>(scope_info->StackLocalName(i)));
11630     frame->SetExpression(i, *value);
11631   }
11632 }
11633
11634
11635 static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
11636                                                 Handle<JSObject> target,
11637                                                 Handle<JSFunction> function,
11638                                                 JavaScriptFrame* frame) {
11639   HandleScope scope(isolate);
11640   Handle<SharedFunctionInfo> shared(function->shared());
11641   Handle<ScopeInfo> scope_info(shared->scope_info());
11642
11643   if (!scope_info->HasContext()) return target;
11644
11645   // Third fill all context locals.
11646   Handle<Context> frame_context(Context::cast(frame->context()));
11647   Handle<Context> function_context(frame_context->declaration_context());
11648   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11649           scope_info, function_context, target)) {
11650     return Handle<JSObject>();
11651   }
11652
11653   // Finally copy any properties from the function context extension.
11654   // These will be variables introduced by eval.
11655   if (function_context->closure() == *function) {
11656     if (function_context->has_extension() &&
11657         !function_context->IsNativeContext()) {
11658       Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11659       bool threw = false;
11660       Handle<FixedArray> keys =
11661           GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11662       if (threw) return Handle<JSObject>();
11663
11664       for (int i = 0; i < keys->length(); i++) {
11665         // Names of variables introduced by eval are strings.
11666         ASSERT(keys->get(i)->IsString());
11667         Handle<String> key(String::cast(keys->get(i)));
11668         RETURN_IF_EMPTY_HANDLE_VALUE(
11669             isolate,
11670             Runtime::SetObjectProperty(isolate,
11671                                        target,
11672                                        key,
11673                                        GetProperty(isolate, ext, key),
11674                                        NONE,
11675                                        SLOPPY),
11676             Handle<JSObject>());
11677       }
11678     }
11679   }
11680
11681   return target;
11682 }
11683
11684
11685 static Handle<JSObject> MaterializeLocalScope(
11686     Isolate* isolate,
11687     JavaScriptFrame* frame,
11688     int inlined_jsframe_index) {
11689   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11690   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11691
11692   Handle<JSObject> local_scope =
11693       isolate->factory()->NewJSObject(isolate->object_function());
11694   local_scope = MaterializeStackLocalsWithFrameInspector(
11695                     isolate, local_scope, function, &frame_inspector);
11696   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
11697
11698   return MaterializeLocalContext(isolate, local_scope, function, frame);
11699 }
11700
11701
11702 // Set the context local variable value.
11703 static bool SetContextLocalValue(Isolate* isolate,
11704                                  Handle<ScopeInfo> scope_info,
11705                                  Handle<Context> context,
11706                                  Handle<String> variable_name,
11707                                  Handle<Object> new_value) {
11708   for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11709     Handle<String> next_name(scope_info->ContextLocalName(i));
11710     if (variable_name->Equals(*next_name)) {
11711       VariableMode mode;
11712       InitializationFlag init_flag;
11713       int context_index =
11714           scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
11715       context->set(context_index, *new_value);
11716       return true;
11717     }
11718   }
11719
11720   return false;
11721 }
11722
11723
11724 static bool SetLocalVariableValue(Isolate* isolate,
11725                                   JavaScriptFrame* frame,
11726                                   int inlined_jsframe_index,
11727                                   Handle<String> variable_name,
11728                                   Handle<Object> new_value) {
11729   if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11730     // Optimized frames are not supported.
11731     return false;
11732   }
11733
11734   Handle<JSFunction> function(frame->function());
11735   Handle<SharedFunctionInfo> shared(function->shared());
11736   Handle<ScopeInfo> scope_info(shared->scope_info());
11737
11738   bool default_result = false;
11739
11740   // Parameters.
11741   for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11742     if (scope_info->ParameterName(i)->Equals(*variable_name)) {
11743       frame->SetParameterValue(i, *new_value);
11744       // Argument might be shadowed in heap context, don't stop here.
11745       default_result = true;
11746     }
11747   }
11748
11749   // Stack locals.
11750   for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11751     if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
11752       frame->SetExpression(i, *new_value);
11753       return true;
11754     }
11755   }
11756
11757   if (scope_info->HasContext()) {
11758     // Context locals.
11759     Handle<Context> frame_context(Context::cast(frame->context()));
11760     Handle<Context> function_context(frame_context->declaration_context());
11761     if (SetContextLocalValue(
11762         isolate, scope_info, function_context, variable_name, new_value)) {
11763       return true;
11764     }
11765
11766     // Function context extension. These are variables introduced by eval.
11767     if (function_context->closure() == *function) {
11768       if (function_context->has_extension() &&
11769           !function_context->IsNativeContext()) {
11770         Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11771
11772         if (JSReceiver::HasProperty(ext, variable_name)) {
11773           // We don't expect this to do anything except replacing
11774           // property value.
11775           Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11776                                      NONE, SLOPPY);
11777           return true;
11778         }
11779       }
11780     }
11781   }
11782
11783   return default_result;
11784 }
11785
11786
11787 // Create a plain JSObject which materializes the closure content for the
11788 // context.
11789 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
11790                                            Handle<Context> context) {
11791   ASSERT(context->IsFunctionContext());
11792
11793   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11794   Handle<ScopeInfo> scope_info(shared->scope_info());
11795
11796   // Allocate and initialize a JSObject with all the content of this function
11797   // closure.
11798   Handle<JSObject> closure_scope =
11799       isolate->factory()->NewJSObject(isolate->object_function());
11800
11801   // Fill all context locals to the context extension.
11802   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11803           scope_info, context, closure_scope)) {
11804     return Handle<JSObject>();
11805   }
11806
11807   // Finally copy any properties from the function context extension. This will
11808   // be variables introduced by eval.
11809   if (context->has_extension()) {
11810     Handle<JSObject> ext(JSObject::cast(context->extension()));
11811     bool threw = false;
11812     Handle<FixedArray> keys =
11813         GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11814     if (threw) return Handle<JSObject>();
11815
11816     for (int i = 0; i < keys->length(); i++) {
11817       // Names of variables introduced by eval are strings.
11818       ASSERT(keys->get(i)->IsString());
11819       Handle<String> key(String::cast(keys->get(i)));
11820        RETURN_IF_EMPTY_HANDLE_VALUE(
11821           isolate,
11822           Runtime::SetObjectProperty(isolate, closure_scope, key,
11823                                      GetProperty(isolate, ext, key),
11824                                      NONE, SLOPPY),
11825           Handle<JSObject>());
11826     }
11827   }
11828
11829   return closure_scope;
11830 }
11831
11832
11833 // This method copies structure of MaterializeClosure method above.
11834 static bool SetClosureVariableValue(Isolate* isolate,
11835                                     Handle<Context> context,
11836                                     Handle<String> variable_name,
11837                                     Handle<Object> new_value) {
11838   ASSERT(context->IsFunctionContext());
11839
11840   Handle<SharedFunctionInfo> shared(context->closure()->shared());
11841   Handle<ScopeInfo> scope_info(shared->scope_info());
11842
11843   // Context locals to the context extension.
11844   if (SetContextLocalValue(
11845           isolate, scope_info, context, variable_name, new_value)) {
11846     return true;
11847   }
11848
11849   // Properties from the function context extension. This will
11850   // be variables introduced by eval.
11851   if (context->has_extension()) {
11852     Handle<JSObject> ext(JSObject::cast(context->extension()));
11853     if (JSReceiver::HasProperty(ext, variable_name)) {
11854       // We don't expect this to do anything except replacing property value.
11855       Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11856                                  NONE, SLOPPY);
11857       return true;
11858     }
11859   }
11860
11861   return false;
11862 }
11863
11864
11865 // Create a plain JSObject which materializes the scope for the specified
11866 // catch context.
11867 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11868                                               Handle<Context> context) {
11869   ASSERT(context->IsCatchContext());
11870   Handle<String> name(String::cast(context->extension()));
11871   Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11872                                isolate);
11873   Handle<JSObject> catch_scope =
11874       isolate->factory()->NewJSObject(isolate->object_function());
11875   RETURN_IF_EMPTY_HANDLE_VALUE(
11876       isolate,
11877       Runtime::SetObjectProperty(isolate, catch_scope, name, thrown_object,
11878                                  NONE, SLOPPY),
11879       Handle<JSObject>());
11880   return catch_scope;
11881 }
11882
11883
11884 static bool SetCatchVariableValue(Isolate* isolate,
11885                                   Handle<Context> context,
11886                                   Handle<String> variable_name,
11887                                   Handle<Object> new_value) {
11888   ASSERT(context->IsCatchContext());
11889   Handle<String> name(String::cast(context->extension()));
11890   if (!name->Equals(*variable_name)) {
11891     return false;
11892   }
11893   context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11894   return true;
11895 }
11896
11897
11898 // Create a plain JSObject which materializes the block scope for the specified
11899 // block context.
11900 static Handle<JSObject> MaterializeBlockScope(
11901     Isolate* isolate,
11902     Handle<Context> context) {
11903   ASSERT(context->IsBlockContext());
11904   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11905
11906   // Allocate and initialize a JSObject with all the arguments, stack locals
11907   // heap locals and extension properties of the debugged function.
11908   Handle<JSObject> block_scope =
11909       isolate->factory()->NewJSObject(isolate->object_function());
11910
11911   // Fill all context locals.
11912   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11913           scope_info, context, block_scope)) {
11914     return Handle<JSObject>();
11915   }
11916
11917   return block_scope;
11918 }
11919
11920
11921 // Create a plain JSObject which materializes the module scope for the specified
11922 // module context.
11923 static Handle<JSObject> MaterializeModuleScope(
11924     Isolate* isolate,
11925     Handle<Context> context) {
11926   ASSERT(context->IsModuleContext());
11927   Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11928
11929   // Allocate and initialize a JSObject with all the members of the debugged
11930   // module.
11931   Handle<JSObject> module_scope =
11932       isolate->factory()->NewJSObject(isolate->object_function());
11933
11934   // Fill all context locals.
11935   if (!ScopeInfo::CopyContextLocalsToScopeObject(
11936           scope_info, context, module_scope)) {
11937     return Handle<JSObject>();
11938   }
11939
11940   return module_scope;
11941 }
11942
11943
11944 // Iterate over the actual scopes visible from a stack frame or from a closure.
11945 // The iteration proceeds from the innermost visible nested scope outwards.
11946 // All scopes are backed by an actual context except the local scope,
11947 // which is inserted "artificially" in the context chain.
11948 class ScopeIterator {
11949  public:
11950   enum ScopeType {
11951     ScopeTypeGlobal = 0,
11952     ScopeTypeLocal,
11953     ScopeTypeWith,
11954     ScopeTypeClosure,
11955     ScopeTypeCatch,
11956     ScopeTypeBlock,
11957     ScopeTypeModule
11958   };
11959
11960   ScopeIterator(Isolate* isolate,
11961                 JavaScriptFrame* frame,
11962                 int inlined_jsframe_index,
11963                 bool ignore_nested_scopes = false)
11964     : isolate_(isolate),
11965       frame_(frame),
11966       inlined_jsframe_index_(inlined_jsframe_index),
11967       function_(frame->function()),
11968       context_(Context::cast(frame->context())),
11969       nested_scope_chain_(4),
11970       failed_(false) {
11971
11972     // Catch the case when the debugger stops in an internal function.
11973     Handle<SharedFunctionInfo> shared_info(function_->shared());
11974     Handle<ScopeInfo> scope_info(shared_info->scope_info());
11975     if (shared_info->script() == isolate->heap()->undefined_value()) {
11976       while (context_->closure() == *function_) {
11977         context_ = Handle<Context>(context_->previous(), isolate_);
11978       }
11979       return;
11980     }
11981
11982     // Get the debug info (create it if it does not exist).
11983     if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
11984       // Return if ensuring debug info failed.
11985       return;
11986     }
11987
11988     // Currently it takes too much time to find nested scopes due to script
11989     // parsing. Sometimes we want to run the ScopeIterator as fast as possible
11990     // (for example, while collecting async call stacks on every
11991     // addEventListener call), even if we drop some nested scopes.
11992     // Later we may optimize getting the nested scopes (cache the result?)
11993     // and include nested scopes into the "fast" iteration case as well.
11994     if (!ignore_nested_scopes) {
11995       Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11996
11997       // Find the break point where execution has stopped.
11998       BreakLocationIterator break_location_iterator(debug_info,
11999                                                     ALL_BREAK_LOCATIONS);
12000       // pc points to the instruction after the current one, possibly a break
12001       // location as well. So the "- 1" to exclude it from the search.
12002       break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12003
12004       // Within the return sequence at the moment it is not possible to
12005       // get a source position which is consistent with the current scope chain.
12006       // Thus all nested with, catch and block contexts are skipped and we only
12007       // provide the function scope.
12008       ignore_nested_scopes = break_location_iterator.IsExit();
12009     }
12010
12011     if (ignore_nested_scopes) {
12012       if (scope_info->HasContext()) {
12013         context_ = Handle<Context>(context_->declaration_context(), isolate_);
12014       } else {
12015         while (context_->closure() == *function_) {
12016           context_ = Handle<Context>(context_->previous(), isolate_);
12017         }
12018       }
12019       if (scope_info->scope_type() == FUNCTION_SCOPE) {
12020         nested_scope_chain_.Add(scope_info);
12021       }
12022     } else {
12023       // Reparse the code and analyze the scopes.
12024       Handle<Script> script(Script::cast(shared_info->script()));
12025       Scope* scope = NULL;
12026
12027       // Check whether we are in global, eval or function code.
12028       Handle<ScopeInfo> scope_info(shared_info->scope_info());
12029       if (scope_info->scope_type() != FUNCTION_SCOPE) {
12030         // Global or eval code.
12031         CompilationInfoWithZone info(script);
12032         if (scope_info->scope_type() == GLOBAL_SCOPE) {
12033           info.MarkAsGlobal();
12034         } else {
12035           ASSERT(scope_info->scope_type() == EVAL_SCOPE);
12036           info.MarkAsEval();
12037           info.SetContext(Handle<Context>(function_->context()));
12038         }
12039         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
12040           scope = info.function()->scope();
12041         }
12042         RetrieveScopeChain(scope, shared_info);
12043       } else {
12044         // Function code
12045         CompilationInfoWithZone info(shared_info);
12046         if (Parser::Parse(&info) && Scope::Analyze(&info)) {
12047           scope = info.function()->scope();
12048         }
12049         RetrieveScopeChain(scope, shared_info);
12050       }
12051     }
12052   }
12053
12054   ScopeIterator(Isolate* isolate,
12055                 Handle<JSFunction> function)
12056     : isolate_(isolate),
12057       frame_(NULL),
12058       inlined_jsframe_index_(0),
12059       function_(function),
12060       context_(function->context()),
12061       failed_(false) {
12062     if (function->IsBuiltin()) {
12063       context_ = Handle<Context>();
12064     }
12065   }
12066
12067   // More scopes?
12068   bool Done() {
12069     ASSERT(!failed_);
12070     return context_.is_null();
12071   }
12072
12073   bool Failed() { return failed_; }
12074
12075   // Move to the next scope.
12076   void Next() {
12077     ASSERT(!failed_);
12078     ScopeType scope_type = Type();
12079     if (scope_type == ScopeTypeGlobal) {
12080       // The global scope is always the last in the chain.
12081       ASSERT(context_->IsNativeContext());
12082       context_ = Handle<Context>();
12083       return;
12084     }
12085     if (nested_scope_chain_.is_empty()) {
12086       context_ = Handle<Context>(context_->previous(), isolate_);
12087     } else {
12088       if (nested_scope_chain_.last()->HasContext()) {
12089         ASSERT(context_->previous() != NULL);
12090         context_ = Handle<Context>(context_->previous(), isolate_);
12091       }
12092       nested_scope_chain_.RemoveLast();
12093     }
12094   }
12095
12096   // Return the type of the current scope.
12097   ScopeType Type() {
12098     ASSERT(!failed_);
12099     if (!nested_scope_chain_.is_empty()) {
12100       Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
12101       switch (scope_info->scope_type()) {
12102         case FUNCTION_SCOPE:
12103           ASSERT(context_->IsFunctionContext() ||
12104                  !scope_info->HasContext());
12105           return ScopeTypeLocal;
12106         case MODULE_SCOPE:
12107           ASSERT(context_->IsModuleContext());
12108           return ScopeTypeModule;
12109         case GLOBAL_SCOPE:
12110           ASSERT(context_->IsNativeContext());
12111           return ScopeTypeGlobal;
12112         case WITH_SCOPE:
12113           ASSERT(context_->IsWithContext());
12114           return ScopeTypeWith;
12115         case CATCH_SCOPE:
12116           ASSERT(context_->IsCatchContext());
12117           return ScopeTypeCatch;
12118         case BLOCK_SCOPE:
12119           ASSERT(!scope_info->HasContext() ||
12120                  context_->IsBlockContext());
12121           return ScopeTypeBlock;
12122         case EVAL_SCOPE:
12123           UNREACHABLE();
12124       }
12125     }
12126     if (context_->IsNativeContext()) {
12127       ASSERT(context_->global_object()->IsGlobalObject());
12128       return ScopeTypeGlobal;
12129     }
12130     if (context_->IsFunctionContext()) {
12131       return ScopeTypeClosure;
12132     }
12133     if (context_->IsCatchContext()) {
12134       return ScopeTypeCatch;
12135     }
12136     if (context_->IsBlockContext()) {
12137       return ScopeTypeBlock;
12138     }
12139     if (context_->IsModuleContext()) {
12140       return ScopeTypeModule;
12141     }
12142     ASSERT(context_->IsWithContext());
12143     return ScopeTypeWith;
12144   }
12145
12146   // Return the JavaScript object with the content of the current scope.
12147   Handle<JSObject> ScopeObject() {
12148     ASSERT(!failed_);
12149     switch (Type()) {
12150       case ScopeIterator::ScopeTypeGlobal:
12151         return Handle<JSObject>(CurrentContext()->global_object());
12152       case ScopeIterator::ScopeTypeLocal:
12153         // Materialize the content of the local scope into a JSObject.
12154         ASSERT(nested_scope_chain_.length() == 1);
12155         return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
12156       case ScopeIterator::ScopeTypeWith:
12157         // Return the with object.
12158         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
12159       case ScopeIterator::ScopeTypeCatch:
12160         return MaterializeCatchScope(isolate_, CurrentContext());
12161       case ScopeIterator::ScopeTypeClosure:
12162         // Materialize the content of the closure scope into a JSObject.
12163         return MaterializeClosure(isolate_, CurrentContext());
12164       case ScopeIterator::ScopeTypeBlock:
12165         return MaterializeBlockScope(isolate_, CurrentContext());
12166       case ScopeIterator::ScopeTypeModule:
12167         return MaterializeModuleScope(isolate_, CurrentContext());
12168     }
12169     UNREACHABLE();
12170     return Handle<JSObject>();
12171   }
12172
12173   bool SetVariableValue(Handle<String> variable_name,
12174                         Handle<Object> new_value) {
12175     ASSERT(!failed_);
12176     switch (Type()) {
12177       case ScopeIterator::ScopeTypeGlobal:
12178         break;
12179       case ScopeIterator::ScopeTypeLocal:
12180         return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
12181             variable_name, new_value);
12182       case ScopeIterator::ScopeTypeWith:
12183         break;
12184       case ScopeIterator::ScopeTypeCatch:
12185         return SetCatchVariableValue(isolate_, CurrentContext(),
12186             variable_name, new_value);
12187       case ScopeIterator::ScopeTypeClosure:
12188         return SetClosureVariableValue(isolate_, CurrentContext(),
12189             variable_name, new_value);
12190       case ScopeIterator::ScopeTypeBlock:
12191         // TODO(2399): should we implement it?
12192         break;
12193       case ScopeIterator::ScopeTypeModule:
12194         // TODO(2399): should we implement it?
12195         break;
12196     }
12197     return false;
12198   }
12199
12200   Handle<ScopeInfo> CurrentScopeInfo() {
12201     ASSERT(!failed_);
12202     if (!nested_scope_chain_.is_empty()) {
12203       return nested_scope_chain_.last();
12204     } else if (context_->IsBlockContext()) {
12205       return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
12206     } else if (context_->IsFunctionContext()) {
12207       return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
12208     }
12209     return Handle<ScopeInfo>::null();
12210   }
12211
12212   // Return the context for this scope. For the local context there might not
12213   // be an actual context.
12214   Handle<Context> CurrentContext() {
12215     ASSERT(!failed_);
12216     if (Type() == ScopeTypeGlobal ||
12217         nested_scope_chain_.is_empty()) {
12218       return context_;
12219     } else if (nested_scope_chain_.last()->HasContext()) {
12220       return context_;
12221     } else {
12222       return Handle<Context>();
12223     }
12224   }
12225
12226 #ifdef DEBUG
12227   // Debug print of the content of the current scope.
12228   void DebugPrint() {
12229     ASSERT(!failed_);
12230     switch (Type()) {
12231       case ScopeIterator::ScopeTypeGlobal:
12232         PrintF("Global:\n");
12233         CurrentContext()->Print();
12234         break;
12235
12236       case ScopeIterator::ScopeTypeLocal: {
12237         PrintF("Local:\n");
12238         function_->shared()->scope_info()->Print();
12239         if (!CurrentContext().is_null()) {
12240           CurrentContext()->Print();
12241           if (CurrentContext()->has_extension()) {
12242             Handle<Object> extension(CurrentContext()->extension(), isolate_);
12243             if (extension->IsJSContextExtensionObject()) {
12244               extension->Print();
12245             }
12246           }
12247         }
12248         break;
12249       }
12250
12251       case ScopeIterator::ScopeTypeWith:
12252         PrintF("With:\n");
12253         CurrentContext()->extension()->Print();
12254         break;
12255
12256       case ScopeIterator::ScopeTypeCatch:
12257         PrintF("Catch:\n");
12258         CurrentContext()->extension()->Print();
12259         CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
12260         break;
12261
12262       case ScopeIterator::ScopeTypeClosure:
12263         PrintF("Closure:\n");
12264         CurrentContext()->Print();
12265         if (CurrentContext()->has_extension()) {
12266           Handle<Object> extension(CurrentContext()->extension(), isolate_);
12267           if (extension->IsJSContextExtensionObject()) {
12268             extension->Print();
12269           }
12270         }
12271         break;
12272
12273       default:
12274         UNREACHABLE();
12275     }
12276     PrintF("\n");
12277   }
12278 #endif
12279
12280  private:
12281   Isolate* isolate_;
12282   JavaScriptFrame* frame_;
12283   int inlined_jsframe_index_;
12284   Handle<JSFunction> function_;
12285   Handle<Context> context_;
12286   List<Handle<ScopeInfo> > nested_scope_chain_;
12287   bool failed_;
12288
12289   void RetrieveScopeChain(Scope* scope,
12290                           Handle<SharedFunctionInfo> shared_info) {
12291     if (scope != NULL) {
12292       int source_position = shared_info->code()->SourcePosition(frame_->pc());
12293       scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
12294     } else {
12295       // A failed reparse indicates that the preparser has diverged from the
12296       // parser or that the preparse data given to the initial parse has been
12297       // faulty. We fail in debug mode but in release mode we only provide the
12298       // information we get from the context chain but nothing about
12299       // completely stack allocated scopes or stack allocated locals.
12300       // Or it could be due to stack overflow.
12301       ASSERT(isolate_->has_pending_exception());
12302       failed_ = true;
12303     }
12304   }
12305
12306   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
12307 };
12308
12309
12310 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
12311   HandleScope scope(isolate);
12312   ASSERT(args.length() == 2);
12313
12314   // Check arguments.
12315   Object* check;
12316   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12317       RUNTIME_ARGUMENTS(isolate, args));
12318     if (!maybe_check->ToObject(&check)) return maybe_check;
12319   }
12320   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12321
12322   // Get the frame where the debugging is performed.
12323   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12324   JavaScriptFrameIterator it(isolate, id);
12325   JavaScriptFrame* frame = it.frame();
12326
12327   // Count the visible scopes.
12328   int n = 0;
12329   for (ScopeIterator it(isolate, frame, 0);
12330        !it.Done();
12331        it.Next()) {
12332     n++;
12333   }
12334
12335   return Smi::FromInt(n);
12336 }
12337
12338
12339 // Returns the list of step-in positions (text offset) in a function of the
12340 // stack frame in a range from the current debug break position to the end
12341 // of the corresponding statement.
12342 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
12343   HandleScope scope(isolate);
12344   ASSERT(args.length() == 2);
12345
12346   // Check arguments.
12347   Object* check;
12348   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12349       RUNTIME_ARGUMENTS(isolate, args));
12350     if (!maybe_check->ToObject(&check)) return maybe_check;
12351   }
12352   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12353
12354   // Get the frame where the debugging is performed.
12355   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12356   JavaScriptFrameIterator frame_it(isolate, id);
12357   RUNTIME_ASSERT(!frame_it.done());
12358
12359   JavaScriptFrame* frame = frame_it.frame();
12360
12361   Handle<JSFunction> fun =
12362       Handle<JSFunction>(frame->function());
12363   Handle<SharedFunctionInfo> shared =
12364       Handle<SharedFunctionInfo>(fun->shared());
12365
12366   if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12367     return isolate->heap()->undefined_value();
12368   }
12369
12370   Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12371
12372   int len = 0;
12373   Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12374   // Find the break point where execution has stopped.
12375   BreakLocationIterator break_location_iterator(debug_info,
12376                                                 ALL_BREAK_LOCATIONS);
12377
12378   break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12379   int current_statement_pos = break_location_iterator.statement_position();
12380
12381   while (!break_location_iterator.Done()) {
12382     bool accept;
12383     if (break_location_iterator.pc() > frame->pc()) {
12384       accept = true;
12385     } else {
12386       StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
12387       // The break point is near our pc. Could be a step-in possibility,
12388       // that is currently taken by active debugger call.
12389       if (break_frame_id == StackFrame::NO_ID) {
12390         // We are not stepping.
12391         accept = false;
12392       } else {
12393         JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id);
12394         // If our frame is a top frame and we are stepping, we can do step-in
12395         // at this place.
12396         accept = additional_frame_it.frame()->id() == id;
12397       }
12398     }
12399     if (accept) {
12400       if (break_location_iterator.IsStepInLocation(isolate)) {
12401         Smi* position_value = Smi::FromInt(break_location_iterator.position());
12402         JSObject::SetElement(array, len,
12403             Handle<Object>(position_value, isolate),
12404             NONE, SLOPPY);
12405         len++;
12406       }
12407     }
12408     // Advance iterator.
12409     break_location_iterator.Next();
12410     if (current_statement_pos !=
12411         break_location_iterator.statement_position()) {
12412       break;
12413     }
12414   }
12415   return *array;
12416 }
12417
12418
12419 static const int kScopeDetailsTypeIndex = 0;
12420 static const int kScopeDetailsObjectIndex = 1;
12421 static const int kScopeDetailsSize = 2;
12422
12423
12424 static Handle<JSObject> MaterializeScopeDetails(Isolate* isolate,
12425     ScopeIterator* it) {
12426   // Calculate the size of the result.
12427   int details_size = kScopeDetailsSize;
12428   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12429
12430   // Fill in scope details.
12431   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12432   Handle<JSObject> scope_object = it->ScopeObject();
12433   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, scope_object, Handle<JSObject>());
12434   details->set(kScopeDetailsObjectIndex, *scope_object);
12435
12436   return isolate->factory()->NewJSArrayWithElements(details);
12437 }
12438
12439
12440 // Return an array with scope details
12441 // args[0]: number: break id
12442 // args[1]: number: frame index
12443 // args[2]: number: inlined frame index
12444 // args[3]: number: scope index
12445 //
12446 // The array returned contains the following information:
12447 // 0: Scope type
12448 // 1: Scope object
12449 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
12450   HandleScope scope(isolate);
12451   ASSERT(args.length() == 4);
12452
12453   // Check arguments.
12454   Object* check;
12455   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12456       RUNTIME_ARGUMENTS(isolate, args));
12457     if (!maybe_check->ToObject(&check)) return maybe_check;
12458   }
12459   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12460   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12461   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12462
12463   // Get the frame where the debugging is performed.
12464   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12465   JavaScriptFrameIterator frame_it(isolate, id);
12466   JavaScriptFrame* frame = frame_it.frame();
12467
12468   // Find the requested scope.
12469   int n = 0;
12470   ScopeIterator it(isolate, frame, inlined_jsframe_index);
12471   for (; !it.Done() && n < index; it.Next()) {
12472     n++;
12473   }
12474   if (it.Done()) {
12475     return isolate->heap()->undefined_value();
12476   }
12477   Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
12478   RETURN_IF_EMPTY_HANDLE(isolate, details);
12479   return *details;
12480 }
12481
12482
12483 // Return an array of scope details
12484 // args[0]: number: break id
12485 // args[1]: number: frame index
12486 // args[2]: number: inlined frame index
12487 // args[3]: boolean: ignore nested scopes
12488 //
12489 // The array returned contains arrays with the following information:
12490 // 0: Scope type
12491 // 1: Scope object
12492 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAllScopesDetails) {
12493   HandleScope scope(isolate);
12494   ASSERT(args.length() == 3 || args.length() == 4);
12495
12496   // Check arguments.
12497   Object* check;
12498   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12499       RUNTIME_ARGUMENTS(isolate, args));
12500     if (!maybe_check->ToObject(&check)) return maybe_check;
12501   }
12502   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12503   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12504
12505   bool ignore_nested_scopes = false;
12506   if (args.length() == 4) {
12507     CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
12508     ignore_nested_scopes = flag;
12509   }
12510
12511   // Get the frame where the debugging is performed.
12512   StackFrame::Id id = UnwrapFrameId(wrapped_id);
12513   JavaScriptFrameIterator frame_it(isolate, id);
12514   JavaScriptFrame* frame = frame_it.frame();
12515
12516   List<Handle<JSObject> > result(4);
12517   ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes);
12518   for (; !it.Done(); it.Next()) {
12519     Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
12520     RETURN_IF_EMPTY_HANDLE(isolate, details);
12521     result.Add(details);
12522   }
12523
12524   Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
12525   for (int i = 0; i < result.length(); ++i) {
12526     array->set(i, *result[i]);
12527   }
12528   return *isolate->factory()->NewJSArrayWithElements(array);
12529 }
12530
12531
12532 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
12533   HandleScope scope(isolate);
12534   ASSERT(args.length() == 1);
12535
12536   // Check arguments.
12537   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12538
12539   // Count the visible scopes.
12540   int n = 0;
12541   for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12542     n++;
12543   }
12544
12545   return Smi::FromInt(n);
12546 }
12547
12548
12549 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
12550   HandleScope scope(isolate);
12551   ASSERT(args.length() == 2);
12552
12553   // Check arguments.
12554   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12555   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12556
12557   // Find the requested scope.
12558   int n = 0;
12559   ScopeIterator it(isolate, fun);
12560   for (; !it.Done() && n < index; it.Next()) {
12561     n++;
12562   }
12563   if (it.Done()) {
12564     return isolate->heap()->undefined_value();
12565   }
12566
12567   Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
12568   RETURN_IF_EMPTY_HANDLE(isolate, details);
12569   return *details;
12570 }
12571
12572
12573 static bool SetScopeVariableValue(ScopeIterator* it, int index,
12574                                   Handle<String> variable_name,
12575                                   Handle<Object> new_value) {
12576   for (int n = 0; !it->Done() && n < index; it->Next()) {
12577     n++;
12578   }
12579   if (it->Done()) {
12580     return false;
12581   }
12582   return it->SetVariableValue(variable_name, new_value);
12583 }
12584
12585
12586 // Change variable value in closure or local scope
12587 // args[0]: number or JsFunction: break id or function
12588 // args[1]: number: frame index (when arg[0] is break id)
12589 // args[2]: number: inlined frame index (when arg[0] is break id)
12590 // args[3]: number: scope index
12591 // args[4]: string: variable name
12592 // args[5]: object: new value
12593 //
12594 // Return true if success and false otherwise
12595 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
12596   HandleScope scope(isolate);
12597   ASSERT(args.length() == 6);
12598
12599   // Check arguments.
12600   CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12601   CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12602   Handle<Object> new_value = args.at<Object>(5);
12603
12604   bool res;
12605   if (args[0]->IsNumber()) {
12606     Object* check;
12607     { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12608         RUNTIME_ARGUMENTS(isolate, args));
12609       if (!maybe_check->ToObject(&check)) return maybe_check;
12610     }
12611     CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12612     CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12613
12614     // Get the frame where the debugging is performed.
12615     StackFrame::Id id = UnwrapFrameId(wrapped_id);
12616     JavaScriptFrameIterator frame_it(isolate, id);
12617     JavaScriptFrame* frame = frame_it.frame();
12618
12619     ScopeIterator it(isolate, frame, inlined_jsframe_index);
12620     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12621   } else {
12622     CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12623     ScopeIterator it(isolate, fun);
12624     res = SetScopeVariableValue(&it, index, variable_name, new_value);
12625   }
12626
12627   return isolate->heap()->ToBoolean(res);
12628 }
12629
12630
12631 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
12632   HandleScope scope(isolate);
12633   ASSERT(args.length() == 0);
12634
12635 #ifdef DEBUG
12636   // Print the scopes for the top frame.
12637   StackFrameLocator locator(isolate);
12638   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12639   for (ScopeIterator it(isolate, frame, 0);
12640        !it.Done();
12641        it.Next()) {
12642     it.DebugPrint();
12643   }
12644 #endif
12645   return isolate->heap()->undefined_value();
12646 }
12647
12648
12649 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
12650   HandleScope scope(isolate);
12651   ASSERT(args.length() == 1);
12652
12653   // Check arguments.
12654   Object* result;
12655   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12656       RUNTIME_ARGUMENTS(isolate, args));
12657     if (!maybe_result->ToObject(&result)) return maybe_result;
12658   }
12659
12660   // Count all archived V8 threads.
12661   int n = 0;
12662   for (ThreadState* thread =
12663           isolate->thread_manager()->FirstThreadStateInUse();
12664        thread != NULL;
12665        thread = thread->Next()) {
12666     n++;
12667   }
12668
12669   // Total number of threads is current thread and archived threads.
12670   return Smi::FromInt(n + 1);
12671 }
12672
12673
12674 static const int kThreadDetailsCurrentThreadIndex = 0;
12675 static const int kThreadDetailsThreadIdIndex = 1;
12676 static const int kThreadDetailsSize = 2;
12677
12678 // Return an array with thread details
12679 // args[0]: number: break id
12680 // args[1]: number: thread index
12681 //
12682 // The array returned contains the following information:
12683 // 0: Is current thread?
12684 // 1: Thread id
12685 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
12686   HandleScope scope(isolate);
12687   ASSERT(args.length() == 2);
12688
12689   // Check arguments.
12690   Object* check;
12691   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12692       RUNTIME_ARGUMENTS(isolate, args));
12693     if (!maybe_check->ToObject(&check)) return maybe_check;
12694   }
12695   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12696
12697   // Allocate array for result.
12698   Handle<FixedArray> details =
12699       isolate->factory()->NewFixedArray(kThreadDetailsSize);
12700
12701   // Thread index 0 is current thread.
12702   if (index == 0) {
12703     // Fill the details.
12704     details->set(kThreadDetailsCurrentThreadIndex,
12705                  isolate->heap()->true_value());
12706     details->set(kThreadDetailsThreadIdIndex,
12707                  Smi::FromInt(ThreadId::Current().ToInteger()));
12708   } else {
12709     // Find the thread with the requested index.
12710     int n = 1;
12711     ThreadState* thread =
12712         isolate->thread_manager()->FirstThreadStateInUse();
12713     while (index != n && thread != NULL) {
12714       thread = thread->Next();
12715       n++;
12716     }
12717     if (thread == NULL) {
12718       return isolate->heap()->undefined_value();
12719     }
12720
12721     // Fill the details.
12722     details->set(kThreadDetailsCurrentThreadIndex,
12723                  isolate->heap()->false_value());
12724     details->set(kThreadDetailsThreadIdIndex,
12725                  Smi::FromInt(thread->id().ToInteger()));
12726   }
12727
12728   // Convert to JS array and return.
12729   return *isolate->factory()->NewJSArrayWithElements(details);
12730 }
12731
12732
12733 // Sets the disable break state
12734 // args[0]: disable break state
12735 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
12736   HandleScope scope(isolate);
12737   ASSERT(args.length() == 1);
12738   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12739   isolate->debug()->set_disable_break(disable_break);
12740   return  isolate->heap()->undefined_value();
12741 }
12742
12743
12744 static bool IsPositionAlignmentCodeCorrect(int alignment) {
12745   return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12746 }
12747
12748
12749 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
12750   HandleScope scope(isolate);
12751   ASSERT(args.length() == 2);
12752
12753   CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12754   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12755
12756   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12757     return isolate->ThrowIllegalOperation();
12758   }
12759   BreakPositionAlignment alignment =
12760       static_cast<BreakPositionAlignment>(statement_aligned_code);
12761
12762   Handle<SharedFunctionInfo> shared(fun->shared());
12763   // Find the number of break points
12764   Handle<Object> break_locations =
12765       Debug::GetSourceBreakLocations(shared, alignment);
12766   if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12767   // Return array as JS array
12768   return *isolate->factory()->NewJSArrayWithElements(
12769       Handle<FixedArray>::cast(break_locations));
12770 }
12771
12772
12773 // Set a break point in a function.
12774 // args[0]: function
12775 // args[1]: number: break source position (within the function source)
12776 // args[2]: number: break point object
12777 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
12778   HandleScope scope(isolate);
12779   ASSERT(args.length() == 3);
12780   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12781   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12782   RUNTIME_ASSERT(source_position >= 0);
12783   Handle<Object> break_point_object_arg = args.at<Object>(2);
12784
12785   // Set break point.
12786   isolate->debug()->SetBreakPoint(function, break_point_object_arg,
12787                                   &source_position);
12788
12789   return Smi::FromInt(source_position);
12790 }
12791
12792
12793 // Changes the state of a break point in a script and returns source position
12794 // where break point was set. NOTE: Regarding performance see the NOTE for
12795 // GetScriptFromScriptData.
12796 // args[0]: script to set break point in
12797 // args[1]: number: break source position (within the script source)
12798 // args[2]: number, breakpoint position alignment
12799 // args[3]: number: break point object
12800 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
12801   HandleScope scope(isolate);
12802   ASSERT(args.length() == 4);
12803   CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12804   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12805   RUNTIME_ASSERT(source_position >= 0);
12806   CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12807   Handle<Object> break_point_object_arg = args.at<Object>(3);
12808
12809   if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12810     return isolate->ThrowIllegalOperation();
12811   }
12812   BreakPositionAlignment alignment =
12813       static_cast<BreakPositionAlignment>(statement_aligned_code);
12814
12815   // Get the script from the script wrapper.
12816   RUNTIME_ASSERT(wrapper->value()->IsScript());
12817   Handle<Script> script(Script::cast(wrapper->value()));
12818
12819   // Set break point.
12820   if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12821                                                 &source_position,
12822                                                 alignment)) {
12823     return isolate->heap()->undefined_value();
12824   }
12825
12826   return Smi::FromInt(source_position);
12827 }
12828
12829
12830 // Clear a break point
12831 // args[0]: number: break point object
12832 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
12833   HandleScope scope(isolate);
12834   ASSERT(args.length() == 1);
12835   Handle<Object> break_point_object_arg = args.at<Object>(0);
12836
12837   // Clear break point.
12838   isolate->debug()->ClearBreakPoint(break_point_object_arg);
12839
12840   return isolate->heap()->undefined_value();
12841 }
12842
12843
12844 // Change the state of break on exceptions.
12845 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12846 // args[1]: Boolean indicating on/off.
12847 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
12848   HandleScope scope(isolate);
12849   ASSERT(args.length() == 2);
12850   RUNTIME_ASSERT(args[0]->IsNumber());
12851   CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12852
12853   // If the number doesn't match an enum value, the ChangeBreakOnException
12854   // function will default to affecting caught exceptions.
12855   ExceptionBreakType type =
12856       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12857   // Update break point state.
12858   isolate->debug()->ChangeBreakOnException(type, enable);
12859   return isolate->heap()->undefined_value();
12860 }
12861
12862
12863 // Returns the state of break on exceptions
12864 // args[0]: boolean indicating uncaught exceptions
12865 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
12866   HandleScope scope(isolate);
12867   ASSERT(args.length() == 1);
12868   RUNTIME_ASSERT(args[0]->IsNumber());
12869
12870   ExceptionBreakType type =
12871       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12872   bool result = isolate->debug()->IsBreakOnException(type);
12873   return Smi::FromInt(result);
12874 }
12875
12876
12877 // Prepare for stepping
12878 // args[0]: break id for checking execution state
12879 // args[1]: step action from the enumeration StepAction
12880 // args[2]: number of times to perform the step, for step out it is the number
12881 //          of frames to step down.
12882 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
12883   HandleScope scope(isolate);
12884   ASSERT(args.length() == 4);
12885   // Check arguments.
12886   Object* check;
12887   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12888       RUNTIME_ARGUMENTS(isolate, args));
12889     if (!maybe_check->ToObject(&check)) return maybe_check;
12890   }
12891   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12892     return isolate->Throw(isolate->heap()->illegal_argument_string());
12893   }
12894
12895   CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]);
12896
12897   StackFrame::Id frame_id;
12898   if (wrapped_frame_id == 0) {
12899     frame_id = StackFrame::NO_ID;
12900   } else {
12901     frame_id = UnwrapFrameId(wrapped_frame_id);
12902   }
12903
12904   // Get the step action and check validity.
12905   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12906   if (step_action != StepIn &&
12907       step_action != StepNext &&
12908       step_action != StepOut &&
12909       step_action != StepInMin &&
12910       step_action != StepMin) {
12911     return isolate->Throw(isolate->heap()->illegal_argument_string());
12912   }
12913
12914   if (frame_id != StackFrame::NO_ID && step_action != StepNext &&
12915       step_action != StepMin && step_action != StepOut) {
12916     return isolate->ThrowIllegalOperation();
12917   }
12918
12919   // Get the number of steps.
12920   int step_count = NumberToInt32(args[2]);
12921   if (step_count < 1) {
12922     return isolate->Throw(isolate->heap()->illegal_argument_string());
12923   }
12924
12925   // Clear all current stepping setup.
12926   isolate->debug()->ClearStepping();
12927
12928   // Prepare step.
12929   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12930                                 step_count,
12931                                 frame_id);
12932   return isolate->heap()->undefined_value();
12933 }
12934
12935
12936 // Clear all stepping set by PrepareStep.
12937 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
12938   HandleScope scope(isolate);
12939   ASSERT(args.length() == 0);
12940   isolate->debug()->ClearStepping();
12941   return isolate->heap()->undefined_value();
12942 }
12943
12944
12945 // Helper function to find or create the arguments object for
12946 // Runtime_DebugEvaluate.
12947 static Handle<JSObject> MaterializeArgumentsObject(
12948     Isolate* isolate,
12949     Handle<JSObject> target,
12950     Handle<JSFunction> function) {
12951   // Do not materialize the arguments object for eval or top-level code.
12952   // Skip if "arguments" is already taken.
12953   if (!function->shared()->is_function() ||
12954       JSReceiver::HasLocalProperty(target,
12955                                    isolate->factory()->arguments_string())) {
12956     return target;
12957   }
12958
12959   // FunctionGetArguments can't throw an exception.
12960   Handle<JSObject> arguments = Handle<JSObject>::cast(
12961       Accessors::FunctionGetArguments(function));
12962   Runtime::SetObjectProperty(isolate, target,
12963                              isolate->factory()->arguments_string(),
12964                              arguments,
12965                              ::NONE,
12966                              SLOPPY);
12967   return target;
12968 }
12969
12970
12971 // Compile and evaluate source for the given context.
12972 static MaybeObject* DebugEvaluate(Isolate* isolate,
12973                                   Handle<Context> context,
12974                                   Handle<Object> context_extension,
12975                                   Handle<Object> receiver,
12976                                   Handle<String> source) {
12977   if (context_extension->IsJSObject()) {
12978     Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12979     Handle<JSFunction> closure(context->closure(), isolate);
12980     context = isolate->factory()->NewWithContext(closure, context, extension);
12981   }
12982
12983   Handle<JSFunction> eval_fun =
12984       Compiler::GetFunctionFromEval(source,
12985                                     context,
12986                                     SLOPPY,
12987                                     NO_PARSE_RESTRICTION,
12988                                     RelocInfo::kNoPosition);
12989   RETURN_IF_EMPTY_HANDLE(isolate, eval_fun);
12990
12991   bool pending_exception;
12992   Handle<Object> result = Execution::Call(
12993       isolate, eval_fun, receiver, 0, NULL, &pending_exception);
12994
12995   if (pending_exception) return Failure::Exception();
12996
12997   // Skip the global proxy as it has no properties and always delegates to the
12998   // real global object.
12999   if (result->IsJSGlobalProxy()) {
13000     result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
13001   }
13002
13003   // Clear the oneshot breakpoints so that the debugger does not step further.
13004   isolate->debug()->ClearStepping();
13005   return *result;
13006 }
13007
13008
13009 // Evaluate a piece of JavaScript in the context of a stack frame for
13010 // debugging.  Things that need special attention are:
13011 // - Parameters and stack-allocated locals need to be materialized.  Altered
13012 //   values need to be written back to the stack afterwards.
13013 // - The arguments object needs to materialized.
13014 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
13015   HandleScope scope(isolate);
13016
13017   // Check the execution state and decode arguments frame and source to be
13018   // evaluated.
13019   ASSERT(args.length() == 6);
13020   Object* check_result;
13021   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
13022       RUNTIME_ARGUMENTS(isolate, args));
13023     if (!maybe_result->ToObject(&check_result)) return maybe_result;
13024   }
13025   CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
13026   CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
13027   CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
13028   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
13029   Handle<Object> context_extension(args[5], isolate);
13030
13031   // Handle the processing of break.
13032   DisableBreak disable_break_save(isolate, disable_break);
13033
13034   // Get the frame where the debugging is performed.
13035   StackFrame::Id id = UnwrapFrameId(wrapped_id);
13036   JavaScriptFrameIterator it(isolate, id);
13037   JavaScriptFrame* frame = it.frame();
13038   FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
13039   Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
13040
13041   // Traverse the saved contexts chain to find the active context for the
13042   // selected frame.
13043   SaveContext* save = FindSavedContextForFrame(isolate, frame);
13044
13045   SaveContext savex(isolate);
13046   isolate->set_context(*(save->context()));
13047
13048   // Evaluate on the context of the frame.
13049   Handle<Context> context(Context::cast(frame->context()));
13050   ASSERT(!context.is_null());
13051
13052   // Materialize stack locals and the arguments object.
13053   Handle<JSObject> materialized =
13054       isolate->factory()->NewJSObject(isolate->object_function());
13055
13056   materialized = MaterializeStackLocalsWithFrameInspector(
13057       isolate, materialized, function, &frame_inspector);
13058   RETURN_IF_EMPTY_HANDLE(isolate, materialized);
13059
13060   materialized = MaterializeArgumentsObject(isolate, materialized, function);
13061   RETURN_IF_EMPTY_HANDLE(isolate, materialized);
13062
13063   // Add the materialized object in a with-scope to shadow the stack locals.
13064   context = isolate->factory()->NewWithContext(function, context, materialized);
13065
13066   Handle<Object> receiver(frame->receiver(), isolate);
13067   Object* evaluate_result_object;
13068   { MaybeObject* maybe_result =
13069     DebugEvaluate(isolate, context, context_extension, receiver, source);
13070     if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
13071   }
13072
13073   Handle<Object> result(evaluate_result_object, isolate);
13074
13075   // Write back potential changes to materialized stack locals to the stack.
13076   UpdateStackLocalsFromMaterializedObject(
13077       isolate, materialized, function, frame, inlined_jsframe_index);
13078
13079   return *result;
13080 }
13081
13082
13083 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
13084   HandleScope scope(isolate);
13085
13086   // Check the execution state and decode arguments frame and source to be
13087   // evaluated.
13088   ASSERT(args.length() == 4);
13089   Object* check_result;
13090   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
13091       RUNTIME_ARGUMENTS(isolate, args));
13092     if (!maybe_result->ToObject(&check_result)) return maybe_result;
13093   }
13094   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13095   CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
13096   Handle<Object> context_extension(args[3], isolate);
13097
13098   // Handle the processing of break.
13099   DisableBreak disable_break_save(isolate, disable_break);
13100
13101   // Enter the top context from before the debugger was invoked.
13102   SaveContext save(isolate);
13103   SaveContext* top = &save;
13104   while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
13105     top = top->prev();
13106   }
13107   if (top != NULL) {
13108     isolate->set_context(*top->context());
13109   }
13110
13111   // Get the native context now set to the top context from before the
13112   // debugger was invoked.
13113   Handle<Context> context = isolate->native_context();
13114   Handle<Object> receiver = isolate->global_object();
13115   return DebugEvaluate(isolate, context, context_extension, receiver, source);
13116 }
13117
13118
13119 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
13120   HandleScope scope(isolate);
13121   ASSERT(args.length() == 0);
13122
13123   // Fill the script objects.
13124   Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
13125
13126   // Convert the script objects to proper JS objects.
13127   for (int i = 0; i < instances->length(); i++) {
13128     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
13129     // Get the script wrapper in a local handle before calling GetScriptWrapper,
13130     // because using
13131     //   instances->set(i, *GetScriptWrapper(script))
13132     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
13133     // already have dereferenced the instances handle.
13134     Handle<JSValue> wrapper = GetScriptWrapper(script);
13135     instances->set(i, *wrapper);
13136   }
13137
13138   // Return result as a JS array.
13139   Handle<JSObject> result =
13140       isolate->factory()->NewJSObject(isolate->array_function());
13141   JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13142   return *result;
13143 }
13144
13145
13146 // Helper function used by Runtime_DebugReferencedBy below.
13147 static int DebugReferencedBy(HeapIterator* iterator,
13148                              JSObject* target,
13149                              Object* instance_filter, int max_references,
13150                              FixedArray* instances, int instances_size,
13151                              JSFunction* arguments_function) {
13152   Isolate* isolate = target->GetIsolate();
13153   SealHandleScope shs(isolate);
13154   DisallowHeapAllocation no_allocation;
13155
13156   // Iterate the heap.
13157   int count = 0;
13158   JSObject* last = NULL;
13159   HeapObject* heap_obj = NULL;
13160   while (((heap_obj = iterator->next()) != NULL) &&
13161          (max_references == 0 || count < max_references)) {
13162     // Only look at all JSObjects.
13163     if (heap_obj->IsJSObject()) {
13164       // Skip context extension objects and argument arrays as these are
13165       // checked in the context of functions using them.
13166       JSObject* obj = JSObject::cast(heap_obj);
13167       if (obj->IsJSContextExtensionObject() ||
13168           obj->map()->constructor() == arguments_function) {
13169         continue;
13170       }
13171
13172       // Check if the JS object has a reference to the object looked for.
13173       if (obj->ReferencesObject(target)) {
13174         // Check instance filter if supplied. This is normally used to avoid
13175         // references from mirror objects (see Runtime_IsInPrototypeChain).
13176         if (!instance_filter->IsUndefined()) {
13177           Object* V = obj;
13178           while (true) {
13179             Object* prototype = V->GetPrototype(isolate);
13180             if (prototype->IsNull()) {
13181               break;
13182             }
13183             if (instance_filter == prototype) {
13184               obj = NULL;  // Don't add this object.
13185               break;
13186             }
13187             V = prototype;
13188           }
13189         }
13190
13191         if (obj != NULL) {
13192           // Valid reference found add to instance array if supplied an update
13193           // count.
13194           if (instances != NULL && count < instances_size) {
13195             instances->set(count, obj);
13196           }
13197           last = obj;
13198           count++;
13199         }
13200       }
13201     }
13202   }
13203
13204   // Check for circular reference only. This can happen when the object is only
13205   // referenced from mirrors and has a circular reference in which case the
13206   // object is not really alive and would have been garbage collected if not
13207   // referenced from the mirror.
13208   if (count == 1 && last == target) {
13209     count = 0;
13210   }
13211
13212   // Return the number of referencing objects found.
13213   return count;
13214 }
13215
13216
13217 // Scan the heap for objects with direct references to an object
13218 // args[0]: the object to find references to
13219 // args[1]: constructor function for instances to exclude (Mirror)
13220 // args[2]: the the maximum number of objects to return
13221 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
13222   HandleScope scope(isolate);
13223   ASSERT(args.length() == 3);
13224
13225   // First perform a full GC in order to avoid references from dead objects.
13226   Heap* heap = isolate->heap();
13227   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugReferencedBy");
13228   // The heap iterator reserves the right to do a GC to make the heap iterable.
13229   // Due to the GC above we know it won't need to do that, but it seems cleaner
13230   // to get the heap iterator constructed before we start having unprotected
13231   // Object* locals that are not protected by handles.
13232
13233   // Check parameters.
13234   CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
13235   Handle<Object> instance_filter = args.at<Object>(1);
13236   RUNTIME_ASSERT(instance_filter->IsUndefined() ||
13237                  instance_filter->IsJSObject());
13238   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
13239   RUNTIME_ASSERT(max_references >= 0);
13240
13241
13242   // Get the constructor function for context extension and arguments array.
13243   Handle<JSObject> arguments_boilerplate(
13244       isolate->context()->native_context()->sloppy_arguments_boilerplate());
13245   Handle<JSFunction> arguments_function(
13246       JSFunction::cast(arguments_boilerplate->map()->constructor()));
13247
13248   // Get the number of referencing objects.
13249   int count;
13250   HeapIterator heap_iterator(heap);
13251   count = DebugReferencedBy(&heap_iterator,
13252                             *target, *instance_filter, max_references,
13253                             NULL, 0, *arguments_function);
13254
13255   // Allocate an array to hold the result.
13256   Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13257
13258   // Fill the referencing objects.
13259   // AllocateFixedArray above does not make the heap non-iterable.
13260   ASSERT(heap->IsHeapIterable());
13261   HeapIterator heap_iterator2(heap);
13262   count = DebugReferencedBy(&heap_iterator2,
13263                             *target, *instance_filter, max_references,
13264                             *instances, count, *arguments_function);
13265
13266   // Return result as JS array.
13267   Handle<JSFunction> constructor(
13268       isolate->context()->native_context()->array_function());
13269
13270   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
13271   JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13272   return *result;
13273 }
13274
13275
13276 // Helper function used by Runtime_DebugConstructedBy below.
13277 static int DebugConstructedBy(HeapIterator* iterator,
13278                               JSFunction* constructor,
13279                               int max_references,
13280                               FixedArray* instances,
13281                               int instances_size) {
13282   DisallowHeapAllocation no_allocation;
13283
13284   // Iterate the heap.
13285   int count = 0;
13286   HeapObject* heap_obj = NULL;
13287   while (((heap_obj = iterator->next()) != NULL) &&
13288          (max_references == 0 || count < max_references)) {
13289     // Only look at all JSObjects.
13290     if (heap_obj->IsJSObject()) {
13291       JSObject* obj = JSObject::cast(heap_obj);
13292       if (obj->map()->constructor() == constructor) {
13293         // Valid reference found add to instance array if supplied an update
13294         // count.
13295         if (instances != NULL && count < instances_size) {
13296           instances->set(count, obj);
13297         }
13298         count++;
13299       }
13300     }
13301   }
13302
13303   // Return the number of referencing objects found.
13304   return count;
13305 }
13306
13307
13308 // Scan the heap for objects constructed by a specific function.
13309 // args[0]: the constructor to find instances of
13310 // args[1]: the the maximum number of objects to return
13311 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
13312   HandleScope scope(isolate);
13313   ASSERT(args.length() == 2);
13314
13315   // First perform a full GC in order to avoid dead objects.
13316   Heap* heap = isolate->heap();
13317   heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13318
13319   // Check parameters.
13320   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
13321   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
13322   RUNTIME_ASSERT(max_references >= 0);
13323
13324   // Get the number of referencing objects.
13325   int count;
13326   HeapIterator heap_iterator(heap);
13327   count = DebugConstructedBy(&heap_iterator,
13328                              *constructor,
13329                              max_references,
13330                              NULL,
13331                              0);
13332
13333   // Allocate an array to hold the result.
13334   Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13335
13336   ASSERT(heap->IsHeapIterable());
13337   // Fill the referencing objects.
13338   HeapIterator heap_iterator2(heap);
13339   count = DebugConstructedBy(&heap_iterator2,
13340                              *constructor,
13341                              max_references,
13342                              *instances,
13343                              count);
13344
13345   // Return result as JS array.
13346   Handle<JSFunction> array_function(
13347       isolate->context()->native_context()->array_function());
13348   Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
13349   JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13350   return *result;
13351 }
13352
13353
13354 // Find the effective prototype object as returned by __proto__.
13355 // args[0]: the object to find the prototype for.
13356 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
13357   SealHandleScope shs(isolate);
13358   ASSERT(args.length() == 1);
13359   CONVERT_ARG_CHECKED(JSObject, obj, 0);
13360   return GetPrototypeSkipHiddenPrototypes(isolate, obj);
13361 }
13362
13363
13364 // Patches script source (should be called upon BeforeCompile event).
13365 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
13366   HandleScope scope(isolate);
13367   ASSERT(args.length() == 2);
13368
13369   CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
13370   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13371
13372   RUNTIME_ASSERT(script_wrapper->value()->IsScript());
13373   Handle<Script> script(Script::cast(script_wrapper->value()));
13374
13375   int compilation_state = script->compilation_state();
13376   RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
13377   script->set_source(*source);
13378
13379   return isolate->heap()->undefined_value();
13380 }
13381
13382
13383 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
13384   SealHandleScope shs(isolate);
13385   ASSERT(args.length() == 0);
13386   OS::DebugBreak();
13387   return isolate->heap()->undefined_value();
13388 }
13389
13390
13391 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
13392   HandleScope scope(isolate);
13393 #ifdef DEBUG
13394   ASSERT(args.length() == 1);
13395   // Get the function and make sure it is compiled.
13396   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13397   if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
13398     return Failure::Exception();
13399   }
13400   func->code()->PrintLn();
13401 #endif  // DEBUG
13402   return isolate->heap()->undefined_value();
13403 }
13404
13405
13406 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
13407   HandleScope scope(isolate);
13408 #ifdef DEBUG
13409   ASSERT(args.length() == 1);
13410   // Get the function and make sure it is compiled.
13411   CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13412   if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
13413     return Failure::Exception();
13414   }
13415   func->shared()->construct_stub()->PrintLn();
13416 #endif  // DEBUG
13417   return isolate->heap()->undefined_value();
13418 }
13419
13420
13421 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
13422   SealHandleScope shs(isolate);
13423   ASSERT(args.length() == 1);
13424
13425   CONVERT_ARG_CHECKED(JSFunction, f, 0);
13426   return f->shared()->inferred_name();
13427 }
13428
13429
13430 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13431                                             Script* script,
13432                                             FixedArray* buffer) {
13433   DisallowHeapAllocation no_allocation;
13434   int counter = 0;
13435   int buffer_size = buffer->length();
13436   for (HeapObject* obj = iterator->next();
13437        obj != NULL;
13438        obj = iterator->next()) {
13439     ASSERT(obj != NULL);
13440     if (!obj->IsSharedFunctionInfo()) {
13441       continue;
13442     }
13443     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13444     if (shared->script() != script) {
13445       continue;
13446     }
13447     if (counter < buffer_size) {
13448       buffer->set(counter, shared);
13449     }
13450     counter++;
13451   }
13452   return counter;
13453 }
13454
13455
13456 // For a script finds all SharedFunctionInfo's in the heap that points
13457 // to this script. Returns JSArray of SharedFunctionInfo wrapped
13458 // in OpaqueReferences.
13459 RUNTIME_FUNCTION(MaybeObject*,
13460                  Runtime_LiveEditFindSharedFunctionInfosForScript) {
13461   HandleScope scope(isolate);
13462   CHECK(isolate->debugger()->live_edit_enabled());
13463   ASSERT(args.length() == 1);
13464   CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13465
13466   RUNTIME_ASSERT(script_value->value()->IsScript());
13467   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13468
13469   const int kBufferSize = 32;
13470
13471   Handle<FixedArray> array;
13472   array = isolate->factory()->NewFixedArray(kBufferSize);
13473   int number;
13474   Heap* heap = isolate->heap();
13475   {
13476     heap->EnsureHeapIsIterable();
13477     DisallowHeapAllocation no_allocation;
13478     HeapIterator heap_iterator(heap);
13479     Script* scr = *script;
13480     FixedArray* arr = *array;
13481     number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13482   }
13483   if (number > kBufferSize) {
13484     array = isolate->factory()->NewFixedArray(number);
13485     heap->EnsureHeapIsIterable();
13486     DisallowHeapAllocation no_allocation;
13487     HeapIterator heap_iterator(heap);
13488     Script* scr = *script;
13489     FixedArray* arr = *array;
13490     FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13491   }
13492
13493   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13494   result->set_length(Smi::FromInt(number));
13495
13496   LiveEdit::WrapSharedFunctionInfos(result);
13497
13498   return *result;
13499 }
13500
13501
13502 // For a script calculates compilation information about all its functions.
13503 // The script source is explicitly specified by the second argument.
13504 // The source of the actual script is not used, however it is important that
13505 // all generated code keeps references to this particular instance of script.
13506 // Returns a JSArray of compilation infos. The array is ordered so that
13507 // each function with all its descendant is always stored in a continues range
13508 // with the function itself going first. The root function is a script function.
13509 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
13510   HandleScope scope(isolate);
13511   CHECK(isolate->debugger()->live_edit_enabled());
13512   ASSERT(args.length() == 2);
13513   CONVERT_ARG_CHECKED(JSValue, script, 0);
13514   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13515
13516   RUNTIME_ASSERT(script->value()->IsScript());
13517   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13518
13519   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
13520
13521   if (isolate->has_pending_exception()) {
13522     return Failure::Exception();
13523   }
13524
13525   return result;
13526 }
13527
13528
13529 // Changes the source of the script to a new_source.
13530 // If old_script_name is provided (i.e. is a String), also creates a copy of
13531 // the script with its original source and sends notification to debugger.
13532 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
13533   HandleScope scope(isolate);
13534   CHECK(isolate->debugger()->live_edit_enabled());
13535   ASSERT(args.length() == 3);
13536   CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13537   CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13538   Handle<Object> old_script_name(args[2], isolate);
13539
13540   RUNTIME_ASSERT(original_script_value->value()->IsScript());
13541   Handle<Script> original_script(Script::cast(original_script_value->value()));
13542
13543   Object* old_script = LiveEdit::ChangeScriptSource(original_script,
13544                                                     new_source,
13545                                                     old_script_name);
13546
13547   if (old_script->IsScript()) {
13548     Handle<Script> script_handle(Script::cast(old_script));
13549     return *(GetScriptWrapper(script_handle));
13550   } else {
13551     return isolate->heap()->null_value();
13552   }
13553 }
13554
13555
13556 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
13557   HandleScope scope(isolate);
13558   CHECK(isolate->debugger()->live_edit_enabled());
13559   ASSERT(args.length() == 1);
13560   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13561   return LiveEdit::FunctionSourceUpdated(shared_info);
13562 }
13563
13564
13565 // Replaces code of SharedFunctionInfo with a new one.
13566 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
13567   HandleScope scope(isolate);
13568   CHECK(isolate->debugger()->live_edit_enabled());
13569   ASSERT(args.length() == 2);
13570   CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13571   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13572
13573   return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13574 }
13575
13576
13577 // Connects SharedFunctionInfo to another script.
13578 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
13579   HandleScope scope(isolate);
13580   CHECK(isolate->debugger()->live_edit_enabled());
13581   ASSERT(args.length() == 2);
13582   Handle<Object> function_object(args[0], isolate);
13583   Handle<Object> script_object(args[1], isolate);
13584
13585   if (function_object->IsJSValue()) {
13586     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13587     if (script_object->IsJSValue()) {
13588       RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13589       Script* script = Script::cast(JSValue::cast(*script_object)->value());
13590       script_object = Handle<Object>(script, isolate);
13591     }
13592
13593     LiveEdit::SetFunctionScript(function_wrapper, script_object);
13594   } else {
13595     // Just ignore this. We may not have a SharedFunctionInfo for some functions
13596     // and we check it in this function.
13597   }
13598
13599   return isolate->heap()->undefined_value();
13600 }
13601
13602
13603 // In a code of a parent function replaces original function as embedded object
13604 // with a substitution one.
13605 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
13606   HandleScope scope(isolate);
13607   CHECK(isolate->debugger()->live_edit_enabled());
13608   ASSERT(args.length() == 3);
13609
13610   CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13611   CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13612   CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13613
13614   LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
13615                                        subst_wrapper);
13616
13617   return isolate->heap()->undefined_value();
13618 }
13619
13620
13621 // Updates positions of a shared function info (first parameter) according
13622 // to script source change. Text change is described in second parameter as
13623 // array of groups of 3 numbers:
13624 // (change_begin, change_end, change_end_new_position).
13625 // Each group describes a change in text; groups are sorted by change_begin.
13626 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
13627   HandleScope scope(isolate);
13628   CHECK(isolate->debugger()->live_edit_enabled());
13629   ASSERT(args.length() == 2);
13630   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13631   CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13632
13633   return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13634 }
13635
13636
13637 // For array of SharedFunctionInfo's (each wrapped in JSValue)
13638 // checks that none of them have activations on stacks (of any thread).
13639 // Returns array of the same length with corresponding results of
13640 // LiveEdit::FunctionPatchabilityStatus type.
13641 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
13642   HandleScope scope(isolate);
13643   CHECK(isolate->debugger()->live_edit_enabled());
13644   ASSERT(args.length() == 2);
13645   CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13646   CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13647
13648   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13649 }
13650
13651
13652 // Compares 2 strings line-by-line, then token-wise and returns diff in form
13653 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13654 // of diff chunks.
13655 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
13656   HandleScope scope(isolate);
13657   CHECK(isolate->debugger()->live_edit_enabled());
13658   ASSERT(args.length() == 2);
13659   CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13660   CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13661
13662   return *LiveEdit::CompareStrings(s1, s2);
13663 }
13664
13665
13666 // Restarts a call frame and completely drops all frames above.
13667 // Returns true if successful. Otherwise returns undefined or an error message.
13668 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
13669   HandleScope scope(isolate);
13670   CHECK(isolate->debugger()->live_edit_enabled());
13671   ASSERT(args.length() == 2);
13672
13673   // Check arguments.
13674   Object* check;
13675   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
13676       RUNTIME_ARGUMENTS(isolate, args));
13677     if (!maybe_check->ToObject(&check)) return maybe_check;
13678   }
13679   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13680   Heap* heap = isolate->heap();
13681
13682   // Find the relevant frame with the requested index.
13683   StackFrame::Id id = isolate->debug()->break_frame_id();
13684   if (id == StackFrame::NO_ID) {
13685     // If there are no JavaScript stack frames return undefined.
13686     return heap->undefined_value();
13687   }
13688
13689   int count = 0;
13690   JavaScriptFrameIterator it(isolate, id);
13691   for (; !it.done(); it.Advance()) {
13692     if (index < count + it.frame()->GetInlineCount()) break;
13693     count += it.frame()->GetInlineCount();
13694   }
13695   if (it.done()) return heap->undefined_value();
13696
13697   const char* error_message = LiveEdit::RestartFrame(it.frame());
13698   if (error_message) {
13699     return *(isolate->factory()->InternalizeUtf8String(error_message));
13700   }
13701   return heap->true_value();
13702 }
13703
13704
13705 // A testing entry. Returns statement position which is the closest to
13706 // source_position.
13707 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
13708   HandleScope scope(isolate);
13709   CHECK(isolate->debugger()->live_edit_enabled());
13710   ASSERT(args.length() == 2);
13711   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13712   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13713
13714   Handle<Code> code(function->code(), isolate);
13715
13716   if (code->kind() != Code::FUNCTION &&
13717       code->kind() != Code::OPTIMIZED_FUNCTION) {
13718     return isolate->heap()->undefined_value();
13719   }
13720
13721   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13722   int closest_pc = 0;
13723   int distance = kMaxInt;
13724   while (!it.done()) {
13725     int statement_position = static_cast<int>(it.rinfo()->data());
13726     // Check if this break point is closer that what was previously found.
13727     if (source_position <= statement_position &&
13728         statement_position - source_position < distance) {
13729       closest_pc =
13730           static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13731       distance = statement_position - source_position;
13732       // Check whether we can't get any closer.
13733       if (distance == 0) break;
13734     }
13735     it.next();
13736   }
13737
13738   return Smi::FromInt(closest_pc);
13739 }
13740
13741
13742 // Calls specified function with or without entering the debugger.
13743 // This is used in unit tests to run code as if debugger is entered or simply
13744 // to have a stack with C++ frame in the middle.
13745 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
13746   HandleScope scope(isolate);
13747   ASSERT(args.length() == 2);
13748   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13749   CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13750
13751   Handle<Object> result;
13752   bool pending_exception;
13753   {
13754     if (without_debugger) {
13755       result = Execution::Call(isolate,
13756                                function,
13757                                isolate->global_object(),
13758                                0,
13759                                NULL,
13760                                &pending_exception);
13761     } else {
13762       EnterDebugger enter_debugger(isolate);
13763       result = Execution::Call(isolate,
13764                                function,
13765                                isolate->global_object(),
13766                                0,
13767                                NULL,
13768                                &pending_exception);
13769     }
13770   }
13771   if (!pending_exception) {
13772     return *result;
13773   } else {
13774     return Failure::Exception();
13775   }
13776 }
13777
13778
13779 // Sets a v8 flag.
13780 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
13781   SealHandleScope shs(isolate);
13782   CONVERT_ARG_CHECKED(String, arg, 0);
13783   SmartArrayPointer<char> flags =
13784       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13785   FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
13786   return isolate->heap()->undefined_value();
13787 }
13788
13789
13790 // Performs a GC.
13791 // Presently, it only does a full GC.
13792 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
13793   SealHandleScope shs(isolate);
13794   isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13795   return isolate->heap()->undefined_value();
13796 }
13797
13798
13799 // Gets the current heap usage.
13800 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
13801   SealHandleScope shs(isolate);
13802   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13803   if (!Smi::IsValid(usage)) {
13804     return *isolate->factory()->NewNumberFromInt(usage);
13805   }
13806   return Smi::FromInt(usage);
13807 }
13808
13809 #endif  // ENABLE_DEBUGGER_SUPPORT
13810
13811
13812 #ifdef V8_I18N_SUPPORT
13813 RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
13814   HandleScope scope(isolate);
13815
13816   ASSERT(args.length() == 1);
13817   CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13818
13819   v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13820
13821   // Return value which denotes invalid language tag.
13822   const char* const kInvalidTag = "invalid-tag";
13823
13824   UErrorCode error = U_ZERO_ERROR;
13825   char icu_result[ULOC_FULLNAME_CAPACITY];
13826   int icu_length = 0;
13827
13828   uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13829                       &icu_length, &error);
13830   if (U_FAILURE(error) || icu_length == 0) {
13831     return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13832   }
13833
13834   char result[ULOC_FULLNAME_CAPACITY];
13835
13836   // Force strict BCP47 rules.
13837   uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13838
13839   if (U_FAILURE(error)) {
13840     return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13841   }
13842
13843   return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13844 }
13845
13846
13847 RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
13848   HandleScope scope(isolate);
13849
13850   ASSERT(args.length() == 1);
13851   CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13852
13853   const icu::Locale* available_locales = NULL;
13854   int32_t count = 0;
13855
13856   if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13857     available_locales = icu::Collator::getAvailableLocales(count);
13858   } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13859     available_locales = icu::NumberFormat::getAvailableLocales(count);
13860   } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13861     available_locales = icu::DateFormat::getAvailableLocales(count);
13862   } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13863     available_locales = icu::BreakIterator::getAvailableLocales(count);
13864   }
13865
13866   UErrorCode error = U_ZERO_ERROR;
13867   char result[ULOC_FULLNAME_CAPACITY];
13868   Handle<JSObject> locales =
13869       isolate->factory()->NewJSObject(isolate->object_function());
13870
13871   for (int32_t i = 0; i < count; ++i) {
13872     const char* icu_name = available_locales[i].getName();
13873
13874     error = U_ZERO_ERROR;
13875     // No need to force strict BCP47 rules.
13876     uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13877     if (U_FAILURE(error)) {
13878       // This shouldn't happen, but lets not break the user.
13879       continue;
13880     }
13881
13882     RETURN_IF_EMPTY_HANDLE(isolate,
13883         JSObject::SetLocalPropertyIgnoreAttributes(
13884             locales,
13885             isolate->factory()->NewStringFromAscii(CStrVector(result)),
13886             isolate->factory()->NewNumber(i),
13887             NONE));
13888   }
13889
13890   return *locales;
13891 }
13892
13893
13894 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
13895   SealHandleScope shs(isolate);
13896
13897   ASSERT(args.length() == 0);
13898
13899   icu::Locale default_locale;
13900
13901   // Set the locale
13902   char result[ULOC_FULLNAME_CAPACITY];
13903   UErrorCode status = U_ZERO_ERROR;
13904   uloc_toLanguageTag(
13905       default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13906   if (U_SUCCESS(status)) {
13907     return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13908   }
13909
13910   return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
13911 }
13912
13913
13914 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
13915   HandleScope scope(isolate);
13916
13917   ASSERT(args.length() == 1);
13918
13919   CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13920
13921   uint32_t length = static_cast<uint32_t>(input->length()->Number());
13922   Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
13923   Handle<Name> maximized =
13924       isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
13925   Handle<Name> base =
13926       isolate->factory()->NewStringFromAscii(CStrVector("base"));
13927   for (unsigned int i = 0; i < length; ++i) {
13928     Handle<Object> locale_id = Object::GetElement(isolate, input, i);
13929     RETURN_IF_EMPTY_HANDLE(isolate, locale_id);
13930     if (!locale_id->IsString()) {
13931       return isolate->Throw(isolate->heap()->illegal_argument_string());
13932     }
13933
13934     v8::String::Utf8Value utf8_locale_id(
13935         v8::Utils::ToLocal(Handle<String>::cast(locale_id)));
13936
13937     UErrorCode error = U_ZERO_ERROR;
13938
13939     // Convert from BCP47 to ICU format.
13940     // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13941     char icu_locale[ULOC_FULLNAME_CAPACITY];
13942     int icu_locale_length = 0;
13943     uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13944                         &icu_locale_length, &error);
13945     if (U_FAILURE(error) || icu_locale_length == 0) {
13946       return isolate->Throw(isolate->heap()->illegal_argument_string());
13947     }
13948
13949     // Maximize the locale.
13950     // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13951     char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13952     uloc_addLikelySubtags(
13953         icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13954
13955     // Remove extensions from maximized locale.
13956     // de_Latn_DE@collation=phonebook -> de_Latn_DE
13957     char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13958     uloc_getBaseName(
13959         icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13960
13961     // Get original name without extensions.
13962     // de_DE@collation=phonebook -> de_DE
13963     char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13964     uloc_getBaseName(
13965         icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13966
13967     // Convert from ICU locale format to BCP47 format.
13968     // de_Latn_DE -> de-Latn-DE
13969     char base_max_locale[ULOC_FULLNAME_CAPACITY];
13970     uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13971                        ULOC_FULLNAME_CAPACITY, FALSE, &error);
13972
13973     // de_DE -> de-DE
13974     char base_locale[ULOC_FULLNAME_CAPACITY];
13975     uloc_toLanguageTag(
13976         icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13977
13978     if (U_FAILURE(error)) {
13979       return isolate->Throw(isolate->heap()->illegal_argument_string());
13980     }
13981
13982     Handle<JSObject> result =
13983         isolate->factory()->NewJSObject(isolate->object_function());
13984     RETURN_IF_EMPTY_HANDLE(isolate,
13985         JSObject::SetLocalPropertyIgnoreAttributes(
13986             result,
13987             maximized,
13988             isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
13989             NONE));
13990     RETURN_IF_EMPTY_HANDLE(isolate,
13991         JSObject::SetLocalPropertyIgnoreAttributes(
13992             result,
13993             base,
13994             isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
13995             NONE));
13996     output->set(i, *result);
13997   }
13998
13999   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
14000   result->set_length(Smi::FromInt(length));
14001   return *result;
14002 }
14003
14004
14005 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
14006   HandleScope scope(isolate);
14007
14008   ASSERT(args.length() == 3);
14009
14010   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14011   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14012   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14013
14014   Handle<ObjectTemplateInfo> date_format_template =
14015       I18N::GetTemplate(isolate);
14016
14017   // Create an empty object wrapper.
14018   bool has_pending_exception = false;
14019   Handle<JSObject> local_object = Execution::InstantiateObject(
14020       date_format_template, &has_pending_exception);
14021   if (has_pending_exception) {
14022     ASSERT(isolate->has_pending_exception());
14023     return Failure::Exception();
14024   }
14025
14026   // Set date time formatter as internal field of the resulting JS object.
14027   icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
14028       isolate, locale, options, resolved);
14029
14030   if (!date_format) return isolate->ThrowIllegalOperation();
14031
14032   local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
14033
14034   RETURN_IF_EMPTY_HANDLE(isolate,
14035       JSObject::SetLocalPropertyIgnoreAttributes(
14036           local_object,
14037           isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
14038           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14039           NONE));
14040
14041   // Make object handle weak so we can delete the data format once GC kicks in.
14042   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14043   GlobalHandles::MakeWeak(wrapper.location(),
14044                           reinterpret_cast<void*>(wrapper.location()),
14045                           DateFormat::DeleteDateFormat);
14046   return *local_object;
14047 }
14048
14049
14050 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
14051   HandleScope scope(isolate);
14052
14053   ASSERT(args.length() == 2);
14054
14055   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
14056   CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
14057
14058   bool has_pending_exception = false;
14059   Handle<Object> value =
14060       Execution::ToNumber(isolate, date, &has_pending_exception);
14061   if (has_pending_exception) {
14062     ASSERT(isolate->has_pending_exception());
14063     return Failure::Exception();
14064   }
14065
14066   icu::SimpleDateFormat* date_format =
14067       DateFormat::UnpackDateFormat(isolate, date_format_holder);
14068   if (!date_format) return isolate->ThrowIllegalOperation();
14069
14070   icu::UnicodeString result;
14071   date_format->format(value->Number(), result);
14072
14073   return *isolate->factory()->NewStringFromTwoByte(
14074       Vector<const uint16_t>(
14075           reinterpret_cast<const uint16_t*>(result.getBuffer()),
14076           result.length()));
14077 }
14078
14079
14080 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
14081   HandleScope scope(isolate);
14082
14083   ASSERT(args.length() == 2);
14084
14085   CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
14086   CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
14087
14088   v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
14089   icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
14090   icu::SimpleDateFormat* date_format =
14091       DateFormat::UnpackDateFormat(isolate, date_format_holder);
14092   if (!date_format) return isolate->ThrowIllegalOperation();
14093
14094   UErrorCode status = U_ZERO_ERROR;
14095   UDate date = date_format->parse(u_date, status);
14096   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14097
14098   bool has_pending_exception = false;
14099   Handle<JSDate> result = Handle<JSDate>::cast(
14100       Execution::NewDate(
14101           isolate, static_cast<double>(date), &has_pending_exception));
14102   if (has_pending_exception) {
14103     ASSERT(isolate->has_pending_exception());
14104     return Failure::Exception();
14105   }
14106   return *result;
14107 }
14108
14109
14110 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
14111   HandleScope scope(isolate);
14112
14113   ASSERT(args.length() == 3);
14114
14115   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14116   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14117   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14118
14119   Handle<ObjectTemplateInfo> number_format_template =
14120       I18N::GetTemplate(isolate);
14121
14122   // Create an empty object wrapper.
14123   bool has_pending_exception = false;
14124   Handle<JSObject> local_object = Execution::InstantiateObject(
14125       number_format_template, &has_pending_exception);
14126   if (has_pending_exception) {
14127     ASSERT(isolate->has_pending_exception());
14128     return Failure::Exception();
14129   }
14130
14131   // Set number formatter as internal field of the resulting JS object.
14132   icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
14133       isolate, locale, options, resolved);
14134
14135   if (!number_format) return isolate->ThrowIllegalOperation();
14136
14137   local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
14138
14139   RETURN_IF_EMPTY_HANDLE(isolate,
14140       JSObject::SetLocalPropertyIgnoreAttributes(
14141           local_object,
14142           isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
14143           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14144           NONE));
14145
14146   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14147   GlobalHandles::MakeWeak(wrapper.location(),
14148                           reinterpret_cast<void*>(wrapper.location()),
14149                           NumberFormat::DeleteNumberFormat);
14150   return *local_object;
14151 }
14152
14153
14154 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
14155   HandleScope scope(isolate);
14156
14157   ASSERT(args.length() == 2);
14158
14159   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14160   CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
14161
14162   bool has_pending_exception = false;
14163   Handle<Object> value = Execution::ToNumber(
14164       isolate, number, &has_pending_exception);
14165   if (has_pending_exception) {
14166     ASSERT(isolate->has_pending_exception());
14167     return Failure::Exception();
14168   }
14169
14170   icu::DecimalFormat* number_format =
14171       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14172   if (!number_format) return isolate->ThrowIllegalOperation();
14173
14174   icu::UnicodeString result;
14175   number_format->format(value->Number(), result);
14176
14177   return *isolate->factory()->NewStringFromTwoByte(
14178       Vector<const uint16_t>(
14179           reinterpret_cast<const uint16_t*>(result.getBuffer()),
14180           result.length()));
14181 }
14182
14183
14184 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
14185   HandleScope scope(isolate);
14186
14187   ASSERT(args.length() == 2);
14188
14189   CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14190   CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
14191
14192   v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
14193   icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
14194   icu::DecimalFormat* number_format =
14195       NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14196   if (!number_format) return isolate->ThrowIllegalOperation();
14197
14198   UErrorCode status = U_ZERO_ERROR;
14199   icu::Formattable result;
14200   // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
14201   // to be part of Chrome.
14202   // TODO(cira): Include currency parsing code using parseCurrency call.
14203   // We need to check if the formatter parses all currencies or only the
14204   // one it was constructed with (it will impact the API - how to return ISO
14205   // code and the value).
14206   number_format->parse(u_number, result, status);
14207   if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14208
14209   switch (result.getType()) {
14210   case icu::Formattable::kDouble:
14211     return *isolate->factory()->NewNumber(result.getDouble());
14212   case icu::Formattable::kLong:
14213     return *isolate->factory()->NewNumberFromInt(result.getLong());
14214   case icu::Formattable::kInt64:
14215     return *isolate->factory()->NewNumber(
14216         static_cast<double>(result.getInt64()));
14217   default:
14218     return isolate->heap()->undefined_value();
14219   }
14220 }
14221
14222
14223 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
14224   HandleScope scope(isolate);
14225
14226   ASSERT(args.length() == 3);
14227
14228   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14229   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14230   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14231
14232   Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
14233
14234   // Create an empty object wrapper.
14235   bool has_pending_exception = false;
14236   Handle<JSObject> local_object = Execution::InstantiateObject(
14237       collator_template, &has_pending_exception);
14238   if (has_pending_exception) {
14239     ASSERT(isolate->has_pending_exception());
14240     return Failure::Exception();
14241   }
14242
14243   // Set collator as internal field of the resulting JS object.
14244   icu::Collator* collator = Collator::InitializeCollator(
14245       isolate, locale, options, resolved);
14246
14247   if (!collator) return isolate->ThrowIllegalOperation();
14248
14249   local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
14250
14251   RETURN_IF_EMPTY_HANDLE(isolate,
14252       JSObject::SetLocalPropertyIgnoreAttributes(
14253           local_object,
14254           isolate->factory()->NewStringFromAscii(CStrVector("collator")),
14255           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14256           NONE));
14257
14258   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14259   GlobalHandles::MakeWeak(wrapper.location(),
14260                           reinterpret_cast<void*>(wrapper.location()),
14261                           Collator::DeleteCollator);
14262   return *local_object;
14263 }
14264
14265
14266 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
14267   HandleScope scope(isolate);
14268
14269   ASSERT(args.length() == 3);
14270
14271   CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
14272   CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
14273   CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
14274
14275   icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
14276   if (!collator) return isolate->ThrowIllegalOperation();
14277
14278   v8::String::Value string_value1(v8::Utils::ToLocal(string1));
14279   v8::String::Value string_value2(v8::Utils::ToLocal(string2));
14280   const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
14281   const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
14282   UErrorCode status = U_ZERO_ERROR;
14283   UCollationResult result = collator->compare(u_string1,
14284                                               string_value1.length(),
14285                                               u_string2,
14286                                               string_value2.length(),
14287                                               status);
14288   if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
14289
14290   return *isolate->factory()->NewNumberFromInt(result);
14291 }
14292
14293
14294 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringNormalize) {
14295   HandleScope scope(isolate);
14296   static const UNormalizationMode normalizationForms[] =
14297       { UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD };
14298
14299   ASSERT(args.length() == 2);
14300
14301   CONVERT_ARG_HANDLE_CHECKED(String, stringValue, 0);
14302   CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
14303
14304   v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
14305   const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
14306
14307   // TODO(mnita): check Normalizer2 (not available in ICU 46)
14308   UErrorCode status = U_ZERO_ERROR;
14309   icu::UnicodeString result;
14310   icu::Normalizer::normalize(u_value, normalizationForms[form_id], 0,
14311       result, status);
14312   if (U_FAILURE(status)) {
14313     return isolate->heap()->undefined_value();
14314   }
14315
14316   return *isolate->factory()->NewStringFromTwoByte(
14317       Vector<const uint16_t>(
14318           reinterpret_cast<const uint16_t*>(result.getBuffer()),
14319           result.length()));
14320 }
14321
14322
14323 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
14324   HandleScope scope(isolate);
14325
14326   ASSERT(args.length() == 3);
14327
14328   CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14329   CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14330   CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14331
14332   Handle<ObjectTemplateInfo> break_iterator_template =
14333       I18N::GetTemplate2(isolate);
14334
14335   // Create an empty object wrapper.
14336   bool has_pending_exception = false;
14337   Handle<JSObject> local_object = Execution::InstantiateObject(
14338       break_iterator_template, &has_pending_exception);
14339   if (has_pending_exception) {
14340     ASSERT(isolate->has_pending_exception());
14341     return Failure::Exception();
14342   }
14343
14344   // Set break iterator as internal field of the resulting JS object.
14345   icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
14346       isolate, locale, options, resolved);
14347
14348   if (!break_iterator) return isolate->ThrowIllegalOperation();
14349
14350   local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
14351   // Make sure that the pointer to adopted text is NULL.
14352   local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
14353
14354   RETURN_IF_EMPTY_HANDLE(isolate,
14355       JSObject::SetLocalPropertyIgnoreAttributes(
14356           local_object,
14357           isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")),
14358           isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14359           NONE));
14360
14361   // Make object handle weak so we can delete the break iterator once GC kicks
14362   // in.
14363   Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14364   GlobalHandles::MakeWeak(wrapper.location(),
14365                           reinterpret_cast<void*>(wrapper.location()),
14366                           BreakIterator::DeleteBreakIterator);
14367   return *local_object;
14368 }
14369
14370
14371 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
14372   HandleScope scope(isolate);
14373
14374   ASSERT(args.length() == 2);
14375
14376   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14377   CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
14378
14379   icu::BreakIterator* break_iterator =
14380       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14381   if (!break_iterator) return isolate->ThrowIllegalOperation();
14382
14383   icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
14384       break_iterator_holder->GetInternalField(1));
14385   delete u_text;
14386
14387   v8::String::Value text_value(v8::Utils::ToLocal(text));
14388   u_text = new icu::UnicodeString(
14389       reinterpret_cast<const UChar*>(*text_value), text_value.length());
14390   break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
14391
14392   break_iterator->setText(*u_text);
14393
14394   return isolate->heap()->undefined_value();
14395 }
14396
14397
14398 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
14399   HandleScope scope(isolate);
14400
14401   ASSERT(args.length() == 1);
14402
14403   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14404
14405   icu::BreakIterator* break_iterator =
14406       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14407   if (!break_iterator) return isolate->ThrowIllegalOperation();
14408
14409   return *isolate->factory()->NewNumberFromInt(break_iterator->first());
14410 }
14411
14412
14413 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
14414   HandleScope scope(isolate);
14415
14416   ASSERT(args.length() == 1);
14417
14418   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14419
14420   icu::BreakIterator* break_iterator =
14421       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14422   if (!break_iterator) return isolate->ThrowIllegalOperation();
14423
14424   return *isolate->factory()->NewNumberFromInt(break_iterator->next());
14425 }
14426
14427
14428 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
14429   HandleScope scope(isolate);
14430
14431   ASSERT(args.length() == 1);
14432
14433   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14434
14435   icu::BreakIterator* break_iterator =
14436       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14437   if (!break_iterator) return isolate->ThrowIllegalOperation();
14438
14439   return *isolate->factory()->NewNumberFromInt(break_iterator->current());
14440 }
14441
14442
14443 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
14444   HandleScope scope(isolate);
14445
14446   ASSERT(args.length() == 1);
14447
14448   CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14449
14450   icu::BreakIterator* break_iterator =
14451       BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14452   if (!break_iterator) return isolate->ThrowIllegalOperation();
14453
14454   // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
14455   icu::RuleBasedBreakIterator* rule_based_iterator =
14456       static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
14457   int32_t status = rule_based_iterator->getRuleStatus();
14458   // Keep return values in sync with JavaScript BreakType enum.
14459   if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
14460     return *isolate->factory()->NewStringFromAscii(CStrVector("none"));
14461   } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
14462     return *isolate->factory()->NewStringFromAscii(CStrVector("number"));
14463   } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
14464     return *isolate->factory()->NewStringFromAscii(CStrVector("letter"));
14465   } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
14466     return *isolate->factory()->NewStringFromAscii(CStrVector("kana"));
14467   } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
14468     return *isolate->factory()->NewStringFromAscii(CStrVector("ideo"));
14469   } else {
14470     return *isolate->factory()->NewStringFromAscii(CStrVector("unknown"));
14471   }
14472 }
14473 #endif  // V8_I18N_SUPPORT
14474
14475
14476 // Finds the script object from the script data. NOTE: This operation uses
14477 // heap traversal to find the function generated for the source position
14478 // for the requested break point. For lazily compiled functions several heap
14479 // traversals might be required rendering this operation as a rather slow
14480 // operation. However for setting break points which is normally done through
14481 // some kind of user interaction the performance is not crucial.
14482 static Handle<Object> Runtime_GetScriptFromScriptName(
14483     Handle<String> script_name) {
14484   // Scan the heap for Script objects to find the script with the requested
14485   // script data.
14486   Handle<Script> script;
14487   Factory* factory = script_name->GetIsolate()->factory();
14488   Heap* heap = script_name->GetHeap();
14489   heap->EnsureHeapIsIterable();
14490   DisallowHeapAllocation no_allocation_during_heap_iteration;
14491   HeapIterator iterator(heap);
14492   HeapObject* obj = NULL;
14493   while (script.is_null() && ((obj = iterator.next()) != NULL)) {
14494     // If a script is found check if it has the script data requested.
14495     if (obj->IsScript()) {
14496       if (Script::cast(obj)->name()->IsString()) {
14497         if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
14498           script = Handle<Script>(Script::cast(obj));
14499         }
14500       }
14501     }
14502   }
14503
14504   // If no script with the requested script data is found return undefined.
14505   if (script.is_null()) return factory->undefined_value();
14506
14507   // Return the script found.
14508   return GetScriptWrapper(script);
14509 }
14510
14511
14512 // Get the script object from script data. NOTE: Regarding performance
14513 // see the NOTE for GetScriptFromScriptData.
14514 // args[0]: script data for the script to find the source for
14515 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
14516   HandleScope scope(isolate);
14517
14518   ASSERT(args.length() == 1);
14519
14520   CONVERT_ARG_CHECKED(String, script_name, 0);
14521
14522   // Find the requested script.
14523   Handle<Object> result =
14524       Runtime_GetScriptFromScriptName(Handle<String>(script_name));
14525   return *result;
14526 }
14527
14528
14529 // Collect the raw data for a stack trace.  Returns an array of 4
14530 // element segments each containing a receiver, function, code and
14531 // native code offset.
14532 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
14533   HandleScope scope(isolate);
14534   ASSERT_EQ(args.length(), 3);
14535   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14536   Handle<Object> caller = args.at<Object>(1);
14537   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
14538
14539   // Optionally capture a more detailed stack trace for the message.
14540   isolate->CaptureAndSetDetailedStackTrace(error_object);
14541   // Capture a simple stack trace for the stack property.
14542   return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
14543 }
14544
14545
14546 // Retrieve the stack trace.  This is the raw stack trace that yet has to
14547 // be formatted.  Since we only need this once, clear it afterwards.
14548 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
14549   HandleScope scope(isolate);
14550   ASSERT_EQ(args.length(), 1);
14551   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14552   Handle<String> key = isolate->factory()->hidden_stack_trace_string();
14553   Handle<Object> result(error_object->GetHiddenProperty(*key), isolate);
14554   if (result->IsTheHole()) return isolate->heap()->undefined_value();
14555   RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
14556   JSObject::DeleteHiddenProperty(error_object, key);
14557   return *result;
14558 }
14559
14560
14561 // Returns V8 version as a string.
14562 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
14563   SealHandleScope shs(isolate);
14564   ASSERT_EQ(args.length(), 0);
14565
14566   const char* version_string = v8::V8::GetVersion();
14567
14568   return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
14569                                                   NOT_TENURED);
14570 }
14571
14572
14573 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
14574   SealHandleScope shs(isolate);
14575   ASSERT(args.length() == 1);
14576   CONVERT_SMI_ARG_CHECKED(message_id, 0);
14577   const char* message = GetBailoutReason(
14578       static_cast<BailoutReason>(message_id));
14579   OS::PrintError("abort: %s\n", message);
14580   isolate->PrintStack(stderr);
14581   OS::Abort();
14582   UNREACHABLE();
14583   return NULL;
14584 }
14585
14586
14587 RUNTIME_FUNCTION(MaybeObject*, Runtime_AbortJS) {
14588   HandleScope scope(isolate);
14589   ASSERT(args.length() == 1);
14590   CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
14591   OS::PrintError("abort: %s\n", message->ToCString().get());
14592   isolate->PrintStack(stderr);
14593   OS::Abort();
14594   UNREACHABLE();
14595   return NULL;
14596 }
14597
14598
14599 RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
14600   HandleScope scope(isolate);
14601   ASSERT(args.length() == 1);
14602   CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
14603   FlattenString(str);
14604   return isolate->heap()->undefined_value();
14605 }
14606
14607
14608 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
14609   HandleScope scope(isolate);
14610   ASSERT(args.length() == 0);
14611   isolate->heap()->NotifyContextDisposed();
14612   return isolate->heap()->undefined_value();
14613 }
14614
14615
14616 RUNTIME_FUNCTION(MaybeObject*, Runtime_TryMigrateInstance) {
14617   HandleScope scope(isolate);
14618   ASSERT(args.length() == 1);
14619   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14620   if (!object->IsJSObject()) return Smi::FromInt(0);
14621   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14622   if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14623   // This call must not cause lazy deopts, because it's called from deferred
14624   // code where we can't handle lazy deopts for lack of a suitable bailout
14625   // ID. So we just try migration and signal failure if necessary,
14626   // which will also trigger a deopt.
14627   Handle<Object> result = JSObject::TryMigrateInstance(js_object);
14628   if (result.is_null()) return Smi::FromInt(0);
14629   return *object;
14630 }
14631
14632
14633 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_GetFromCache) {
14634   SealHandleScope shs(isolate);
14635   // This is only called from codegen, so checks might be more lax.
14636   CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
14637   Object* key = args[1];
14638
14639   int finger_index = cache->finger_index();
14640   Object* o = cache->get(finger_index);
14641   if (o == key) {
14642     // The fastest case: hit the same place again.
14643     return cache->get(finger_index + 1);
14644   }
14645
14646   for (int i = finger_index - 2;
14647        i >= JSFunctionResultCache::kEntriesIndex;
14648        i -= 2) {
14649     o = cache->get(i);
14650     if (o == key) {
14651       cache->set_finger_index(i);
14652       return cache->get(i + 1);
14653     }
14654   }
14655
14656   int size = cache->size();
14657   ASSERT(size <= cache->length());
14658
14659   for (int i = size - 2; i > finger_index; i -= 2) {
14660     o = cache->get(i);
14661     if (o == key) {
14662       cache->set_finger_index(i);
14663       return cache->get(i + 1);
14664     }
14665   }
14666
14667   // There is no value in the cache.  Invoke the function and cache result.
14668   HandleScope scope(isolate);
14669
14670   Handle<JSFunctionResultCache> cache_handle(cache);
14671   Handle<Object> key_handle(key, isolate);
14672   Handle<Object> value;
14673   {
14674     Handle<JSFunction> factory(JSFunction::cast(
14675           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14676     // TODO(antonm): consider passing a receiver when constructing a cache.
14677     Handle<Object> receiver(isolate->native_context()->global_object(),
14678                             isolate);
14679     // This handle is nor shared, nor used later, so it's safe.
14680     Handle<Object> argv[] = { key_handle };
14681     bool pending_exception;
14682     value = Execution::Call(isolate,
14683                             factory,
14684                             receiver,
14685                             ARRAY_SIZE(argv),
14686                             argv,
14687                             &pending_exception);
14688     if (pending_exception) return Failure::Exception();
14689   }
14690
14691 #ifdef VERIFY_HEAP
14692   if (FLAG_verify_heap) {
14693     cache_handle->JSFunctionResultCacheVerify();
14694   }
14695 #endif
14696
14697   // Function invocation may have cleared the cache.  Reread all the data.
14698   finger_index = cache_handle->finger_index();
14699   size = cache_handle->size();
14700
14701   // If we have spare room, put new data into it, otherwise evict post finger
14702   // entry which is likely to be the least recently used.
14703   int index = -1;
14704   if (size < cache_handle->length()) {
14705     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14706     index = size;
14707   } else {
14708     index = finger_index + JSFunctionResultCache::kEntrySize;
14709     if (index == cache_handle->length()) {
14710       index = JSFunctionResultCache::kEntriesIndex;
14711     }
14712   }
14713
14714   ASSERT(index % 2 == 0);
14715   ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
14716   ASSERT(index < cache_handle->length());
14717
14718   cache_handle->set(index, *key_handle);
14719   cache_handle->set(index + 1, *value);
14720   cache_handle->set_finger_index(index);
14721
14722 #ifdef VERIFY_HEAP
14723   if (FLAG_verify_heap) {
14724     cache_handle->JSFunctionResultCacheVerify();
14725   }
14726 #endif
14727
14728   return *value;
14729 }
14730
14731
14732 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
14733   SealHandleScope shs(isolate);
14734   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14735   return Smi::FromInt(message->start_position());
14736 }
14737
14738
14739 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
14740   SealHandleScope shs(isolate);
14741   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14742   return message->script();
14743 }
14744
14745
14746 #ifdef DEBUG
14747 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
14748 // Exclude the code in release mode.
14749 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
14750   HandleScope scope(isolate);
14751   ASSERT(args.length() == 0);
14752 #define COUNT_ENTRY(Name, argc, ressize) + 1
14753   int entry_count = 0
14754       RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14755       RUNTIME_HIDDEN_FUNCTION_LIST(COUNT_ENTRY)
14756       INLINE_FUNCTION_LIST(COUNT_ENTRY);
14757 #undef COUNT_ENTRY
14758   Factory* factory = isolate->factory();
14759   Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14760   int index = 0;
14761   bool inline_runtime_functions = false;
14762 #define ADD_ENTRY(Name, argc, ressize)                                       \
14763   {                                                                          \
14764     HandleScope inner(isolate);                                              \
14765     Handle<String> name;                                                     \
14766     /* Inline runtime functions have an underscore in front of the name. */  \
14767     if (inline_runtime_functions) {                                          \
14768       name = factory->NewStringFromAscii(                                    \
14769           Vector<const char>("_" #Name, StrLength("_" #Name)));              \
14770     } else {                                                                 \
14771       name = factory->NewStringFromAscii(                                    \
14772           Vector<const char>(#Name, StrLength(#Name)));                      \
14773     }                                                                        \
14774     Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
14775     pair_elements->set(0, *name);                                            \
14776     pair_elements->set(1, Smi::FromInt(argc));                               \
14777     Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
14778     elements->set(index++, *pair);                                           \
14779   }
14780   inline_runtime_functions = false;
14781   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14782   // Calling hidden runtime functions should just throw.
14783   RUNTIME_HIDDEN_FUNCTION_LIST(ADD_ENTRY)
14784   inline_runtime_functions = true;
14785   INLINE_FUNCTION_LIST(ADD_ENTRY)
14786 #undef ADD_ENTRY
14787   ASSERT_EQ(index, entry_count);
14788   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14789   return *result;
14790 }
14791 #endif
14792
14793
14794 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Log) {
14795   HandleScope handle_scope(isolate);
14796   ASSERT(args.length() == 2);
14797   CONVERT_ARG_HANDLE_CHECKED(String, format, 0);
14798   CONVERT_ARG_HANDLE_CHECKED(JSArray, elms, 1);
14799
14800   SmartArrayPointer<char> format_chars = format->ToCString();
14801   isolate->logger()->LogRuntime(
14802       Vector<const char>(format_chars.get(), format->length()), elms);
14803   return isolate->heap()->undefined_value();
14804 }
14805
14806
14807 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
14808   UNREACHABLE();  // implemented as macro in the parser
14809   return NULL;
14810 }
14811
14812
14813 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
14814   RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
14815     CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
14816     return isolate->heap()->ToBoolean(obj->Has##Name());  \
14817   }
14818
14819 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
14820 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14821 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14822 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14823 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14824 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14825 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
14826 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14827 // Properties test sitting with elements tests - not fooling anyone.
14828 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
14829
14830 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14831
14832
14833 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size)     \
14834   RUNTIME_FUNCTION(MaybeObject*, Runtime_HasExternal##Type##Elements) {        \
14835     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                     \
14836     return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements());     \
14837   }
14838
14839 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
14840
14841 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14842
14843
14844 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s)  \
14845   RUNTIME_FUNCTION(MaybeObject*, Runtime_HasFixed##Type##Elements) {           \
14846     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                     \
14847     return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements());        \
14848   }
14849
14850 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
14851
14852 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14853
14854
14855 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
14856   SealHandleScope shs(isolate);
14857   ASSERT(args.length() == 2);
14858   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14859   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14860   return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14861 }
14862
14863
14864 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) {
14865   SealHandleScope shs(isolate);
14866   ASSERT(args.length() == 1);
14867   CONVERT_ARG_CHECKED(HeapObject, obj, 0);
14868   return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded());
14869 }
14870
14871
14872 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
14873   SealHandleScope shs(isolate);
14874   ASSERT(args.length() == 1);
14875
14876   if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14877   JSReceiver* obj = JSReceiver::cast(args[0]);
14878   if (obj->IsJSGlobalProxy()) {
14879     Object* proto = obj->GetPrototype();
14880     if (proto->IsNull()) return isolate->heap()->false_value();
14881     ASSERT(proto->IsJSGlobalObject());
14882     obj = JSReceiver::cast(proto);
14883   }
14884   return isolate->heap()->ToBoolean(obj->map()->is_observed());
14885 }
14886
14887
14888 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
14889   HandleScope scope(isolate);
14890   ASSERT(args.length() == 1);
14891   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
14892   if (obj->IsJSGlobalProxy()) {
14893     Object* proto = obj->GetPrototype();
14894     if (proto->IsNull()) return isolate->heap()->undefined_value();
14895     ASSERT(proto->IsJSGlobalObject());
14896     obj = handle(JSReceiver::cast(proto));
14897   }
14898   if (obj->IsJSProxy())
14899     return isolate->heap()->undefined_value();
14900
14901   ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
14902            Handle<JSObject>::cast(obj)->HasFastElements()));
14903   ASSERT(obj->IsJSObject());
14904   JSObject::SetObserved(Handle<JSObject>::cast(obj));
14905   return isolate->heap()->undefined_value();
14906 }
14907
14908
14909 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetMicrotaskPending) {
14910   SealHandleScope shs(isolate);
14911   ASSERT(args.length() == 1);
14912   CONVERT_BOOLEAN_ARG_CHECKED(new_state, 0);
14913   bool old_state = isolate->microtask_pending();
14914   isolate->set_microtask_pending(new_state);
14915   return isolate->heap()->ToBoolean(old_state);
14916 }
14917
14918
14919 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunMicrotasks) {
14920   HandleScope scope(isolate);
14921   ASSERT(args.length() == 0);
14922   if (isolate->microtask_pending())
14923     Execution::RunMicrotasks(isolate);
14924   return isolate->heap()->undefined_value();
14925 }
14926
14927
14928 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetMicrotaskState) {
14929   SealHandleScope shs(isolate);
14930   ASSERT(args.length() == 0);
14931   return isolate->heap()->microtask_state();
14932 }
14933
14934
14935 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
14936   SealHandleScope shs(isolate);
14937   ASSERT(args.length() == 0);
14938   return isolate->heap()->observation_state();
14939 }
14940
14941
14942 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
14943   HandleScope scope(isolate);
14944   ASSERT(args.length() == 0);
14945   // TODO(adamk): Currently this runtime function is only called three times per
14946   // isolate. If it's called more often, the map should be moved into the
14947   // strong root list.
14948   Handle<Map> map =
14949       isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
14950   Handle<JSWeakMap> weakmap =
14951       Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
14952   return WeakCollectionInitialize(isolate, weakmap);
14953 }
14954
14955
14956 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
14957   SealHandleScope shs(isolate);
14958   ASSERT(args.length() == 1);
14959   Object* object = args[0];
14960   if (object->IsJSGlobalProxy()) {
14961     object = object->GetPrototype(isolate);
14962     if (object->IsNull()) return isolate->heap()->undefined_value();
14963   }
14964   return object;
14965 }
14966
14967
14968 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
14969   HandleScope scope(isolate);
14970   ASSERT(args.length() == 3);
14971   CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
14972   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
14973   ASSERT(object->map()->is_access_check_needed());
14974   Handle<Object> key = args.at<Object>(2);
14975   SaveContext save(isolate);
14976   isolate->set_context(observer->context());
14977   if (!isolate->MayNamedAccessWrapper(object,
14978                                       isolate->factory()->undefined_value(),
14979                                       v8::ACCESS_KEYS)) {
14980     return isolate->heap()->false_value();
14981   }
14982   bool access_allowed = false;
14983   uint32_t index = 0;
14984   if (key->ToArrayIndex(&index) ||
14985       (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) {
14986     access_allowed =
14987         isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_GET) &&
14988         isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS);
14989   } else {
14990     access_allowed =
14991         isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_GET) &&
14992         isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS);
14993   }
14994   return isolate->heap()->ToBoolean(access_allowed);
14995 }
14996
14997
14998 static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
14999                                            Handle<JSFunction> constructor,
15000                                            Handle<AllocationSite> site,
15001                                            Arguments* caller_args) {
15002   Factory* factory = isolate->factory();
15003
15004   bool holey = false;
15005   bool can_use_type_feedback = true;
15006   if (caller_args->length() == 1) {
15007     Handle<Object> argument_one = caller_args->at<Object>(0);
15008     if (argument_one->IsSmi()) {
15009       int value = Handle<Smi>::cast(argument_one)->value();
15010       if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
15011         // the array is a dictionary in this case.
15012         can_use_type_feedback = false;
15013       } else if (value != 0) {
15014         holey = true;
15015       }
15016     } else {
15017       // Non-smi length argument produces a dictionary
15018       can_use_type_feedback = false;
15019     }
15020   }
15021
15022   Handle<JSArray> array;
15023   if (!site.is_null() && can_use_type_feedback) {
15024     ElementsKind to_kind = site->GetElementsKind();
15025     if (holey && !IsFastHoleyElementsKind(to_kind)) {
15026       to_kind = GetHoleyElementsKind(to_kind);
15027       // Update the allocation site info to reflect the advice alteration.
15028       site->SetElementsKind(to_kind);
15029     }
15030
15031     // We should allocate with an initial map that reflects the allocation site
15032     // advice. Therefore we use AllocateJSObjectFromMap instead of passing
15033     // the constructor.
15034     Handle<Map> initial_map(constructor->initial_map(), isolate);
15035     if (to_kind != initial_map->elements_kind()) {
15036       initial_map = Map::AsElementsKind(initial_map, to_kind);
15037       RETURN_IF_EMPTY_HANDLE(isolate, initial_map);
15038     }
15039
15040     // If we don't care to track arrays of to_kind ElementsKind, then
15041     // don't emit a memento for them.
15042     Handle<AllocationSite> allocation_site;
15043     if (AllocationSite::GetMode(to_kind) == TRACK_ALLOCATION_SITE) {
15044       allocation_site = site;
15045     }
15046
15047     array = Handle<JSArray>::cast(factory->NewJSObjectFromMap(
15048         initial_map, NOT_TENURED, true, allocation_site));
15049   } else {
15050     array = Handle<JSArray>::cast(factory->NewJSObject(constructor));
15051
15052     // We might need to transition to holey
15053     ElementsKind kind = constructor->initial_map()->elements_kind();
15054     if (holey && !IsFastHoleyElementsKind(kind)) {
15055       kind = GetHoleyElementsKind(kind);
15056       JSObject::TransitionElementsKind(array, kind);
15057     }
15058   }
15059
15060   factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
15061
15062   ElementsKind old_kind = array->GetElementsKind();
15063   RETURN_IF_EMPTY_HANDLE(isolate,
15064                          ArrayConstructInitializeElements(array, caller_args));
15065   if (!site.is_null() &&
15066       (old_kind != array->GetElementsKind() ||
15067        !can_use_type_feedback)) {
15068     // The arguments passed in caused a transition. This kind of complexity
15069     // can't be dealt with in the inlined hydrogen array constructor case.
15070     // We must mark the allocationsite as un-inlinable.
15071     site->SetDoNotInlineCall();
15072   }
15073   return *array;
15074 }
15075
15076
15077 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ArrayConstructor) {
15078   HandleScope scope(isolate);
15079   // If we get 2 arguments then they are the stub parameters (constructor, type
15080   // info).  If we get 4, then the first one is a pointer to the arguments
15081   // passed by the caller, and the last one is the length of the arguments
15082   // passed to the caller (redundant, but useful to check on the deoptimizer
15083   // with an assert).
15084   Arguments empty_args(0, NULL);
15085   bool no_caller_args = args.length() == 2;
15086   ASSERT(no_caller_args || args.length() == 4);
15087   int parameters_start = no_caller_args ? 0 : 1;
15088   Arguments* caller_args = no_caller_args
15089       ? &empty_args
15090       : reinterpret_cast<Arguments*>(args[0]);
15091   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15092   CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
15093 #ifdef DEBUG
15094   if (!no_caller_args) {
15095     CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
15096     ASSERT(arg_count == caller_args->length());
15097   }
15098 #endif
15099
15100   Handle<AllocationSite> site;
15101   if (!type_info.is_null() &&
15102       *type_info != isolate->heap()->undefined_value()) {
15103     site = Handle<AllocationSite>::cast(type_info);
15104     ASSERT(!site->SitePointsToLiteral());
15105   }
15106
15107   return ArrayConstructorCommon(isolate,
15108                                 constructor,
15109                                 site,
15110                                 caller_args);
15111 }
15112
15113
15114 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InternalArrayConstructor) {
15115   HandleScope scope(isolate);
15116   Arguments empty_args(0, NULL);
15117   bool no_caller_args = args.length() == 1;
15118   ASSERT(no_caller_args || args.length() == 3);
15119   int parameters_start = no_caller_args ? 0 : 1;
15120   Arguments* caller_args = no_caller_args
15121       ? &empty_args
15122       : reinterpret_cast<Arguments*>(args[0]);
15123   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15124 #ifdef DEBUG
15125   if (!no_caller_args) {
15126     CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
15127     ASSERT(arg_count == caller_args->length());
15128   }
15129 #endif
15130   return ArrayConstructorCommon(isolate,
15131                                 constructor,
15132                                 Handle<AllocationSite>::null(),
15133                                 caller_args);
15134 }
15135
15136
15137 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaxSmi) {
15138   return Smi::FromInt(Smi::kMaxValue);
15139 }
15140
15141
15142 #define RETURN_Float32x4_RESULT(value)                                         \
15143   Float32x4* float32x4;                                                        \
15144   MaybeObject* maybe = isolate->heap()->AllocateFloat32x4(value);              \
15145   if (!maybe->To(&float32x4)) return maybe;                                    \
15146   return float32x4;
15147
15148
15149 #define RETURN_Int32x4_RESULT(value)                                           \
15150   Int32x4* int32x4;                                                            \
15151   MaybeObject* maybe = isolate->heap()->AllocateInt32x4(value);                \
15152   if (!maybe->To(&int32x4)) return maybe;                                      \
15153   return int32x4;
15154
15155
15156 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateFloat32x4) {
15157   HandleScope scope(isolate);
15158   ASSERT(args.length() == 4);
15159   RUNTIME_ASSERT(args[0]->IsNumber());
15160   RUNTIME_ASSERT(args[1]->IsNumber());
15161   RUNTIME_ASSERT(args[2]->IsNumber());
15162   RUNTIME_ASSERT(args[3]->IsNumber());
15163
15164   float32x4_value_t value;
15165   value.storage[0] = static_cast<float>(args.number_at(0));
15166   value.storage[1] = static_cast<float>(args.number_at(1));
15167   value.storage[2] = static_cast<float>(args.number_at(2));
15168   value.storage[3] = static_cast<float>(args.number_at(3));
15169
15170   RETURN_Float32x4_RESULT(value);
15171 }
15172
15173
15174 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateInt32x4) {
15175   HandleScope scope(isolate);
15176   ASSERT(args.length() == 4);
15177   RUNTIME_ASSERT(args[0]->IsNumber());
15178   RUNTIME_ASSERT(args[1]->IsNumber());
15179   RUNTIME_ASSERT(args[2]->IsNumber());
15180   RUNTIME_ASSERT(args[3]->IsNumber());
15181
15182   int32x4_value_t value;
15183   value.storage[0] = NumberToInt32(args[0]);
15184   value.storage[1] = NumberToInt32(args[1]);
15185   value.storage[2] = NumberToInt32(args[2]);
15186   value.storage[3] = NumberToInt32(args[3]);
15187
15188   RETURN_Int32x4_RESULT(value);
15189 }
15190
15191
15192 // Used to convert between uint32_t and float32 without breaking strict
15193 // aliasing rules.
15194 union float32_uint32 {
15195   float f;
15196   uint32_t u;
15197   float32_uint32(float v) {
15198     f = v;
15199   }
15200   float32_uint32(uint32_t v) {
15201     u = v;
15202   }
15203 };
15204
15205
15206 RUNTIME_FUNCTION(MaybeObject*, Runtime_Float32x4GetSignMask) {
15207   HandleScope scope(isolate);
15208   ASSERT(args.length() == 1);
15209   CONVERT_ARG_CHECKED(Float32x4, self, 0);
15210   float32_uint32 x(self->x());
15211   float32_uint32 y(self->y());
15212   float32_uint32 z(self->z());
15213   float32_uint32 w(self->w());
15214   uint32_t mx = (x.u & 0x80000000) >> 31;
15215   uint32_t my = (y.u & 0x80000000) >> 31;
15216   uint32_t mz = (z.u & 0x80000000) >> 31;
15217   uint32_t mw = (w.u & 0x80000000) >> 31;
15218   uint32_t value = mx | (my << 1) | (mz << 2) | (mw << 3);
15219   return isolate->heap()->NumberFromUint32(value);
15220 }
15221
15222
15223
15224 RUNTIME_FUNCTION(MaybeObject*, Runtime_Int32x4GetSignMask) {
15225   HandleScope scope(isolate);
15226   ASSERT(args.length() == 1);
15227   CONVERT_ARG_CHECKED(Int32x4, self, 0);
15228   uint32_t mx = (self->x() & 0x80000000) >> 31;
15229   uint32_t my = (self->y() & 0x80000000) >> 31;
15230   uint32_t mz = (self->z() & 0x80000000) >> 31;
15231   uint32_t mw = (self->w() & 0x80000000) >> 31;
15232   uint32_t value = mx | (my << 1) | (mz << 2) | (mw << 3);
15233   return isolate->heap()->NumberFromUint32(value);
15234 }
15235
15236
15237 #define LANE_VALUE(VALUE, LANE) \
15238   VALUE->LANE()
15239
15240
15241 #define LANE_FLAG(VALUE, LANE)  \
15242   VALUE->LANE() != 0
15243
15244
15245 #define SIMD128_LANE_ACCESS_FUNCTIONS(V)                      \
15246   V(Float32x4, GetX, AllocateHeapNumber, x, LANE_VALUE)       \
15247   V(Float32x4, GetY, AllocateHeapNumber, y, LANE_VALUE)       \
15248   V(Float32x4, GetZ, AllocateHeapNumber, z, LANE_VALUE)       \
15249   V(Float32x4, GetW, AllocateHeapNumber, w, LANE_VALUE)       \
15250   V(Int32x4, GetX, NumberFromInt32, x, LANE_VALUE)            \
15251   V(Int32x4, GetY, NumberFromInt32, y, LANE_VALUE)            \
15252   V(Int32x4, GetZ, NumberFromInt32, z, LANE_VALUE)            \
15253   V(Int32x4, GetW, NumberFromInt32, w, LANE_VALUE)            \
15254   V(Int32x4, GetFlagX, ToBoolean, x, LANE_FLAG)               \
15255   V(Int32x4, GetFlagY, ToBoolean, y, LANE_FLAG)               \
15256   V(Int32x4, GetFlagZ, ToBoolean, z, LANE_FLAG)               \
15257   V(Int32x4, GetFlagW, ToBoolean, w, LANE_FLAG)
15258
15259
15260 #define DECLARE_SIMD_LANE_ACCESS_FUNCTION(                    \
15261     TYPE, NAME, HEAP_FUNCTION, LANE, ACCESS_FUNCTION)         \
15262 RUNTIME_FUNCTION(MaybeObject*, Runtime_##TYPE##NAME) {        \
15263   SealHandleScope shs(isolate);                               \
15264   ASSERT(args.length() == 1);                                 \
15265                                                               \
15266   CONVERT_ARG_CHECKED(TYPE, a, 0);                            \
15267                                                               \
15268   return isolate->heap()->HEAP_FUNCTION(                      \
15269       ACCESS_FUNCTION(a, LANE));                              \
15270 }
15271
15272
15273 SIMD128_LANE_ACCESS_FUNCTIONS(DECLARE_SIMD_LANE_ACCESS_FUNCTION)
15274
15275
15276 template<typename T>
15277 static inline T Neg(T a) {
15278   return -a;
15279 }
15280
15281
15282 template<typename T>
15283 static inline T Not(T a) {
15284   return ~a;
15285 }
15286
15287
15288 template<typename T>
15289 static inline T Reciprocal(T a) {
15290   UNIMPLEMENTED();
15291 }
15292
15293
15294 template<>
15295 inline float Reciprocal<float>(float a) {
15296   return 1.0f / a;
15297 }
15298
15299
15300 template<typename T>
15301 static inline T ReciprocalSqrt(T a) {
15302   UNIMPLEMENTED();
15303 }
15304
15305
15306 template<>
15307 inline float ReciprocalSqrt<float>(float a) {
15308   return sqrtf(1.0f / a);
15309 }
15310
15311
15312 template<typename T>
15313 static inline T Sqrt(T a) {
15314   UNIMPLEMENTED();
15315 }
15316
15317
15318 template<>
15319 inline float Sqrt<float>(float a) {
15320   return sqrtf(a);
15321 }
15322
15323
15324 #define SIMD128_UNARY_FUNCTIONS(V)                            \
15325   V(Float32x4, Abs)                                           \
15326   V(Float32x4, Neg)                                           \
15327   V(Float32x4, Reciprocal)                                    \
15328   V(Float32x4, ReciprocalSqrt)                                \
15329   V(Float32x4, Sqrt)                                          \
15330   V(Int32x4, Neg)                                             \
15331   V(Int32x4, Not)
15332
15333
15334 #define DECLARE_SIMD_UNARY_FUNCTION(TYPE, FUNCTION)           \
15335 RUNTIME_FUNCTION(MaybeObject*, Runtime_##TYPE##FUNCTION) {    \
15336   SealHandleScope shs(isolate);                               \
15337   ASSERT(args.length() == 1);                                 \
15338                                                               \
15339   CONVERT_ARG_CHECKED(TYPE, a, 0);                            \
15340                                                               \
15341   TYPE::value_t result;                                       \
15342   for (int i = 0; i < TYPE::kLanes; i++) {                    \
15343     result.storage[i] = FUNCTION(a->getAt(i));                \
15344   }                                                           \
15345                                                               \
15346   RETURN_##TYPE##_RESULT(result);                             \
15347 }
15348
15349
15350 SIMD128_UNARY_FUNCTIONS(DECLARE_SIMD_UNARY_FUNCTION)
15351
15352
15353 template<typename T1, typename T2>
15354 inline void BitsTo(T1 s, T2* t) {
15355   memcpy(t, &s, sizeof(T2));
15356 }
15357
15358
15359 template<typename T1, typename T2>
15360 inline void To(T1 s, T2* t) {
15361 }
15362
15363
15364 template<>
15365 inline void To<int32_t, float>(int32_t s, float* t) {
15366   *t = static_cast<float>(s);
15367 }
15368
15369
15370 template<>
15371 inline void To<float, int32_t>(float s, int32_t* t) {
15372   *t = DoubleToInt32(static_cast<double>(s));
15373 }
15374
15375
15376 #define SIMD128_CONVERSION_FUNCTIONS(V)                       \
15377   V(Float32x4, BitsTo, Int32x4)                               \
15378   V(Float32x4, To, Int32x4)                                   \
15379   V(Int32x4, BitsTo, Float32x4)                               \
15380   V(Int32x4, To, Float32x4)
15381
15382
15383 #define DECLARE_SIMD_CONVERSION_FUNCTION(                     \
15384     SOURCE_TYPE, FUNCTION, TARGET_TYPE)                       \
15385 RUNTIME_FUNCTION(MaybeObject*,                                \
15386     Runtime_##SOURCE_TYPE##FUNCTION##TARGET_TYPE) {           \
15387   SealHandleScope shs(isolate);                               \
15388   ASSERT(args.length() == 1);                                 \
15389                                                               \
15390   CONVERT_ARG_CHECKED(SOURCE_TYPE, a, 0);                     \
15391                                                               \
15392   TARGET_TYPE::value_t result;                                \
15393   for (int i = 0; i < SOURCE_TYPE::kLanes; i++) {             \
15394     FUNCTION(a->getAt(i), &result.storage[i]);                \
15395   }                                                           \
15396                                                               \
15397   RETURN_##TARGET_TYPE##_RESULT(result);                      \
15398 }
15399
15400
15401 SIMD128_CONVERSION_FUNCTIONS(DECLARE_SIMD_CONVERSION_FUNCTION)
15402
15403
15404 template<typename T>
15405 static inline T Add(T a, T b) {
15406   return a + b;
15407 }
15408
15409
15410 template<typename T>
15411 static inline T Div(T a, T b) {
15412   return a / b;
15413 }
15414
15415
15416 template<typename T>
15417 static inline T Mul(T a, T b) {
15418   return a * b;
15419 }
15420
15421
15422 template<typename T>
15423 static inline T Sub(T a, T b) {
15424   return a - b;
15425 }
15426
15427
15428 template<typename T>
15429 static inline int32_t Equal(T a, T b) {
15430   return a == b ? -1 : 0;
15431 }
15432
15433
15434 template<typename T>
15435 static inline int32_t NotEqual(T a, T b) {
15436   return a != b ? -1 : 0;
15437 }
15438
15439
15440 template<typename T>
15441 static inline int32_t GreaterThanOrEqual(T a, T b) {
15442   return a >= b ? -1 : 0;
15443 }
15444
15445
15446 template<typename T>
15447 static inline int32_t GreaterThan(T a, T b) {
15448   return a > b ? -1 : 0;
15449 }
15450
15451
15452 template<typename T>
15453 static inline int32_t LessThan(T a, T b) {
15454   return a < b ? -1 : 0;
15455 }
15456
15457
15458 template<typename T>
15459 static inline int32_t LessThanOrEqual(T a, T b) {
15460   return a <= b ? -1 : 0;
15461 }
15462
15463
15464 template<typename T>
15465 static inline T And(T a, T b) {
15466   return a & b;
15467 }
15468
15469
15470 template<typename T>
15471 static inline T Or(T a, T b) {
15472   return a | b;
15473 }
15474
15475
15476 template<typename T>
15477 static inline T Xor(T a, T b) {
15478   return a ^ b;
15479 }
15480
15481
15482 #define SIMD128_BINARY_FUNCTIONS(V)                           \
15483   V(Float32x4, Add, Float32x4)                                \
15484   V(Float32x4, Div, Float32x4)                                \
15485   V(Float32x4, Max, Float32x4)                                \
15486   V(Float32x4, Min, Float32x4)                                \
15487   V(Float32x4, Mul, Float32x4)                                \
15488   V(Float32x4, Sub, Float32x4)                                \
15489   V(Float32x4, Equal, Int32x4)                                \
15490   V(Float32x4, NotEqual, Int32x4)                             \
15491   V(Float32x4, GreaterThanOrEqual, Int32x4)                   \
15492   V(Float32x4, GreaterThan, Int32x4)                          \
15493   V(Float32x4, LessThan, Int32x4)                             \
15494   V(Float32x4, LessThanOrEqual, Int32x4)                      \
15495   V(Int32x4, Add, Int32x4)                                    \
15496   V(Int32x4, And, Int32x4)                                    \
15497   V(Int32x4, Mul, Int32x4)                                    \
15498   V(Int32x4, Or, Int32x4)                                     \
15499   V(Int32x4, Sub, Int32x4)                                    \
15500   V(Int32x4, Xor, Int32x4)                                    \
15501   V(Int32x4, Equal, Int32x4)                                  \
15502   V(Int32x4, GreaterThan, Int32x4)                            \
15503   V(Int32x4, LessThan, Int32x4)
15504
15505
15506 #define DECLARE_SIMD_BINARY_FUNCTION(                         \
15507     TYPE, FUNCTION, RETURN_TYPE)                              \
15508 RUNTIME_FUNCTION(MaybeObject*, Runtime_##TYPE##FUNCTION) {    \
15509   SealHandleScope shs(isolate);                               \
15510   ASSERT(args.length() == 2);                                 \
15511                                                               \
15512   CONVERT_ARG_CHECKED(TYPE, a, 0);                            \
15513   CONVERT_ARG_CHECKED(TYPE, b, 1);                            \
15514                                                               \
15515   RETURN_TYPE::value_t result;                                \
15516   for (int i = 0; i < TYPE::kLanes; i++) {                    \
15517     result.storage[i] = FUNCTION(a->getAt(i), b->getAt(i));   \
15518   }                                                           \
15519                                                               \
15520   RETURN_##RETURN_TYPE##_RESULT(result);                      \
15521 }
15522
15523
15524 SIMD128_BINARY_FUNCTIONS(DECLARE_SIMD_BINARY_FUNCTION)
15525
15526
15527 #define SIMD128_SHUFFLE_FUNCTIONS(V)                          \
15528   V(Float32x4)                                                \
15529   V(Int32x4)
15530
15531
15532 #define DECLARE_SIMD_SHUFFLE_FUNCTION(TYPE)                   \
15533 RUNTIME_FUNCTION(MaybeObject*, Runtime_##TYPE##Shuffle) {     \
15534   SealHandleScope shs(isolate);                               \
15535   ASSERT(args.length() == 2);                                 \
15536                                                               \
15537   CONVERT_ARG_CHECKED(TYPE, a, 0);                            \
15538   RUNTIME_ASSERT(args[1]->IsNumber());                        \
15539   uint32_t m = NumberToUint32(args[1]);                       \
15540                                                               \
15541   TYPE::value_t result;                                       \
15542   for (int i = 0; i < TYPE::kLanes; i++) {                    \
15543     result.storage[i] = a->getAt((m >> (i * 2)) & 0x3);       \
15544   }                                                           \
15545                                                               \
15546   RETURN_##TYPE##_RESULT(result);                             \
15547 }
15548
15549
15550 SIMD128_SHUFFLE_FUNCTIONS(DECLARE_SIMD_SHUFFLE_FUNCTION)
15551
15552
15553 RUNTIME_FUNCTION(MaybeObject*, Runtime_Float32x4Scale) {
15554   SealHandleScope shs(isolate);
15555   ASSERT(args.length() == 2);
15556
15557   CONVERT_ARG_CHECKED(Float32x4, self, 0);
15558   RUNTIME_ASSERT(args[1]->IsNumber());
15559
15560   float _s = static_cast<float>(args.number_at(1));
15561   float32x4_value_t result;
15562   result.storage[0] = self->x() * _s;
15563   result.storage[1] = self->y() * _s;
15564   result.storage[2] = self->z() * _s;
15565   result.storage[3] = self->w() * _s;
15566
15567   RETURN_Float32x4_RESULT(result);
15568 }
15569
15570
15571 #define ARG_TO_FLOAT32(x) \
15572   CONVERT_DOUBLE_ARG_CHECKED(t, 1); \
15573   float x = static_cast<float>(t);
15574
15575
15576 #define ARG_TO_INT32(x) \
15577   RUNTIME_ASSERT(args[1]->IsNumber()); \
15578   int32_t x = NumberToInt32(args[1]);
15579
15580
15581 #define ARG_TO_BOOLEAN(x) \
15582   CONVERT_BOOLEAN_ARG_CHECKED(flag, 1); \
15583   int32_t x = flag ? -1 : 0;
15584
15585 #define SIMD128_SET_LANE_FUNCTIONS(V)                         \
15586   V(Float32x4, WithX, ARG_TO_FLOAT32, 0)                      \
15587   V(Float32x4, WithY, ARG_TO_FLOAT32, 1)                      \
15588   V(Float32x4, WithZ, ARG_TO_FLOAT32, 2)                      \
15589   V(Float32x4, WithW, ARG_TO_FLOAT32, 3)                      \
15590   V(Int32x4, WithX, ARG_TO_INT32, 0)                          \
15591   V(Int32x4, WithY, ARG_TO_INT32, 1)                          \
15592   V(Int32x4, WithZ, ARG_TO_INT32, 2)                          \
15593   V(Int32x4, WithW, ARG_TO_INT32, 3)                          \
15594   V(Int32x4, WithFlagX, ARG_TO_BOOLEAN, 0)                    \
15595   V(Int32x4, WithFlagY, ARG_TO_BOOLEAN, 1)                    \
15596   V(Int32x4, WithFlagZ, ARG_TO_BOOLEAN, 2)                    \
15597   V(Int32x4, WithFlagW, ARG_TO_BOOLEAN, 3)
15598
15599
15600 #define DECLARE_SIMD_SET_LANE_FUNCTION(                       \
15601     TYPE, NAME, ARG_FUNCTION, LANE)                           \
15602 RUNTIME_FUNCTION(MaybeObject*, Runtime_##TYPE##NAME) {        \
15603   SealHandleScope shs(isolate);                               \
15604   ASSERT(args.length() == 2);                                 \
15605                                                               \
15606   CONVERT_ARG_CHECKED(TYPE, a, 0);                            \
15607   ARG_FUNCTION(value);                                        \
15608                                                               \
15609   TYPE::value_t result;                                       \
15610   for (int i = 0; i < TYPE::kLanes; i++) {                    \
15611     if (i != LANE)                                            \
15612       result.storage[i] = a->getAt(i);                        \
15613     else                                                      \
15614       result.storage[i] = value;                              \
15615   }                                                           \
15616                                                               \
15617   RETURN_##TYPE##_RESULT(result);                             \
15618 }
15619
15620
15621 SIMD128_SET_LANE_FUNCTIONS(DECLARE_SIMD_SET_LANE_FUNCTION)
15622
15623
15624 RUNTIME_FUNCTION(MaybeObject*, Runtime_Float32x4Clamp) {
15625   SealHandleScope shs(isolate);
15626   ASSERT(args.length() == 3);
15627
15628   CONVERT_ARG_CHECKED(Float32x4, self, 0);
15629   CONVERT_ARG_CHECKED(Float32x4, lo, 1);
15630   CONVERT_ARG_CHECKED(Float32x4, hi, 2);
15631
15632   float32x4_value_t result;
15633   float _x = self->x() > lo->x() ? self->x() : lo->x();
15634   float _y = self->y() > lo->y() ? self->y() : lo->y();
15635   float _z = self->z() > lo->z() ? self->z() : lo->z();
15636   float _w = self->w() > lo->w() ? self->w() : lo->w();
15637   result.storage[0] = _x > hi->x() ? hi->x() : _x;
15638   result.storage[1] = _y > hi->y() ? hi->y() : _y;
15639   result.storage[2] = _z > hi->z() ? hi->z() : _z;
15640   result.storage[3] = _w > hi->w() ? hi->w() : _w;
15641
15642   RETURN_Float32x4_RESULT(result);
15643 }
15644
15645
15646 RUNTIME_FUNCTION(MaybeObject*, Runtime_Float32x4ShuffleMix) {
15647   SealHandleScope shs(isolate);
15648   ASSERT(args.length() == 3);
15649
15650   CONVERT_ARG_CHECKED(Float32x4, first, 0);
15651   CONVERT_ARG_CHECKED(Float32x4, second, 1);
15652   RUNTIME_ASSERT(args[2]->IsNumber());
15653
15654   uint32_t m = NumberToUint32(args[2]);
15655   float32x4_value_t result;
15656   float data1[4] = { first->x(), first->y(), first->z(), first->w() };
15657   float data2[4] = { second->x(), second->y(), second->z(), second->w() };
15658   result.storage[0] = data1[m & 0x3];
15659   result.storage[1] = data1[(m >> 2) & 0x3];
15660   result.storage[2] = data2[(m >> 4) & 0x3];
15661   result.storage[3] = data2[(m >> 6) & 0x3];
15662
15663   RETURN_Float32x4_RESULT(result);
15664 }
15665
15666
15667 RUNTIME_FUNCTION(MaybeObject*, Runtime_Int32x4Select) {
15668   SealHandleScope shs(isolate);
15669   ASSERT(args.length() == 3);
15670
15671   CONVERT_ARG_CHECKED(Int32x4, self, 0);
15672   CONVERT_ARG_CHECKED(Float32x4, tv, 1);
15673   CONVERT_ARG_CHECKED(Float32x4, fv, 2);
15674
15675   uint32_t _maskX = self->x();
15676   uint32_t _maskY = self->y();
15677   uint32_t _maskZ = self->z();
15678   uint32_t _maskW = self->w();
15679   // Extract floats and interpret them as masks.
15680   float32_uint32 tvx(tv->x());
15681   float32_uint32 tvy(tv->y());
15682   float32_uint32 tvz(tv->z());
15683   float32_uint32 tvw(tv->w());
15684   float32_uint32 fvx(fv->x());
15685   float32_uint32 fvy(fv->y());
15686   float32_uint32 fvz(fv->z());
15687   float32_uint32 fvw(fv->w());
15688   // Perform select.
15689   float32_uint32 tempX((_maskX & tvx.u) | (~_maskX & fvx.u));
15690   float32_uint32 tempY((_maskY & tvy.u) | (~_maskY & fvy.u));
15691   float32_uint32 tempZ((_maskZ & tvz.u) | (~_maskZ & fvz.u));
15692   float32_uint32 tempW((_maskW & tvw.u) | (~_maskW & fvw.u));
15693
15694   float32x4_value_t result;
15695   result.storage[0] = tempX.f;
15696   result.storage[1] = tempY.f;
15697   result.storage[2] = tempZ.f;
15698   result.storage[3] = tempW.f;
15699
15700   RETURN_Float32x4_RESULT(result);
15701 }
15702
15703
15704 // ----------------------------------------------------------------------------
15705 // Implementation of Runtime
15706
15707 #define F(name, number_of_args, result_size)                             \
15708   { Runtime::k##name, Runtime::RUNTIME, #name,   \
15709     FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
15710
15711
15712 #define FH(name, number_of_args, result_size)                             \
15713   { Runtime::kHidden##name, Runtime::RUNTIME_HIDDEN, NULL,   \
15714     FUNCTION_ADDR(RuntimeHidden_##name), number_of_args, result_size },
15715
15716
15717 #define I(name, number_of_args, result_size)                             \
15718   { Runtime::kInline##name, Runtime::INLINE,     \
15719     "_" #name, NULL, number_of_args, result_size },
15720
15721
15722 #define IO(name, number_of_args, result_size) \
15723   { Runtime::kInlineOptimized##name, Runtime::INLINE_OPTIMIZED, \
15724     "_" #name, FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
15725
15726
15727 static const Runtime::Function kIntrinsicFunctions[] = {
15728   RUNTIME_FUNCTION_LIST(F)
15729   RUNTIME_HIDDEN_FUNCTION_LIST(FH)
15730   INLINE_FUNCTION_LIST(I)
15731   INLINE_OPTIMIZED_FUNCTION_LIST(IO)
15732 };
15733
15734 #undef IO
15735 #undef I
15736 #undef FH
15737 #undef F
15738
15739
15740 MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
15741                                                        Object* dictionary) {
15742   ASSERT(dictionary != NULL);
15743   ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
15744   for (int i = 0; i < kNumFunctions; ++i) {
15745     const char* name = kIntrinsicFunctions[i].name;
15746     if (name == NULL) continue;
15747     Object* name_string;
15748     { MaybeObject* maybe_name_string =
15749           heap->InternalizeUtf8String(name);
15750       if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
15751     }
15752     NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
15753     { MaybeObject* maybe_dictionary = name_dictionary->Add(
15754           String::cast(name_string),
15755           Smi::FromInt(i),
15756           PropertyDetails(NONE, NORMAL, Representation::None()));
15757       if (!maybe_dictionary->ToObject(&dictionary)) {
15758         // Non-recoverable failure.  Calling code must restart heap
15759         // initialization.
15760         return maybe_dictionary;
15761       }
15762     }
15763   }
15764   return dictionary;
15765 }
15766
15767
15768 const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
15769   Heap* heap = name->GetHeap();
15770   int entry = heap->intrinsic_function_names()->FindEntry(*name);
15771   if (entry != kNotFound) {
15772     Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
15773     int function_index = Smi::cast(smi_index)->value();
15774     return &(kIntrinsicFunctions[function_index]);
15775   }
15776   return NULL;
15777 }
15778
15779
15780 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
15781   return &(kIntrinsicFunctions[static_cast<int>(id)]);
15782 }
15783
15784
15785 void Runtime::PerformGC(Object* result, Isolate* isolate) {
15786   Failure* failure = Failure::cast(result);
15787   if (failure->IsRetryAfterGC()) {
15788     if (isolate->heap()->new_space()->AddFreshPage()) {
15789       return;
15790     }
15791
15792     // Try to do a garbage collection; ignore it if it fails. The C
15793     // entry stub will throw an out-of-memory exception in that case.
15794     isolate->heap()->CollectGarbage(failure->allocation_space(),
15795                                     "Runtime::PerformGC");
15796   } else {
15797     // Handle last resort GC and make sure to allow future allocations
15798     // to grow the heap without causing GCs (if possible).
15799     isolate->counters()->gc_last_resort_from_js()->Increment();
15800     isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
15801                                        "Runtime::PerformGC");
15802   }
15803 }
15804
15805
15806 } }  // namespace v8::internal